00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 #include "TGButton.h"
00092 #include "TGWidget.h"
00093 #include "TGPicture.h"
00094 #include "TGToolTip.h"
00095 #include "TGButtonGroup.h"
00096 #include "TGResourcePool.h"
00097 #include "Riostream.h"
00098 #include "TSystem.h"
00099 #include "TImage.h"
00100 #include "TEnv.h"
00101 #include "TClass.h"
00102 #include "TGMenu.h"
00103 #include "KeySymbols.h"
00104
00105 const TGGC *TGButton::fgHibckgndGC = 0;
00106 const TGGC *TGButton::fgDefaultGC = 0;
00107
00108 const TGFont *TGTextButton::fgDefaultFont = 0;
00109
00110 const TGFont *TGCheckButton::fgDefaultFont = 0;
00111 const TGGC *TGCheckButton::fgDefaultGC = 0;
00112
00113 const TGFont *TGRadioButton::fgDefaultFont = 0;
00114 const TGGC *TGRadioButton::fgDefaultGC = 0;
00115
00116 Window_t TGButton::fgReleaseBtn = 0;
00117
00118 ClassImp(TGButton)
00119 ClassImp(TGTextButton)
00120 ClassImp(TGPictureButton)
00121 ClassImp(TGCheckButton)
00122 ClassImp(TGRadioButton)
00123 ClassImp(TGSplitButton)
00124
00125
00126 TGButton::TGButton(const TGWindow *p, Int_t id, GContext_t norm, UInt_t options)
00127 : TGFrame(p, 1, 1, options)
00128 {
00129
00130
00131 fWidgetId = id;
00132 fWidgetFlags = kWidgetWantFocus;
00133 fMsgWindow = p;
00134 fUserData = 0;
00135 fTip = 0;
00136 fGroup = 0;
00137
00138 fNormGC = norm;
00139 fState = kButtonUp;
00140 fStayDown = kFALSE;
00141 fWidgetFlags = kWidgetIsEnabled;
00142
00143 if (p && p->IsA()->InheritsFrom(TGButtonGroup::Class())) {
00144 TGButtonGroup *bg = (TGButtonGroup*) p;
00145 bg->Insert(this, id);
00146 }
00147
00148 gVirtualX->GrabButton(fId, kButton1, kAnyModifier,
00149 kButtonPressMask | kButtonReleaseMask,
00150 kNone, kNone);
00151
00152 AddInput(kEnterWindowMask | kLeaveWindowMask);
00153 SetWindowName();
00154 }
00155
00156
00157 TGButton::~TGButton()
00158 {
00159
00160
00161
00162 if (fGroup) {
00163 fGroup->Remove(this);
00164 fGroup = 0;
00165 }
00166
00167 if (fTip) delete fTip;
00168 }
00169
00170
00171 void TGButton::SetState(EButtonState state, Bool_t emit)
00172 {
00173
00174
00175 Bool_t was = !IsDown();
00176
00177 if (state == kButtonDisabled)
00178 fWidgetFlags &= ~kWidgetIsEnabled;
00179 else
00180 fWidgetFlags |= kWidgetIsEnabled;
00181 if (state != fState) {
00182 switch (state) {
00183 case kButtonEngaged:
00184 case kButtonDown:
00185 fOptions &= ~kRaisedFrame;
00186 fOptions |= kSunkenFrame;
00187 break;
00188 case kButtonDisabled:
00189 case kButtonUp:
00190 fOptions &= ~kSunkenFrame;
00191 fOptions |= kRaisedFrame;
00192 break;
00193 }
00194 fState = state;
00195 DoRedraw();
00196 if (emit || fGroup) EmitSignals(was);
00197 }
00198 }
00199
00200
00201 void TGButton::SetDown(Bool_t on, Bool_t emit)
00202 {
00203
00204
00205
00206 if (GetState() == kButtonDisabled) return;
00207
00208 SetState(on ? kButtonDown : kButtonUp, emit);
00209 }
00210
00211
00212 void TGButton::SetGroup(TGButtonGroup *group)
00213 {
00214
00215
00216 fGroup = group;
00217 }
00218
00219
00220 Bool_t TGButton::HandleButton(Event_t *event)
00221 {
00222
00223
00224 Bool_t click = kFALSE;
00225
00226 if (fTip) fTip->Hide();
00227
00228 if (fState == kButtonDisabled) return kTRUE;
00229
00230 Bool_t in = (event->fX >= 0) && (event->fY >= 0) &&
00231 (event->fX <= (Int_t)fWidth) && (event->fY <= (Int_t)fHeight);
00232
00233
00234
00235 if (event->fType == kButtonPress) {
00236 fgReleaseBtn = 0;
00237
00238 if (fState == kButtonEngaged) {
00239 return kTRUE;
00240 }
00241 if (in) SetState(kButtonDown, kTRUE);
00242 } else {
00243 if (fState == kButtonEngaged) {
00244 if (in) SetState(kButtonUp, kTRUE);
00245 click = kTRUE;
00246 } else {
00247 click = (fState == kButtonDown) && in;
00248 if (click && fStayDown) {
00249 if (in) {
00250 SetState(kButtonEngaged, kTRUE);
00251 fgReleaseBtn = 0;
00252 }
00253 } else {
00254 if (in) {
00255 SetState(kButtonUp, kTRUE);
00256 fgReleaseBtn = fId;
00257 }
00258 }
00259 }
00260 }
00261 if (click) {
00262 SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
00263 (Long_t) fUserData);
00264 fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
00265 (Long_t) fUserData);
00266 }
00267
00268 return kTRUE;
00269 }
00270
00271
00272 void TGButton::EmitSignals(Bool_t was)
00273 {
00274
00275
00276 Bool_t now = !IsDown();
00277
00278
00279 if (was && !now) {
00280 Pressed();
00281 if (fStayDown) Clicked();
00282 }
00283 if (!was && now) {
00284 Released();
00285 Clicked();
00286 }
00287 if ((was != now) && IsToggleButton()) Toggled(!now);
00288 }
00289
00290
00291 Bool_t TGButton::HandleCrossing(Event_t *event)
00292 {
00293
00294
00295 if (fTip) {
00296 if (event->fType == kEnterNotify)
00297 fTip->Reset();
00298 else
00299 fTip->Hide();
00300 }
00301
00302 if ((fgDbw != event->fWindow) || (fgReleaseBtn == event->fWindow)) return kTRUE;
00303
00304 if (!(event->fState & (kButton1Mask | kButton2Mask | kButton3Mask)))
00305 return kTRUE;
00306
00307 if (fState == kButtonEngaged || fState == kButtonDisabled) return kTRUE;
00308
00309 if (event->fType == kLeaveNotify) {
00310 fgReleaseBtn = fId;
00311 SetState(kButtonUp, kFALSE);
00312 }
00313 return kTRUE;
00314 }
00315
00316
00317 void TGButton::SetToolTipText(const char *text, Long_t delayms)
00318 {
00319
00320
00321
00322
00323 if (fTip) {
00324 delete fTip;
00325 fTip = 0;
00326 }
00327
00328 if (text && strlen(text))
00329 fTip = new TGToolTip(fClient->GetDefaultRoot(), this, text, delayms);
00330 }
00331
00332
00333 void TGButton::SetEnabled(Bool_t e)
00334 {
00335
00336
00337 SetState(e ? kButtonUp : kButtonDisabled);
00338
00339 if (e) fWidgetFlags |= kWidgetIsEnabled;
00340 else fWidgetFlags &= ~kWidgetIsEnabled;
00341 }
00342
00343
00344 const TGGC &TGButton::GetDefaultGC()
00345 {
00346
00347
00348 if (!fgDefaultGC)
00349 fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
00350 return *fgDefaultGC;
00351 }
00352
00353
00354 const TGGC &TGButton::GetHibckgndGC()
00355 {
00356
00357
00358 if (!fgHibckgndGC) {
00359 GCValues_t gval;
00360 gval.fMask = kGCForeground | kGCBackground | kGCTile |
00361 kGCFillStyle | kGCGraphicsExposures;
00362 gval.fForeground = gClient->GetResourcePool()->GetFrameHiliteColor();
00363 gval.fBackground = gClient->GetResourcePool()->GetFrameBgndColor();
00364 gval.fFillStyle = kFillTiled;
00365 gval.fTile = gClient->GetResourcePool()->GetCheckeredPixmap();
00366 gval.fGraphicsExposures = kFALSE;
00367 fgHibckgndGC = gClient->GetGC(&gval, kTRUE);
00368 }
00369 return *fgHibckgndGC;
00370 }
00371
00372
00373
00374 TGTextButton::TGTextButton(const TGWindow *p, TGHotString *s, Int_t id,
00375 GContext_t norm, FontStruct_t font,
00376 UInt_t options) : TGButton(p, id, norm, options)
00377 {
00378
00379
00380
00381 fLabel = s;
00382 fFontStruct = font;
00383
00384 Init();
00385 }
00386
00387
00388 TGTextButton::TGTextButton(const TGWindow *p, const char *s, Int_t id,
00389 GContext_t norm, FontStruct_t font,
00390 UInt_t options) : TGButton(p, id, norm, options)
00391 {
00392
00393
00394 fLabel = new TGHotString(!p && !s ? GetName() : s);
00395 fFontStruct = font;
00396
00397 Init();
00398 }
00399
00400
00401 TGTextButton::TGTextButton(const TGWindow *p, const char *s, const char *cmd,
00402 Int_t id, GContext_t norm, FontStruct_t font,
00403 UInt_t options) : TGButton(p, id, norm, options)
00404 {
00405
00406
00407 fLabel = new TGHotString(s);
00408 fFontStruct = font;
00409 fCommand = cmd;
00410
00411 Init();
00412 }
00413
00414
00415 void TGTextButton::Init()
00416 {
00417
00418
00419 int hotchar;
00420
00421 fTMode = kTextCenterX | kTextCenterY;
00422 fHKeycode = 0;
00423 fHasOwnFont = kFALSE;
00424 fPrevStateOn =
00425 fStateOn = kFALSE;
00426 fWrapLength = -1;
00427 fMLeft = fMRight = fMTop = fMBottom = 0;
00428
00429 TGFont *font = fClient->GetFontPool()->FindFont(fFontStruct);
00430 if (!font) {
00431 font = fClient->GetFontPool()->GetFont(fgDefaultFont);
00432 fFontStruct = font->GetFontStruct();
00433 }
00434
00435 fTLayout = font->ComputeTextLayout(fLabel->GetString(), fLabel->GetLength(),
00436 fWrapLength, kTextLeft, 0,
00437 &fTWidth, &fTHeight);
00438
00439 Resize();
00440 fWidth = fTWidth;
00441 fHeight = fTHeight;
00442
00443 if ((hotchar = fLabel->GetHotChar()) != 0) {
00444 if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0) {
00445 const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
00446 main->BindKey(this, fHKeycode, kKeyMod1Mask);
00447 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
00448 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
00449 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
00450
00451 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
00452 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
00453 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
00454 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
00455 }
00456 }
00457 SetWindowAttributes_t wattr;
00458 wattr.fMask = kWAWinGravity | kWABitGravity;
00459 wattr.fBitGravity = 5;
00460 wattr.fWinGravity = 1;
00461 gVirtualX->ChangeWindowAttributes(fId, &wattr);
00462
00463 SetWindowName();
00464 }
00465
00466
00467 TGTextButton::~TGTextButton()
00468 {
00469
00470
00471 if (fHKeycode && (fParent->MustCleanup() != kDeepCleanup)) {
00472 const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
00473 main->RemoveBind(this, fHKeycode, kKeyMod1Mask);
00474 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
00475 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
00476 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
00477
00478 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
00479 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
00480 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
00481 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
00482 }
00483 if (fLabel) delete fLabel;
00484 if (fHasOwnFont) {
00485 TGGCPool *pool = fClient->GetGCPool();
00486 TGGC *gc = pool->FindGC(fNormGC);
00487 pool->FreeGC(gc);
00488 }
00489
00490 delete fTLayout;
00491 }
00492
00493
00494 void TGTextButton::Layout()
00495 {
00496
00497
00498 delete fTLayout;
00499
00500 TGFont *font = fClient->GetFontPool()->FindFont(fFontStruct);
00501 if (!font) {
00502 font = fClient->GetFontPool()->GetFont(fgDefaultFont);
00503 fFontStruct = font->GetFontStruct();
00504 }
00505
00506 fTLayout = font->ComputeTextLayout(fLabel->GetString(), fLabel->GetLength(),
00507 fWrapLength, kTextLeft, 0,
00508 &fTWidth, &fTHeight);
00509 fClient->NeedRedraw(this);
00510 }
00511
00512
00513 void TGTextButton::SetText(TGHotString *new_label)
00514 {
00515
00516
00517 int hotchar;
00518 const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
00519
00520 if (fLabel) {
00521 if (fHKeycode) {
00522 main->RemoveBind(this, fHKeycode, kKeyMod1Mask);
00523 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
00524 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
00525 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
00526
00527 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
00528 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
00529 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
00530 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
00531 }
00532 delete fLabel;
00533 }
00534
00535 fLabel = new_label;
00536 if ((hotchar = fLabel->GetHotChar()) != 0) {
00537 if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0)
00538 main->BindKey(this, fHKeycode, kKeyMod1Mask);
00539 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
00540 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
00541 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
00542
00543 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
00544 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
00545 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
00546 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
00547 }
00548
00549 Layout();
00550 }
00551
00552
00553 void TGTextButton::SetText(const TString &new_label)
00554 {
00555
00556
00557 SetText(new TGHotString(new_label));
00558 }
00559
00560
00561 void TGTextButton::SetTextJustify(Int_t mode)
00562 {
00563
00564
00565
00566
00567 fTMode = mode;
00568
00569 SetWindowAttributes_t wattr;
00570 wattr.fMask = kWAWinGravity | kWABitGravity;
00571 wattr.fWinGravity = 1;
00572
00573 switch (mode) {
00574 case kTextTop | kTextLeft:
00575 wattr.fBitGravity = 1;
00576 break;
00577 case kTextTop | kTextCenterX:
00578 case kTextTop:
00579 wattr.fBitGravity = 2;
00580 break;
00581 case kTextTop | kTextRight:
00582 wattr.fBitGravity = 3;
00583 break;
00584 case kTextLeft | kTextCenterY:
00585 case kTextLeft:
00586 wattr.fBitGravity = 4;
00587 break;
00588 case kTextCenterY | kTextCenterX:
00589 wattr.fBitGravity = 5;
00590 break;
00591 case kTextRight | kTextCenterY:
00592 case kTextRight:
00593 wattr.fBitGravity = 6;
00594 break;
00595 case kTextBottom | kTextLeft:
00596 wattr.fBitGravity = 7;
00597 break;
00598 case kTextBottom | kTextCenterX:
00599 case kTextBottom:
00600 wattr.fBitGravity = 8;
00601 break;
00602 case kTextBottom | kTextRight:
00603 wattr.fBitGravity = 9;
00604 break;
00605 default:
00606 wattr.fBitGravity = 5;
00607 break;
00608 }
00609
00610 gVirtualX->ChangeWindowAttributes(fId, &wattr);
00611 Layout();
00612 }
00613
00614
00615 void TGTextButton::DoRedraw()
00616 {
00617
00618
00619 int x, y;
00620
00621 TGFrame::DoRedraw();
00622
00623 if (fTMode & kTextLeft) {
00624 x = fMLeft + 4;
00625 } else if (fTMode & kTextRight) {
00626 x = fWidth - fTWidth - fMRight - 4;
00627 } else {
00628 x = (fWidth - fTWidth + fMLeft - fMRight) >> 1;
00629 }
00630
00631 if (fTMode & kTextTop) {
00632 y = fMTop + 3;
00633 } else if (fTMode & kTextBottom) {
00634 y = fHeight - fTHeight - fMBottom - 3;
00635 } else {
00636 y = (fHeight - fTHeight + fMTop - fMBottom) >> 1;
00637 }
00638
00639 if (fState == kButtonDown || fState == kButtonEngaged) { ++x; ++y; }
00640 if (fState == kButtonEngaged) {
00641 gVirtualX->FillRectangle(fId, GetHibckgndGC()(), 2, 2, fWidth-4, fHeight-4);
00642 gVirtualX->DrawLine(fId, GetHilightGC()(), 2, 2, fWidth-3, 2);
00643 }
00644
00645 Int_t hotpos = fLabel->GetHotPos();
00646
00647 if (fState == kButtonDisabled) {
00648 TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
00649 TGGC *gc = pool->FindGC(fNormGC);
00650 Pixel_t fore = gc->GetForeground();
00651 Pixel_t hi = GetHilightGC().GetForeground();
00652 Pixel_t sh = GetShadowGC().GetForeground();
00653
00654 gc->SetForeground(hi);
00655 fTLayout->DrawText(fId, gc->GetGC(), x + 1, y + 1, 0, -1);
00656 if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x + 1, y + 1, hotpos - 1);
00657
00658 gc->SetForeground(sh);
00659 fTLayout->DrawText(fId, gc->GetGC(), x, y, 0, -1);
00660 if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x, y, hotpos - 1);
00661 gc->SetForeground(fore);
00662 } else {
00663 fTLayout->DrawText(fId, fNormGC, x, y, 0, -1);
00664 if (hotpos) fTLayout->UnderlineChar(fId, fNormGC, x, y, hotpos - 1);
00665 }
00666 }
00667
00668
00669 Bool_t TGTextButton::HandleKey(Event_t *event)
00670 {
00671
00672
00673 Bool_t click = kFALSE;
00674 Bool_t was = !IsDown();
00675
00676 if (event->fType == kGKeyPress) {
00677 gVirtualX->SetKeyAutoRepeat(kFALSE);
00678 } else {
00679 gVirtualX->SetKeyAutoRepeat(kTRUE);
00680 }
00681
00682 if (fTip && event->fType == kGKeyPress) fTip->Hide();
00683
00684 if (fState == kButtonDisabled) return kTRUE;
00685
00686
00687
00688
00689 if ((event->fType == kGKeyPress) && (event->fState & kKeyMod1Mask)) {
00690 if (fState == kButtonEngaged) return kTRUE;
00691 SetState(kButtonDown);
00692 } else if ((event->fType == kKeyRelease) && (event->fState & kKeyMod1Mask)) {
00693 if (fState == kButtonEngaged ) return kTRUE;
00694 click = (fState == kButtonDown);
00695 if (click && fStayDown) {
00696 SetState(kButtonEngaged);
00697 } else {
00698 SetState(kButtonUp);
00699 }
00700 }
00701 if (click) {
00702 SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
00703 (Long_t) fUserData);
00704 fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
00705 (Long_t) fUserData);
00706 }
00707 EmitSignals(was);
00708
00709 return kTRUE;
00710 }
00711
00712
00713 TGDimension TGTextButton::GetDefaultSize() const
00714 {
00715
00716
00717 UInt_t w = GetOptions() & kFixedWidth ? fWidth : fTWidth + fMLeft + fMRight + 8;
00718 UInt_t h = GetOptions() & kFixedHeight ? fHeight : fTHeight + fMTop + fMBottom + 7;
00719 return TGDimension(w, h);
00720 }
00721
00722
00723 FontStruct_t TGTextButton::GetDefaultFontStruct()
00724 {
00725
00726
00727 if (!fgDefaultFont)
00728 fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
00729 return fgDefaultFont->GetFontStruct();
00730 }
00731
00732
00733 void TGTextButton::SetFont(FontStruct_t font, Bool_t global)
00734 {
00735
00736
00737
00738 if (font != fFontStruct) {
00739 FontH_t v = gVirtualX->GetFontHandle(font);
00740 if (!v) return;
00741
00742 fFontStruct = font;
00743 TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
00744 TGGC *gc = pool->FindGC(fNormGC);
00745
00746 if (!global) {
00747 gc = pool->GetGC((GCValues_t*)gc->GetAttributes(), kTRUE);
00748 fHasOwnFont = kTRUE;
00749 }
00750
00751 gc->SetFont(v);
00752
00753 fNormGC = gc->GetGC();
00754 Layout();
00755 }
00756 }
00757
00758
00759 void TGTextButton::SetFont(const char *fontName, Bool_t global)
00760 {
00761
00762
00763
00764 TGFont *font = fClient->GetFont(fontName);
00765 if (font) {
00766 SetFont(font->GetFontStruct(), global);
00767 }
00768 }
00769
00770
00771 void TGTextButton::SetTextColor(Pixel_t color, Bool_t global)
00772 {
00773
00774
00775
00776 TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
00777 TGGC *gc = pool->FindGC(fNormGC);
00778
00779 if (!global) {
00780 gc = pool->GetGC((GCValues_t*)gc->GetAttributes(), kTRUE);
00781 fHasOwnFont = kTRUE;
00782 }
00783
00784 gc->SetForeground(color);
00785 fNormGC = gc->GetGC();
00786 fClient->NeedRedraw(this);
00787 }
00788
00789
00790 Bool_t TGTextButton::HasOwnFont() const
00791 {
00792
00793
00794
00795 return fHasOwnFont;
00796 }
00797
00798
00799 TGPictureButton::TGPictureButton(const TGWindow *p, const TGPicture *pic,
00800 Int_t id, GContext_t norm, UInt_t option) : TGButton(p, id, norm, option)
00801 {
00802
00803
00804
00805
00806 if (!pic) {
00807 Error("TGPictureButton", "pixmap not found for button %d", id);
00808 fPic = fClient->GetPicture("mb_question_s.xpm");
00809 } else {
00810 fPic = pic;
00811 }
00812
00813 if (fPic) {
00814 fTWidth = fPic->GetWidth();
00815 fTHeight = fPic->GetHeight();
00816
00817 Resize(fTWidth + (fBorderWidth << 1) + fBorderWidth + 1,
00818 fTHeight + (fBorderWidth << 1) + fBorderWidth);
00819 }
00820 fPicD = 0;
00821 fOwnDisabledPic = kFALSE;
00822 SetWindowName();
00823 }
00824
00825
00826 TGPictureButton::TGPictureButton(const TGWindow *p, const TGPicture *pic,
00827 const char *cmd, Int_t id, GContext_t norm, UInt_t option)
00828 : TGButton(p, id, norm, option)
00829 {
00830
00831
00832
00833
00834
00835 if (!pic) {
00836 Error("TGPictureButton", "pixmap not found for button\n%s",
00837 cmd ? cmd : "");
00838 fPic = fClient->GetPicture("mb_question_s.xpm");
00839 } else {
00840 fPic = pic;
00841 }
00842
00843 fCommand = cmd;
00844
00845 if (fPic) {
00846 fTWidth = fPic->GetWidth();
00847 fTHeight = fPic->GetHeight();
00848
00849 Resize(fTWidth + (fBorderWidth << 1) + fBorderWidth + 1,
00850 fTHeight + (fBorderWidth << 1) + fBorderWidth);
00851 }
00852 fPicD = 0;
00853 fOwnDisabledPic = kFALSE;
00854 SetWindowName();
00855 }
00856
00857
00858 TGPictureButton::TGPictureButton(const TGWindow *p, const char *pic,
00859 Int_t id, GContext_t norm, UInt_t option) : TGButton(p, id, norm, option)
00860 {
00861
00862
00863 if (!pic || !strlen(pic)) {
00864 if (p) Error("TGPictureButton", "pixmap not found for button");
00865 fPic = fClient->GetPicture("mb_question_s.xpm");
00866 } else {
00867 fPic = fClient->GetPicture(pic);
00868 }
00869
00870 if (fPic) {
00871 fTWidth = fPic->GetWidth();
00872 fTHeight = fPic->GetHeight();
00873
00874 Resize(fTWidth + (fBorderWidth << 1) + fBorderWidth + 1,
00875 fTHeight + (fBorderWidth << 1) + fBorderWidth);
00876 }
00877 fPicD = 0;
00878 fOwnDisabledPic = kFALSE;
00879 SetWindowName();
00880 }
00881
00882
00883 TGPictureButton::~TGPictureButton()
00884 {
00885
00886
00887 if (fOwnDisabledPic) fClient->FreePicture(fPicD);
00888 }
00889
00890
00891 void TGPictureButton::SetPicture(const TGPicture *new_pic)
00892 {
00893
00894
00895
00896
00897 if (!new_pic) {
00898 Error("SetPicture", "pixmap not found for button %d\n%s",
00899 fWidgetId, fCommand.Data());
00900 return;
00901 }
00902
00903 fPic = new_pic;
00904
00905 if (fState == kButtonDisabled) {
00906 fClient->FreePicture(fPicD);
00907 fPicD = 0;
00908 }
00909
00910 fTWidth = fPic->GetWidth();
00911 fTHeight = fPic->GetHeight();
00912
00913 fClient->NeedRedraw(this);
00914 }
00915
00916
00917 void TGPictureButton::DoRedraw()
00918 {
00919
00920
00921 if (!fPic) {
00922 TGFrame::DoRedraw();
00923 return;
00924 }
00925
00926 int x = (fWidth - fTWidth) >> 1;
00927 int y = (fHeight - fTHeight) >> 1;
00928
00929 TGFrame::DoRedraw();
00930 if (fState == kButtonDown || fState == kButtonEngaged) { ++x; ++y; }
00931 if (fState == kButtonEngaged) {
00932 gVirtualX->FillRectangle(fId, GetHibckgndGC()(), 2, 2, fWidth-4, fHeight-4);
00933 gVirtualX->DrawLine(fId, GetHilightGC()(), 2, 2, fWidth-3, 2);
00934 }
00935
00936 const TGPicture *pic = fPic;
00937 if (fState == kButtonDisabled) {
00938 if (!fPicD) CreateDisabledPicture();
00939 pic = fPicD ? fPicD : fPic;
00940 }
00941
00942 pic->Draw(fId, fNormGC, x, y);
00943 }
00944
00945
00946 void TGPictureButton::CreateDisabledPicture()
00947 {
00948
00949
00950 TImage *img = TImage::Create();
00951 TImage *img2 = TImage::Create();
00952
00953 TString back = gEnv->GetValue("Gui.BackgroundColor", "#c0c0c0");
00954 img2->FillRectangle(back.Data(), 0, 0, fPic->GetWidth(), fPic->GetHeight());
00955 img->SetImage(fPic->GetPicture(), fPic->GetMask());
00956 Pixmap_t mask = img->GetMask();
00957 img2->Merge(img, "overlay");
00958
00959 TString name = "disbl_";
00960 name += fPic->GetName();
00961 fPicD = fClient->GetPicturePool()->GetPicture(name.Data(), img2->GetPixmap(),
00962 mask);
00963 fOwnDisabledPic = kTRUE;
00964 delete img;
00965 delete img2;
00966 }
00967
00968
00969 void TGPictureButton::SetDisabledPicture(const TGPicture *pic)
00970 {
00971
00972
00973 if (!pic) return;
00974
00975 if (fOwnDisabledPic && fPicD) fClient->FreePicture(fPicD);
00976 fPicD = pic;
00977 ((TGPicture*)pic)->AddReference();
00978 fOwnDisabledPic = kFALSE;
00979 }
00980
00981
00982 TGCheckButton::TGCheckButton(const TGWindow *p, TGHotString *s, Int_t id,
00983 GContext_t norm, FontStruct_t font, UInt_t option)
00984 : TGTextButton(p, s, id, norm, font, option)
00985 {
00986
00987
00988
00989 Init();
00990 }
00991
00992
00993 TGCheckButton::TGCheckButton(const TGWindow *p, const char *s, Int_t id,
00994 GContext_t norm, FontStruct_t font, UInt_t option)
00995 : TGTextButton(p, s, id, norm, font, option)
00996 {
00997
00998
00999 Init();
01000 }
01001
01002
01003 TGCheckButton::TGCheckButton(const TGWindow *p, const char *s, const char *cmd,
01004 Int_t id, GContext_t norm, FontStruct_t font,
01005 UInt_t option) : TGTextButton(p, s, cmd, id, norm, font, option)
01006 {
01007
01008
01009 Init();
01010 }
01011
01012
01013 void TGCheckButton::Init()
01014 {
01015
01016
01017 fPrevState =
01018 fState = kButtonUp;
01019 fHKeycode = 0;
01020
01021 fOn = fClient->GetPicture("checked_t.xpm");
01022 fOff = fClient->GetPicture("unchecked_t.xpm");
01023 fDisOn = fClient->GetPicture("checked_dis_t.xpm");
01024 fDisOff = fClient->GetPicture("unchecked_dis_t.xpm");
01025
01026 Resize();
01027
01028 if (!fOn) {
01029 Error("TGCheckButton", "checked_t.xpm not found");
01030 } else if (!fOff) {
01031 Error("TGCheckButton", "unchecked_t.xpm not found");
01032 } else if (!fDisOn) {
01033 Error("TGCheckButton", "checked_dis_t.xpm not found");
01034 } else if (!fDisOff) {
01035 Error("TGCheckButton", "unchecked_dis_t.xpm not found");
01036 }
01037 int hotchar;
01038
01039 if ((hotchar = fLabel->GetHotChar()) != 0) {
01040 if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0) {
01041 const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
01042 main->BindKey(this, fHKeycode, kKeyMod1Mask);
01043 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
01044 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
01045 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
01046
01047 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
01048 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
01049 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
01050 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
01051 }
01052 }
01053 SetWindowName();
01054 }
01055
01056
01057 TGCheckButton::~TGCheckButton()
01058 {
01059
01060
01061 if (fOn) fClient->FreePicture(fOn);
01062 if (fOff) fClient->FreePicture(fOff);
01063 if (fDisOn) fClient->FreePicture(fDisOn);
01064 if (fDisOff) fClient->FreePicture(fDisOff);
01065 }
01066
01067
01068 TGDimension TGCheckButton::GetDefaultSize() const
01069 {
01070
01071
01072 UInt_t w = !fTWidth ? fOff->GetWidth() : fTWidth + fOff->GetWidth() + 9;
01073 UInt_t h = !fTHeight ? fOff->GetHeight() : fTHeight + 2;
01074
01075 w = GetOptions() & kFixedWidth ? fWidth : w;
01076 h = GetOptions() & kFixedHeight ? fHeight : h;
01077
01078 return TGDimension(w, h);
01079 }
01080
01081
01082 void TGCheckButton::SetState(EButtonState state, Bool_t emit)
01083 {
01084
01085
01086 if (state == kButtonDisabled)
01087 fWidgetFlags &= ~kWidgetIsEnabled;
01088 else
01089 fWidgetFlags |= kWidgetIsEnabled;
01090 PSetState(state, emit);
01091 }
01092
01093
01094 void TGCheckButton::EmitSignals(Bool_t )
01095 {
01096
01097
01098 if (fState == kButtonUp) Released();
01099 if (fState == kButtonDown) Pressed();
01100 Clicked();
01101 Toggled(fStateOn);
01102 }
01103
01104
01105 void TGCheckButton::PSetState(EButtonState state, Bool_t emit)
01106 {
01107
01108
01109 if (state != fState) {
01110 if (state == kButtonUp) {
01111 if (fPrevState == kButtonDisabled) {
01112 if (fStateOn) {
01113 fState = kButtonDown;
01114 fPrevState = kButtonDown;
01115 } else {
01116 fState = state;
01117 fPrevState = state;
01118 }
01119 } else if (fPrevState == kButtonDown) {
01120 fStateOn = kFALSE;
01121 fState = state;
01122 fPrevState = state;
01123 }
01124 } else if (state == kButtonDown) {
01125 fStateOn = kTRUE;
01126 fState = state;
01127 fPrevState = state;
01128 } else {
01129 fState = state;
01130 fPrevState = state;
01131 }
01132 if (emit) {
01133
01134 EmitSignals();
01135 }
01136 DoRedraw();
01137 }
01138 }
01139
01140
01141 void TGCheckButton::SetDisabledAndSelected(Bool_t enable)
01142 {
01143
01144
01145
01146 if (!enable) {
01147 if (fState == kButtonDisabled && fStateOn) {
01148 PSetState(kButtonUp, kFALSE);
01149 PSetState(kButtonUp, kFALSE);
01150 PSetState(kButtonDisabled, kFALSE);
01151 } else {
01152 PSetState(kButtonUp, kFALSE);
01153 PSetState(kButtonDisabled, kFALSE);
01154 }
01155 } else {
01156 PSetState(kButtonDown, kFALSE);
01157 PSetState(kButtonDisabled, kFALSE);
01158 }
01159 }
01160
01161
01162 Bool_t TGCheckButton::HandleButton(Event_t *event)
01163 {
01164
01165
01166 Bool_t click = kFALSE;
01167
01168 if (fTip) fTip->Hide();
01169
01170 if (fState == kButtonDisabled) return kTRUE;
01171
01172 Bool_t in = (event->fX >= 0) && (event->fY >= 0) &&
01173 (event->fX <= (Int_t)fWidth) && (event->fY <= (Int_t)fHeight);
01174
01175
01176
01177 if (event->fType == kButtonPress) {
01178 fgReleaseBtn = 0;
01179 if (in) {
01180 fOptions |= kSunkenFrame;
01181 Pressed();
01182 }
01183 } else {
01184 if (in) {
01185 PSetState((fPrevState == kButtonUp) ? kButtonDown : kButtonUp, kFALSE);
01186 click = kTRUE;
01187 fPrevStateOn = fStateOn;
01188 Released();
01189 }
01190 fgReleaseBtn = fId;
01191 fOptions &= ~kSunkenFrame;
01192 }
01193 if (click) {
01194 Clicked();
01195 Toggled(fStateOn);
01196 SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_CHECKBUTTON),
01197 fWidgetId, (Long_t) fUserData);
01198 fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_CHECKBUTTON),
01199 fWidgetId, (Long_t) fUserData);
01200 }
01201 DoRedraw();
01202 return kTRUE;
01203 }
01204
01205
01206 Bool_t TGCheckButton::HandleCrossing(Event_t *event)
01207 {
01208
01209
01210 if (fTip) {
01211 if (event->fType == kEnterNotify)
01212 fTip->Reset();
01213 else
01214 fTip->Hide();
01215 }
01216
01217 if ((fgDbw != event->fWindow) || (fgReleaseBtn == event->fWindow)) return kTRUE;
01218
01219 if (!(event->fState & (kButton1Mask | kButton2Mask | kButton3Mask)))
01220 return kTRUE;
01221
01222 if (fState == kButtonDisabled) return kTRUE;
01223
01224 if (event->fType == kEnterNotify) {
01225 fOptions |= kSunkenFrame;
01226 } else {
01227 fOptions &= ~kSunkenFrame;
01228 }
01229 DoRedraw();
01230
01231 return kTRUE;
01232 }
01233
01234
01235 Bool_t TGCheckButton::HandleKey(Event_t *event)
01236 {
01237
01238
01239 Bool_t click = kFALSE;
01240
01241 if (event->fType == kGKeyPress)
01242 gVirtualX->SetKeyAutoRepeat(kFALSE);
01243 else
01244 gVirtualX->SetKeyAutoRepeat(kTRUE);
01245
01246 if (fTip && event->fType == kGKeyPress) fTip->Hide();
01247
01248 if (fState == kButtonDisabled) return kTRUE;
01249
01250
01251
01252
01253 if ((event->fType == kGKeyPress) && (event->fState & kKeyMod1Mask)) {
01254 PSetState((fPrevState == kButtonUp) ? kButtonDown : kButtonUp, kTRUE);
01255 } else if ((event->fType == kKeyRelease) && (event->fState & kKeyMod1Mask)) {
01256 click = (fState != fPrevState);
01257 fPrevState = fState;
01258 }
01259 if (click) {
01260 SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_CHECKBUTTON), fWidgetId,
01261 (Long_t) fUserData);
01262 fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_CHECKBUTTON), fWidgetId,
01263 (Long_t) fUserData);
01264 }
01265 return kTRUE;
01266 }
01267
01268
01269 void TGCheckButton::DoRedraw()
01270 {
01271
01272
01273 int x, y, y0, cw;
01274
01275 TGFrame::DoRedraw();
01276
01277 x = 20;
01278 y = (fHeight - fTHeight) >> 1;
01279
01280 cw = 13;
01281 y0 = !fTHeight ? 0 : y + 1;
01282
01283 if (fStateOn) {
01284 if (fOn) fOn->Draw(fId, fNormGC, 0, y0);
01285 } else {
01286 if (fOff) fOff->Draw(fId, fNormGC, 0, y0);
01287 }
01288
01289 Int_t hotpos = fLabel->GetHotPos();
01290
01291 if (fState == kButtonDisabled) {
01292 if (fStateOn == kTRUE) {
01293 if (fDisOn) fDisOn->Draw(fId, fNormGC, 0, y0);
01294 } else {
01295 if (fDisOff) fDisOff->Draw(fId, fNormGC, 0, y0);
01296 }
01297
01298 TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
01299 TGGC *gc = pool->FindGC(fNormGC);
01300 Pixel_t fore = gc->GetForeground();
01301 Pixel_t hi = GetHilightGC().GetForeground();
01302 Pixel_t sh = GetShadowGC().GetForeground();
01303
01304 gc->SetForeground(hi);
01305 fTLayout->DrawText(fId, gc->GetGC(), x + 1, y + 1, 0, -1);
01306 if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x, y, hotpos - 1);
01307
01308 gc->SetForeground(sh);
01309 fTLayout->DrawText(fId, gc->GetGC(), x, y, 0, -1);
01310 if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x, y, hotpos - 1);
01311
01312 gc->SetForeground(fore);
01313 } else {
01314 fTLayout->DrawText(fId, fNormGC, x, y, 0, -1);
01315 if (hotpos) fTLayout->UnderlineChar(fId, fNormGC, x, y, hotpos - 1);
01316 }
01317 }
01318
01319
01320 FontStruct_t TGCheckButton::GetDefaultFontStruct()
01321 {
01322
01323
01324 if (!fgDefaultFont)
01325 fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
01326 return fgDefaultFont->GetFontStruct();
01327 }
01328
01329
01330 const TGGC &TGCheckButton::GetDefaultGC()
01331 {
01332
01333
01334 if (!fgDefaultGC)
01335 fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
01336 return *fgDefaultGC;
01337 }
01338
01339
01340
01341 TGRadioButton::TGRadioButton(const TGWindow *p, TGHotString *s, Int_t id,
01342 GContext_t norm, FontStruct_t font, UInt_t option)
01343 : TGTextButton(p, s, id, norm, font, option)
01344 {
01345
01346
01347
01348 Init();
01349 }
01350
01351
01352 TGRadioButton::TGRadioButton(const TGWindow *p, const char *s, Int_t id,
01353 GContext_t norm, FontStruct_t font, UInt_t option)
01354 : TGTextButton(p, s, id, norm, font, option)
01355 {
01356
01357
01358 Init();
01359 }
01360
01361 TGRadioButton::TGRadioButton(const TGWindow *p, const char *s, const char *cmd,
01362 Int_t id, GContext_t norm,
01363 FontStruct_t font, UInt_t option)
01364 : TGTextButton(p, s, cmd, id, norm, font, option)
01365 {
01366
01367
01368 Init();
01369 }
01370
01371
01372 void TGRadioButton::Init()
01373 {
01374
01375
01376 fPrevState =
01377 fState = kButtonUp;
01378 fHKeycode = 0;
01379
01380 fOn = fClient->GetPicture("rbutton_on.xpm");
01381 fOff = fClient->GetPicture("rbutton_off.xpm");
01382 fDisOn = fClient->GetPicture("rbutton_dis_on.xpm");
01383 fDisOff = fClient->GetPicture("rbutton_dis_off.xpm");
01384
01385 if (!fOn || !fOff || !fDisOn || !fDisOff)
01386 Error("TGRadioButton", "rbutton_*.xpm not found");
01387
01388 Resize();
01389
01390 int hotchar;
01391
01392 if ((hotchar = fLabel->GetHotChar()) != 0) {
01393 if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0) {
01394 const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
01395 main->BindKey(this, fHKeycode, kKeyMod1Mask);
01396 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
01397 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
01398 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
01399
01400 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
01401 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
01402 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
01403 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
01404 }
01405 }
01406
01407 if (fParent->IsA()->InheritsFrom(TGButtonGroup::Class())) {
01408 ((TGButtonGroup*)fParent)->SetRadioButtonExclusive(kTRUE);
01409 }
01410 SetWindowName();
01411 }
01412
01413
01414 TGRadioButton::~TGRadioButton()
01415 {
01416
01417
01418 if (fOn) fClient->FreePicture(fOn);
01419 if (fOff) fClient->FreePicture(fOff);
01420 if (fDisOn) fClient->FreePicture(fDisOn);
01421 if (fDisOff) fClient->FreePicture(fDisOff);
01422 }
01423
01424
01425 TGDimension TGRadioButton::GetDefaultSize() const
01426 {
01427
01428
01429 UInt_t w = !fTWidth ? fOff->GetWidth() : fTWidth + fOff->GetWidth() + 10;
01430 UInt_t h = !fTHeight ? fOff->GetHeight() : fTHeight + 2;
01431
01432 w = GetOptions() & kFixedWidth ? fWidth : w;
01433 h = GetOptions() & kFixedHeight ? fHeight : h;
01434
01435 return TGDimension(w, h);
01436 }
01437
01438 void TGRadioButton::SetState(EButtonState state, Bool_t emit)
01439 {
01440
01441
01442 if (state == kButtonDisabled)
01443 fWidgetFlags &= ~kWidgetIsEnabled;
01444 else
01445 fWidgetFlags |= kWidgetIsEnabled;
01446 PSetState(state, emit);
01447 }
01448
01449
01450 void TGRadioButton::SetDisabledAndSelected(Bool_t enable)
01451 {
01452
01453
01454
01455 if (!enable) {
01456 if (fState == kButtonDisabled && fStateOn) {
01457 PSetState(kButtonUp, kFALSE);
01458 PSetState(kButtonUp, kFALSE);
01459 PSetState(kButtonDisabled, kFALSE);
01460 } else {
01461 PSetState(kButtonUp, kFALSE);
01462 PSetState(kButtonDisabled, kFALSE);
01463 }
01464 } else {
01465 PSetState(kButtonDown, kFALSE);
01466 PSetState(kButtonDisabled, kFALSE);
01467 }
01468 }
01469
01470
01471 void TGRadioButton::EmitSignals(Bool_t )
01472 {
01473
01474
01475 if (fState == kButtonUp) Released();
01476 if (fState == kButtonDown) Pressed();
01477 Clicked();
01478 Toggled(fStateOn);
01479 }
01480
01481
01482 void TGRadioButton::PSetState(EButtonState state, Bool_t emit)
01483 {
01484
01485
01486 if (state != fState) {
01487
01488 if (state == kButtonUp) {
01489 if (fPrevState == kButtonDisabled) {
01490 if (fStateOn) {
01491 fState = kButtonDown;
01492 fPrevState = kButtonDown;
01493 } else {
01494 fState = state;
01495 fPrevState = state;
01496 }
01497 } else if (fPrevState == kButtonDown) {
01498 fStateOn = kFALSE;
01499 fState = state;
01500 fPrevState = state;
01501 }
01502 } else if (state == kButtonDown) {
01503 fStateOn = kTRUE;
01504 fState = state;
01505 fPrevState = state;
01506 } else {
01507 fState = state;
01508 fPrevState = state;
01509 }
01510 if (emit) {
01511
01512 EmitSignals();
01513 }
01514 DoRedraw();
01515 }
01516 }
01517
01518
01519 Bool_t TGRadioButton::HandleButton(Event_t *event)
01520 {
01521
01522
01523 Bool_t click = kFALSE;
01524 Bool_t toggled = kFALSE;
01525
01526 if (fTip) fTip->Hide();
01527
01528 if (fState == kButtonDisabled) return kFALSE;
01529
01530
01531 Bool_t in = (event->fX >= 0) && (event->fY >= 0) &&
01532 (event->fX <= (Int_t)fWidth) && (event->fY <= (Int_t)fHeight);
01533
01534 if (event->fType == kButtonPress) {
01535 fgReleaseBtn = 0;
01536 if (in) {
01537 fOptions |= kSunkenFrame;
01538 Pressed();
01539 }
01540 } else {
01541 if (in) {
01542 if (!fStateOn) {
01543 PSetState(kButtonDown, kFALSE);
01544 toggled = kTRUE;
01545 }
01546 fPrevStateOn = fStateOn;
01547 Released();
01548 click = kTRUE;
01549 }
01550 fOptions &= ~kSunkenFrame;
01551 fgReleaseBtn = fId;
01552 }
01553 if (click) {
01554 Clicked();
01555 SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_RADIOBUTTON),
01556 fWidgetId, (Long_t) fUserData);
01557 fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_RADIOBUTTON),
01558 fWidgetId, (Long_t) fUserData);
01559 }
01560 if (toggled) {
01561 Toggled(fStateOn);
01562 }
01563 DoRedraw();
01564 return kTRUE;
01565 }
01566
01567
01568 Bool_t TGRadioButton::HandleCrossing(Event_t *event)
01569 {
01570
01571
01572 if (fTip) {
01573 if (event->fType == kEnterNotify)
01574 fTip->Reset();
01575 else
01576 fTip->Hide();
01577 }
01578
01579 if ((fgDbw != event->fWindow) || (fgReleaseBtn == event->fWindow)) return kTRUE;
01580
01581 if (!(event->fState & (kButton1Mask | kButton2Mask | kButton3Mask)))
01582 return kTRUE;
01583
01584 if (fState == kButtonDisabled) return kTRUE;
01585
01586 if (event->fType == kEnterNotify) {
01587 fOptions |= kSunkenFrame;
01588 } else {
01589 fOptions &= ~kSunkenFrame;
01590 }
01591 DoRedraw();
01592
01593 return kTRUE;
01594 }
01595
01596
01597 Bool_t TGRadioButton::HandleKey(Event_t *event)
01598 {
01599
01600
01601 if (event->fType == kGKeyPress)
01602 gVirtualX->SetKeyAutoRepeat(kFALSE);
01603 else
01604 gVirtualX->SetKeyAutoRepeat(kTRUE);
01605
01606 if (fTip && event->fType == kGKeyPress)
01607 fTip->Hide();
01608
01609 if (fState == kButtonDisabled) return kTRUE;
01610
01611
01612
01613
01614 if ((event->fType == kGKeyPress) && (event->fState & kKeyMod1Mask)) {
01615 PSetState(kButtonDown, kTRUE);
01616 SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_RADIOBUTTON),
01617 fWidgetId, (Long_t) fUserData);
01618 fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_RADIOBUTTON),
01619 fWidgetId, (Long_t) fUserData);
01620 } else if ((event->fType == kKeyRelease) && (event->fState & kKeyMod1Mask)) {
01621 fPrevState = fState;
01622 }
01623 return kTRUE;
01624 }
01625
01626
01627 void TGRadioButton::DoRedraw()
01628 {
01629
01630
01631 Int_t tx, ty, y0;
01632
01633 TGFrame::DoRedraw();
01634
01635 tx = 20;
01636 ty = (fHeight - fTHeight) >> 1;
01637
01638
01639 y0 = !fTHeight ? 0 : ty + 1;
01640
01641 if (fStateOn) {
01642 if (fOn) fOn->Draw(fId, fNormGC, 0, y0);
01643 } else {
01644 if (fOff) fOff->Draw(fId, fNormGC, 0, y0);
01645 }
01646
01647 Int_t hotpos = fLabel->GetHotPos();
01648
01649 if (fState == kButtonDisabled) {
01650 if (fStateOn == kTRUE) {
01651 if (fDisOn) fDisOn->Draw(fId, fNormGC, 0, y0);
01652 } else {
01653 if (fDisOff) fDisOff->Draw(fId, fNormGC, 0, y0);
01654 }
01655
01656 TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
01657 TGGC *gc = pool->FindGC(fNormGC);
01658 Pixel_t fore = gc->GetForeground();
01659 Pixel_t hi = GetHilightGC().GetForeground();
01660 Pixel_t sh = GetShadowGC().GetForeground();
01661
01662 gc->SetForeground(hi);
01663 fTLayout->DrawText(fId, gc->GetGC(), tx + 1, ty + 1, 0, -1);
01664 if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), tx, ty, hotpos - 1);
01665
01666 gc->SetForeground(sh);
01667 fTLayout->DrawText(fId, gc->GetGC(), tx, ty, 0, -1);
01668 if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), tx, ty, hotpos - 1);
01669
01670 gc->SetForeground(fore);
01671 } else {
01672 fTLayout->DrawText(fId, fNormGC, tx, ty, 0, -1);
01673 if (hotpos) fTLayout->UnderlineChar(fId, fNormGC, tx, ty, hotpos-1);
01674 }
01675 }
01676
01677
01678 FontStruct_t TGRadioButton::GetDefaultFontStruct()
01679 {
01680
01681
01682 if (!fgDefaultFont)
01683 fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
01684 return fgDefaultFont->GetFontStruct();
01685 }
01686
01687
01688 const TGGC &TGRadioButton::GetDefaultGC()
01689 {
01690
01691
01692 if (!fgDefaultGC)
01693 fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
01694 return *fgDefaultGC;
01695 }
01696
01697
01698 void TGButton::SavePrimitive(ostream &out, Option_t *option )
01699 {
01700
01701
01702 char quote = '"';
01703
01704 if (option && strstr(option, "keep_names"))
01705 out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
01706
01707 if (fState == kButtonDown) {
01708 out << " " << GetName() << "->SetState(kButtonDown);" << endl;
01709 }
01710 if (fState == kButtonDisabled) {
01711 out << " " << GetName() << "->SetState(kButtonDisabled);" << endl;
01712 }
01713 if (fState == kButtonEngaged) {
01714 out << " " << GetName() << "->SetState(kButtonEngaged);" << endl;
01715 }
01716 if (fBackground != fgDefaultFrameBackground) {
01717 SaveUserColor(out, option);
01718 out << " " << GetName() << "->ChangeBackground(ucolor);" << endl;
01719 }
01720
01721 if (fTip) {
01722 TString tiptext = fTip->GetText()->GetString();
01723 tiptext.ReplaceAll("\n", "\\n");
01724 out << " ";
01725 out << GetName() << "->SetToolTipText(" << quote
01726 << tiptext << quote << ");" << endl;
01727 }
01728 if (strlen(fCommand)) {
01729 out << " " << GetName() << "->SetCommand(" << quote << fCommand
01730 << quote << ");" << endl;
01731 }
01732 }
01733
01734
01735 void TGTextButton::SavePrimitive(ostream &out, Option_t *option )
01736 {
01737
01738
01739 char quote = '"';
01740 TString outext(fLabel->GetString());
01741 if (fLabel->GetHotPos() > 0)
01742 outext.Insert(fLabel->GetHotPos()-1, "&");
01743 if (outext.First('\n') >= 0)
01744 outext.ReplaceAll("\n", "\\n");
01745
01746
01747 option = GetName()+5;
01748 TString parGC, parFont;
01749 parFont.Form("%s::GetDefaultFontStruct()",IsA()->GetName());
01750 parGC.Form("%s::GetDefaultGC()()",IsA()->GetName());
01751
01752 if ((GetDefaultFontStruct() != fFontStruct) || (GetDefaultGC()() != fNormGC)) {
01753 TGFont *ufont = gClient->GetResourcePool()->GetFontPool()->FindFont(fFontStruct);
01754 if (ufont) {
01755 ufont->SavePrimitive(out, option);
01756 parFont.Form("ufont->GetFontStruct()");
01757 }
01758
01759 TGGC *userGC = gClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
01760 if (userGC) {
01761 userGC->SavePrimitive(out, option);
01762 parGC.Form("uGC->GetGC()");
01763 }
01764 }
01765
01766 if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
01767
01768 out << " TGTextButton *";
01769 out << GetName() << " = new TGTextButton(" << fParent->GetName()
01770 << "," << quote << outext.Data() << quote;
01771
01772 if (GetOptions() == (kRaisedFrame | kDoubleBorder)) {
01773 if (fFontStruct == GetDefaultFontStruct()) {
01774 if (fNormGC == GetDefaultGC()()) {
01775 if (fWidgetId == -1) {
01776 out << ");" << endl;
01777 } else {
01778 out << "," << fWidgetId <<");" << endl;
01779 }
01780 } else {
01781 out << "," << fWidgetId << "," << parGC << ");" << endl;
01782 }
01783 } else {
01784 out << "," << fWidgetId << "," << parGC << "," << parFont << ");" << endl;
01785 }
01786 } else {
01787 out << "," << fWidgetId << "," << parGC << "," << parFont << "," << GetOptionString() << ");" << endl;
01788 }
01789
01790 out << " " << GetName() << "->SetTextJustify(" << fTMode << ");" << endl;
01791 out << " " << GetName() << "->SetMargins(" << fMLeft << "," << fMRight << ",";
01792 out << fMTop << "," << fMBottom << ");" << endl;
01793 out << " " << GetName() << "->SetWrapLength(" << fWrapLength << ");" << endl;
01794
01795 out << " " << GetName() << "->Resize(" << GetWidth() << "," << GetHeight()
01796 << ");" << endl;
01797
01798 TGButton::SavePrimitive(out,option);
01799 }
01800
01801
01802 void TGPictureButton::SavePrimitive(ostream &out, Option_t *option )
01803 {
01804
01805
01806 if (!fPic) {
01807 Error("SavePrimitive()", "pixmap not found for picture button %d ", fWidgetId);
01808 return;
01809 }
01810
01811
01812 option = GetName()+5;
01813 TString parGC;
01814 parGC.Form("%s::GetDefaultGC()()",IsA()->GetName());
01815
01816 if (GetDefaultGC()() != fNormGC) {
01817 TGGC *userGC = gClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
01818 if (userGC) {
01819 userGC->SavePrimitive(out, option);
01820 parGC.Form("uGC->GetGC()");
01821 }
01822 }
01823
01824 char quote = '"';
01825 const char *picname = fPic->GetName();
01826
01827 out <<" TGPictureButton *";
01828
01829 out << GetName() << " = new TGPictureButton(" << fParent->GetName()
01830 << ",gClient->GetPicture(" << quote
01831 << gSystem->ExpandPathName(gSystem->UnixPathName(picname)) << quote << ")";
01832
01833 if (GetOptions() == (kRaisedFrame | kDoubleBorder)) {
01834 if (fNormGC == GetDefaultGC()()) {
01835 if (fWidgetId == -1) {
01836 out << ");" << endl;
01837 } else {
01838 out << "," << fWidgetId << ");" << endl;
01839 }
01840 } else {
01841 out << "," << fWidgetId << "," << parGC.Data() << ");" << endl;
01842 }
01843 } else {
01844 out << "," << fWidgetId << "," << parGC.Data() << "," << GetOptionString()
01845 << ");" << endl;
01846 }
01847
01848 TGButton::SavePrimitive(out,option);
01849 }
01850
01851
01852 void TGCheckButton::SavePrimitive(ostream &out, Option_t *option )
01853 {
01854
01855
01856 char quote = '"';
01857
01858 TString outext(fLabel->GetString());
01859 if (fLabel->GetHotPos() > 0)
01860 outext.Insert(fLabel->GetHotPos()-1, "&");
01861 if (outext.First('\n') >= 0)
01862 outext.ReplaceAll("\n", "\\n");
01863
01864 out <<" TGCheckButton *";
01865 out << GetName() << " = new TGCheckButton(" << fParent->GetName()
01866 << "," << quote << outext.Data() << quote;
01867
01868
01869 option = GetName()+5;
01870 TString parGC, parFont;
01871 parFont.Form("%s::GetDefaultFontStruct()",IsA()->GetName());
01872 parGC.Form("%s::GetDefaultGC()()",IsA()->GetName());
01873
01874 if ((GetDefaultFontStruct() != fFontStruct) || (GetDefaultGC()() != fNormGC)) {
01875 TGFont *ufont = gClient->GetResourcePool()->GetFontPool()->FindFont(fFontStruct);
01876 if (ufont) {
01877 ufont->SavePrimitive(out, option);
01878 parFont.Form("ufont->GetFontStruct()");
01879 }
01880
01881 TGGC *userGC = gClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
01882 if (userGC) {
01883 userGC->SavePrimitive(out, option);
01884 parGC.Form("uGC->GetGC()");
01885 }
01886 }
01887
01888 if (GetOptions() == kChildFrame) {
01889 if (fFontStruct == GetDefaultFontStruct()) {
01890 if (fNormGC == GetDefaultGC()()) {
01891 if (fWidgetId == -1) {
01892 out << ");" << endl;
01893 } else {
01894 out << "," << fWidgetId << ");" << endl;
01895 }
01896 } else {
01897 out << "," << fWidgetId << "," << parGC << ");" << endl;
01898 }
01899 } else {
01900 out << "," << fWidgetId << "," << parGC << "," << parFont << ");" << endl;
01901 }
01902 } else {
01903 out << "," << fWidgetId << "," << parGC << "," << parFont << "," << GetOptionString() << ");" << endl;
01904 }
01905
01906 TGButton::SavePrimitive(out,option);
01907 if (fState == kButtonDisabled) {
01908 if (IsDisabledAndSelected())
01909 out << " " << GetName() << "->SetDisabledAndSelected(kTRUE);" << endl;
01910 else
01911 out << " " << GetName() << "->SetDisabledAndSelected(kFALSE);" << endl;
01912 }
01913 out << " " << GetName() << "->SetTextJustify(" << fTMode << ");" << endl;
01914 out << " " << GetName() << "->SetMargins(" << fMLeft << "," << fMRight << ",";
01915 out << fMTop << "," << fMBottom << ");" << endl;
01916 out << " " << GetName() << "->SetWrapLength(" << fWrapLength << ");" << endl;
01917 }
01918
01919
01920 void TGRadioButton::SavePrimitive(ostream &out, Option_t *option )
01921 {
01922
01923
01924 char quote = '"';
01925
01926 TString outext(fLabel->GetString());
01927 if (fLabel->GetHotPos() > 0)
01928 outext.Insert(fLabel->GetHotPos()-1, "&");
01929 if (outext.First('\n') >= 0)
01930 outext.ReplaceAll("\n", "\\n");
01931
01932 out << " TGRadioButton *";
01933 out << GetName() << " = new TGRadioButton(" << fParent->GetName()
01934 << "," << quote << outext.Data() << quote;
01935
01936
01937 option = GetName()+5;
01938 TString parGC, parFont;
01939 parFont.Form("%s::GetDefaultFontStruct()",IsA()->GetName());
01940 parGC.Form("%s::GetDefaultGC()()",IsA()->GetName());
01941
01942 if ((GetDefaultFontStruct() != fFontStruct) || (GetDefaultGC()() != fNormGC)) {
01943 TGFont *ufont = gClient->GetResourcePool()->GetFontPool()->FindFont(fFontStruct);
01944 if (ufont) {
01945 ufont->SavePrimitive(out, option);
01946 parFont.Form("ufont->GetFontStruct()");
01947 }
01948
01949 TGGC *userGC = gClient->GetResourcePool()->GetGCPool()->FindGC(fNormGC);
01950 if (userGC) {
01951 userGC->SavePrimitive(out, option);
01952 parGC.Form("uGC->GetGC()");
01953 }
01954 }
01955
01956 if (GetOptions() == (kChildFrame)) {
01957 if (fFontStruct == GetDefaultFontStruct()) {
01958 if (fNormGC == GetDefaultGC()()) {
01959 if (fWidgetId == -1) {
01960 out <<");" << endl;
01961 } else {
01962 out << "," << fWidgetId << ");" << endl;
01963 }
01964 } else {
01965 out << "," << fWidgetId << "," << parGC << ");" << endl;
01966 }
01967 } else {
01968 out << "," << fWidgetId << "," << parGC << "," << parFont << ");" << endl;
01969 }
01970 } else {
01971 out << "," << fWidgetId << "," << parGC << "," << parFont << "," << GetOptionString() << ");" << endl;
01972 }
01973
01974 TGButton::SavePrimitive(out,option);
01975 if (fState == kButtonDisabled) {
01976 if (IsDisabledAndSelected())
01977 out << " " << GetName() << "->SetDisabledAndSelected(kTRUE);" << endl;
01978 else
01979 out << " " << GetName() << "->SetDisabledAndSelected(kFALSE);" << endl;
01980 }
01981 out << " " << GetName() << "->SetTextJustify(" << fTMode << ");" << endl;
01982 out << " " << GetName() << "->SetMargins(" << fMLeft << "," << fMRight << ",";
01983 out << fMTop << "," << fMBottom << ");" << endl;
01984 out << " " << GetName() << "->SetWrapLength(" << fWrapLength << ");" << endl;
01985 }
01986
01987
01988 TGSplitButton::TGSplitButton(const TGWindow *p, TGHotString* menulabel,
01989 TGPopupMenu *popmenu, Bool_t split, Int_t id,
01990 GContext_t norm, FontStruct_t fontstruct, UInt_t options)
01991 : TGTextButton(p, menulabel, id, norm, fontstruct, options)
01992 {
01993
01994
01995
01996
01997
01998 fFontStruct = fontstruct;
01999 fMBWidth = 16;
02000 fMenuLabel = new TGHotString(*menulabel);
02001 fPopMenu = popmenu;
02002 fPopMenu->fSplitButton = this;
02003 fSplit = split;
02004 fTMode = 0;
02005 fHKeycode = 0;
02006 fMBState = kButtonUp; fDefaultCursor = fClient->GetResourcePool()->GetGrabCursor();
02007 fKeyNavigate = kFALSE;
02008 fWidestLabel = "";
02009 fHeighestLabel = "";
02010
02011
02012 TGMenuEntry *entry = 0;
02013 TGHotString lstring(*fMenuLabel);
02014 TGHotString hstring(*fMenuLabel);
02015 const TList *list = fPopMenu->GetListOfEntries();
02016 UInt_t lwidth = 0, lheight = 0;
02017 UInt_t twidth = 0, theight = 0;
02018
02019 TGFont *font = fClient->GetFontPool()->FindFont(fFontStruct);
02020 if (!font) {
02021 font = fClient->GetFontPool()->GetFont(fgDefaultFont);
02022 fFontStruct = font->GetFontStruct();
02023 }
02024
02025 font->ComputeTextLayout(lstring, lstring.GetLength(),
02026 fWrapLength, kTextLeft, 0,
02027 &lwidth, &lheight);
02028
02029 TIter iter(list);
02030 entry = (TGMenuEntry *)iter.Next();
02031 while (entry != 0) {
02032 if (entry->GetType() == kMenuEntry) {
02033 const TGHotString string(*(entry->GetLabel()));
02034 font->ComputeTextLayout(string, string.GetLength(),
02035 fWrapLength, kTextLeft, 0,
02036 &twidth, &theight);
02037 if(twidth > lwidth) {
02038 lstring = string;
02039 }
02040 if(theight > lheight) {
02041 hstring = string;
02042 }
02043 }
02044 entry = (TGMenuEntry *)iter.Next();
02045 }
02046 fWidestLabel = lstring;
02047 fHeighestLabel = hstring;
02048
02049 UInt_t dummy = 0;
02050 font->ComputeTextLayout(lstring, lstring.GetLength(),
02051 fWrapLength, kTextLeft, 0,
02052 &fTWidth, &dummy);
02053 font->ComputeTextLayout(hstring, hstring.GetLength(),
02054 fWrapLength, kTextLeft, 0,
02055 &dummy, &fTHeight);
02056
02057 fTBWidth = fTWidth + 8;
02058 fHeight = fTHeight + 7;
02059 Resize(fTBWidth + fMBWidth, fHeight);
02060
02061 ChangeOptions(GetOptions() | kFixedSize);
02062
02063
02064 TIter iter1(list);
02065 do {
02066 entry = (TGMenuEntry *)iter1.Next();
02067 if ((entry->GetStatus() & kMenuEnableMask) &&
02068 !(entry->GetStatus() & kMenuHideMask) &&
02069 (entry->GetType() != kMenuSeparator) &&
02070 (entry->GetType() != kMenuLabel)) break;
02071 entry = (TGMenuEntry *)iter1.Next();
02072 } while (entry);
02073 if (entry) fEntryId = entry->GetEntryId();
02074
02075
02076 fPopMenu->Connect("Activated(Int_t)", "TGSplitButton", this, "HandleMenu(Int_t)");
02077 SetSplit(fSplit);
02078
02079 Init();
02080 }
02081
02082
02083
02084 void TGSplitButton::Init()
02085 {
02086
02087
02088 Int_t hotchar;
02089
02090 fTMode = kTextCenterX | kTextCenterY;
02091 fHKeycode = 0;
02092 fHasOwnFont = kFALSE;
02093 fPrevStateOn =
02094 fStateOn = kFALSE;
02095 fMBState = kButtonUp;
02096
02097 SetSize(TGDimension(fWidth, fHeight));
02098
02099 if ((hotchar = fLabel->GetHotChar()) != 0) {
02100 if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0) {
02101 const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
02102 main->BindKey(this, fHKeycode, kKeyMod1Mask);
02103 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
02104 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
02105 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
02106
02107 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
02108 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
02109 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
02110 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
02111 }
02112 }
02113 SetWindowAttributes_t wattr;
02114 wattr.fMask = kWAWinGravity | kWABitGravity;
02115 wattr.fBitGravity = 5;
02116 wattr.fWinGravity = 1;
02117 gVirtualX->ChangeWindowAttributes(fId, &wattr);
02118
02119
02120 AddInput(kPointerMotionMask | kEnterWindowMask | kLeaveWindowMask);
02121
02122 SetWindowName();
02123 }
02124
02125
02126 TGSplitButton::~TGSplitButton()
02127 {
02128
02129
02130 if (fPopMenu) delete fPopMenu;
02131 if (fMenuLabel) delete fMenuLabel;
02132 }
02133
02134
02135 void TGSplitButton::DrawTriangle(const GContext_t gc, Int_t x, Int_t y)
02136 {
02137
02138
02139 Point_t points[3];
02140
02141 points[0].fX = x;
02142 points[0].fY = y;
02143 points[1].fX = x + 5;
02144 points[1].fY = y;
02145 points[2].fX = x + 2;
02146 points[2].fY = y + 3;
02147
02148 gVirtualX->FillPolygon(fId, gc, points, 3);
02149 }
02150
02151
02152 void TGSplitButton::CalcSize()
02153 {
02154
02155
02156 Int_t max_ascent, max_descent;
02157 fTWidth = gVirtualX->TextWidth(fFontStruct, fLabel->GetString(), fLabel->GetLength());
02158 gVirtualX->GetFontProperties(fFontStruct, max_ascent, max_descent);
02159 fTHeight = max_ascent + max_descent;
02160
02161 fTBWidth = fTWidth + 8;
02162 fHeight = fTHeight + 7;
02163 fWidth = fTBWidth;
02164 }
02165
02166
02167 Bool_t TGSplitButton::HandleSButton(Event_t *event)
02168 {
02169
02170
02171 if (fState == kButtonDisabled) return kFALSE;
02172
02173 Bool_t activate = kFALSE;
02174 Bool_t bclick = kFALSE;
02175 static Bool_t mbpress = kFALSE;
02176 static Bool_t tbpress = kFALSE;
02177 static Bool_t outpress = kFALSE;
02178
02179 Bool_t inTB = (event->fX >= 0) && (event->fY >= 0) &&
02180 (event->fX <= (Int_t)fTBWidth) && (event->fY <= (Int_t)fHeight);
02181
02182 Bool_t inMB = (event->fX >= (Int_t)(fWidth -fMBWidth)) && (event->fY >= 0) &&
02183 (event->fX <= (Int_t)fWidth) && (event->fY <= (Int_t)fHeight);
02184
02185
02186
02187
02188 if (inTB) {
02189 if (event->fType == kButtonPress) {
02190 mbpress = kFALSE;
02191 tbpress = kTRUE;
02192 fgReleaseBtn = 0;
02193 if (fState == kButtonEngaged) {
02194 return kTRUE;
02195 }
02196 SetState(kButtonDown);
02197 Pressed();
02198 } else {
02199 if (fMBState == kButtonDown) {
02200 SetMBState(kButtonUp);
02201 }
02202 if (fState == kButtonEngaged && tbpress) {
02203 SetState(kButtonUp);
02204 Released();
02205 bclick = kTRUE;
02206 } else if (fState == kButtonDown && tbpress) {
02207 tbpress = kFALSE;
02208 if (fStayDown) {
02209 bclick = kTRUE;
02210 SetState(kButtonEngaged);
02211 fgReleaseBtn = 0;
02212 } else {
02213 bclick = kTRUE;
02214 SetState(kButtonUp);
02215 Released();
02216 fgReleaseBtn = fId;
02217 }
02218 }else {
02219 SetState(kButtonUp);
02220 }
02221 }
02222 } else if (inMB) {
02223 if (event->fType == kButtonPress) {
02224 fgReleaseBtn = 0;
02225 mbpress = kTRUE;
02226 tbpress = kFALSE;
02227 if (fMBState == kButtonEngaged) {
02228 return kTRUE;
02229 }
02230 SetMBState(kButtonDown);
02231 MBPressed();
02232 gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
02233 kPointerMotionMask, kNone, fDefaultCursor);
02234 } else {
02235 if (fState == kButtonDown) {
02236 SetState(kButtonUp);
02237 }
02238 if (fMBState == kButtonEngaged && mbpress) {
02239 mbpress = kFALSE;
02240 SetMBState(kButtonUp);
02241 SetMenuState(kFALSE);
02242 MBReleased();
02243 MBClicked();
02244 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
02245 } else if (fMBState == kButtonDown && mbpress) {
02246 MBClicked();
02247 SetMBState(kButtonEngaged);
02248 SetMenuState(kTRUE);
02249 fgReleaseBtn = 0;
02250 } else {
02251 SetMBState(kButtonUp);
02252 }
02253 }
02254 } else {
02255 if (event->fType == kButtonPress) {
02256 fgReleaseBtn = 0;
02257 outpress = kTRUE;
02258 } else {
02259 if(outpress) {
02260 outpress = kFALSE;
02261 SetMBState(kButtonUp);
02262 SetMenuState(kFALSE);
02263 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
02264 activate = kTRUE;
02265 }
02266 }
02267 }
02268 if (bclick) {
02269 Clicked();
02270 SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
02271 (Long_t) fUserData);
02272 fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
02273 (Long_t) fUserData);
02274 }
02275 if (activate) {
02276 TGMenuEntry *entry = fPopMenu->GetCurrent();
02277 if (entry) {
02278 if ((entry->GetStatus() & kMenuEnableMask) &&
02279 !(entry->GetStatus() & kMenuHideMask) &&
02280 (entry->GetType() != kMenuSeparator) &&
02281 (entry->GetType() != kMenuLabel)) {
02282 Int_t id = entry->GetEntryId();
02283 fPopMenu->Activated(id);
02284 }
02285 }
02286 }
02287
02288
02289
02290
02291
02292
02293
02294 return kTRUE;
02295 }
02296
02297
02298 Bool_t TGSplitButton::HandleSCrossing(Event_t *event)
02299 {
02300
02301
02302 if (fTip) {
02303 if (event->fType == kEnterNotify)
02304 fTip->Reset();
02305 else
02306 fTip->Hide();
02307 }
02308
02309 if ((fgDbw != event->fWindow) || (fgReleaseBtn == event->fWindow)) return kTRUE;
02310
02311 if (!(event->fState & (kButton1Mask | kButton2Mask | kButton3Mask)))
02312 return kTRUE;
02313
02314 if (fState == kButtonEngaged || fState == kButtonDisabled) return kTRUE;
02315
02316 Bool_t inTB = (event->fX <= (Int_t)fTBWidth);
02317
02318
02319
02320
02321 if (event->fType == kEnterNotify) {
02322 if (inTB) {
02323 SetState(kButtonDown, kFALSE);
02324 } else {
02325 if(fMBState == kButtonEngaged) return kTRUE;
02326 SetMBState(kButtonDown);
02327 }
02328 } else {
02329
02330 if(fState == kButtonDown) {
02331 SetState(kButtonUp, kFALSE);
02332 }
02333 if (fMBState == kButtonEngaged) return kTRUE;
02334 SetMBState(kButtonUp);
02335 }
02336 return kTRUE;
02337 }
02338
02339
02340 Bool_t TGSplitButton::HandleSKey(Event_t *event)
02341 {
02342
02343
02344 if (fState == kButtonDisabled) return kFALSE;
02345
02346 Bool_t click = kFALSE;
02347
02348 if (event->fType == kGKeyPress) {
02349 gVirtualX->SetKeyAutoRepeat(kFALSE);
02350 } else {
02351 gVirtualX->SetKeyAutoRepeat(kTRUE);
02352 }
02353
02354 if (fTip && event->fType == kGKeyPress) fTip->Hide();
02355
02356
02357
02358
02359 if ((event->fType == kGKeyPress) && (event->fState & kKeyMod1Mask)) {
02360 if (fState == kButtonEngaged) return kTRUE;
02361 SetState(kButtonDown);
02362 Pressed();
02363 } else if ((event->fType == kKeyRelease) && (event->fState & kKeyMod1Mask)) {
02364 if (fState == kButtonEngaged) {
02365 SetState(kButtonUp);
02366 Released();
02367 }
02368 if (fStayDown) {
02369 SetState(kButtonEngaged);
02370 } else {
02371 SetState(kButtonUp);
02372 Released();
02373 }
02374 click = kTRUE;
02375 }
02376 if (click) {
02377 Clicked();
02378 SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
02379 (Long_t) fUserData);
02380 fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
02381 (Long_t) fUserData);
02382 }
02383
02384 return kTRUE;
02385 }
02386
02387
02388 void TGSplitButton::SetMenuState(Bool_t state)
02389 {
02390
02391
02392 if (state) {
02393 Int_t ax, ay;
02394 Window_t wdummy;
02395
02396 if (fSplit) {
02397 Int_t n_entries = 0;
02398 TGMenuEntry *entry = 0;
02399 TIter next(fPopMenu->GetListOfEntries());
02400
02401 while ((entry = (TGMenuEntry *) next())) {
02402 if ((entry->GetType() != kMenuSeparator) &&
02403 (entry->GetType() != kMenuLabel)) {
02404 n_entries++;
02405 }
02406 }
02407 if (n_entries <= 1) {
02408 Info("TGSplitButton", "Only one entry in the menu.");
02409 return;
02410 }
02411 }
02412
02413 gVirtualX->TranslateCoordinates(fId, fPopMenu->GetParent()->GetId(),
02414 0, 0, ax, ay, wdummy);
02415
02416
02417 fPopMenu->PlaceMenu(ax-1, ay+fHeight, kTRUE, kFALSE);
02418 BindKeys(kTRUE);
02419 BindMenuKeys(kTRUE);
02420 } else {
02421 fPopMenu->EndMenu(fUserData);
02422 BindKeys(kFALSE);
02423 BindMenuKeys(kFALSE);
02424 fPopMenu->EndMenu(fUserData);
02425 }
02426 }
02427
02428
02429 void TGSplitButton::DoRedraw()
02430 {
02431
02432
02433 int x, y;
02434 TGFrame::DoRedraw();
02435
02436 if (fState == kButtonDisabled) fMBState = kButtonDisabled;
02437 else if (fMBState == kButtonDisabled) fMBState = kButtonUp;
02438
02439 if (fTMode & kTextLeft) {
02440 x = fMLeft + 4;
02441 } else if (fTMode & kTextRight) {
02442 x = fWidth - fTWidth -fMBWidth - fMRight - 4;
02443 } else {
02444 x = (fWidth - fTWidth -fMBWidth + fMLeft - fMRight) >> 1;
02445 }
02446
02447 if (fTMode & kTextTop) {
02448 y = fMTop + 3;
02449 } else if (fTMode & kTextBottom) {
02450 y = fHeight - fTHeight - fMBottom - 3;
02451 } else {
02452 y = (fHeight - fTHeight + fMTop - fMBottom) >> 1;
02453 }
02454
02455 if (fState == kButtonDown || fState == kButtonEngaged) { ++x; ++y; }
02456 if (fState == kButtonEngaged) {
02457 gVirtualX->FillRectangle(fId, GetHibckgndGC()(), 2, 2, fWidth-4, fHeight-4);
02458 gVirtualX->DrawLine(fId, GetHilightGC()(), 2, 2, fWidth-3, 2);
02459 }
02460
02461 Int_t hotpos = fLabel->GetHotPos();
02462
02463 if (fState == kButtonDisabled) {
02464 TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
02465 TGGC *gc = pool->FindGC(fNormGC);
02466 Pixel_t fore = gc->GetForeground();
02467 Pixel_t hi = GetHilightGC().GetForeground();
02468 Pixel_t sh = GetShadowGC().GetForeground();
02469
02470 gc->SetForeground(hi);
02471 fTLayout->DrawText(fId, gc->GetGC(), x + 1, y + 1, 0, -1);
02472 if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x + 1, y + 1, hotpos - 1);
02473
02474 gc->SetForeground(sh);
02475 fTLayout->DrawText(fId, gc->GetGC(), x, y, 0, -1);
02476 if (hotpos) fTLayout->UnderlineChar(fId, gc->GetGC(), x, y, hotpos - 1);
02477 gc->SetForeground(fore);
02478 } else {
02479 fTLayout->DrawText(fId, fNormGC, x, y, 0, -1);
02480 if (hotpos) fTLayout->UnderlineChar(fId, fNormGC, x, y, hotpos - 1);
02481 }
02482
02483
02484
02485
02486 x = fWidth - 11;
02487 y = fHeight - 10;
02488
02489 if (fSplit) {
02490
02491 Int_t lx = fWidth - fMBWidth;
02492 Int_t ly = 2;
02493 Int_t lh = fHeight - 2;
02494
02495 if(fMBState == kButtonDown || fMBState == kButtonEngaged) {
02496 x++;
02497 y++;
02498 }
02499
02500 gVirtualX->DrawLine(fId, GetShadowGC()(), lx, ly + 2, lx, lh - 4);
02501 gVirtualX->DrawLine(fId, GetHilightGC()(), lx + 1, ly + 2, lx + 1, lh - 3);
02502 gVirtualX->DrawLine(fId, GetHilightGC()(), lx, lh - 3, lx + 1, lh - 3);
02503
02504 if (fMBState == kButtonEngaged) {
02505 gVirtualX->FillRectangle(fId, GetHibckgndGC()(), fTBWidth + 1, 1, fMBWidth - 3, fHeight - 3);
02506 }
02507
02508 if (fMBState == kButtonDisabled) {
02509 DrawTriangle(GetHilightGC()(), x + 1, y + 1);
02510 DrawTriangle(GetShadowGC()(), x, y);
02511 } else {
02512 DrawTriangle(fNormGC, x, y);
02513 }
02514
02515 } else {
02516 x -= 2;
02517 if(fState == kButtonDown || fState == kButtonEngaged) {
02518 x++;
02519 y++;
02520 }
02521 if (fState == kButtonDisabled) {
02522 DrawTriangle(GetHilightGC()(), x + 1, y + 1);
02523 DrawTriangle(GetShadowGC()(), x, y);
02524 } else {
02525 DrawTriangle(fNormGC, x, y);
02526 }
02527 }
02528
02529 }
02530
02531
02532 void TGSplitButton::BindKeys(Bool_t on)
02533 {
02534
02535
02536
02537 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Up), kAnyModifier, on);
02538 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Down), kAnyModifier, on);
02539 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Enter), kAnyModifier, on);
02540 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Return), kAnyModifier, on);
02541 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(kKey_Escape), kAnyModifier, on);
02542 }
02543
02544
02545 void TGSplitButton::BindMenuKeys(Bool_t on)
02546 {
02547
02548
02549 TGMenuEntry *e = 0;
02550 TIter next(fPopMenu->GetListOfEntries());
02551
02552 while ((e = (TGMenuEntry*)next())) {
02553 Int_t hot = 0;
02554 if (e->GetLabel()) {
02555 hot = e->GetLabel()->GetHotChar();
02556 }
02557 if (!hot) continue;
02558 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), 0, on);
02559 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask, on);
02560 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyLockMask, on);
02561 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyMod2Mask, on);
02562 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask | kKeyLockMask, on);
02563 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask | kKeyMod2Mask, on);
02564 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyLockMask | kKeyMod2Mask, on);
02565 gVirtualX->GrabKey(fId, gVirtualX->KeysymToKeycode(hot), kKeyShiftMask | kKeyLockMask | kKeyMod2Mask, on);
02566 }
02567 }
02568
02569
02570 TGDimension TGSplitButton::GetDefaultSize() const
02571 {
02572
02573
02574 UInt_t w = GetOptions() & kFixedWidth ? fWidth + fMBWidth : fTWidth + fMLeft + fMRight + fMBWidth + 8;
02575 UInt_t h = GetOptions() & kFixedHeight ? fHeight : fTHeight + fMTop + fMBottom + 7;
02576 return TGDimension(w, h);
02577 }
02578
02579
02580 void TGSplitButton::SetText(TGHotString *new_label)
02581 {
02582
02583
02584 Int_t hotchar;
02585 static Bool_t longlabeltip = kFALSE;
02586 const TGMainFrame *main = (TGMainFrame *) GetMainFrame();
02587
02588 TGFont *font = fClient->GetFontPool()->FindFont(fFontStruct);
02589 if (!font) {
02590 font = fClient->GetFontPool()->GetFont(fgDefaultFont);
02591 fFontStruct = font->GetFontStruct();
02592 }
02593
02594 UInt_t width = 0, bwidth = 0, dummy;
02595 font->ComputeTextLayout(new_label->GetString(), new_label->GetLength(),
02596 fWrapLength, kTextLeft, 0,
02597 &width, &dummy);
02598 font->ComputeTextLayout(fWidestLabel.GetString(), fWidestLabel.GetLength(),
02599 fWrapLength, kTextLeft, 0,
02600 &bwidth, &dummy);
02601
02602 if (width > bwidth) {
02603 if (!fTip) {
02604 SetToolTipText(new_label->GetString());
02605 longlabeltip = kTRUE;
02606 }
02607 Info("TGSplitbutton", "Length of new label to long, label truncated.");
02608 new_label->Resize(fWidestLabel.GetLength());
02609 } else if (new_label->GetLength() <= fWidestLabel.GetLength() && longlabeltip) {
02610 if (fTip) delete fTip;
02611 fTip = 0;
02612 longlabeltip = kFALSE;
02613 }
02614
02615 if (fLabel) {
02616 if (fHKeycode) {
02617 main->RemoveBind(this, fHKeycode, kKeyMod1Mask);
02618 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
02619 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
02620 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
02621
02622 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
02623 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
02624 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
02625 main->RemoveBind(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
02626 }
02627 delete fLabel;
02628 }
02629
02630 fLabel = new_label;
02631 if ((hotchar = fLabel->GetHotChar()) != 0) {
02632 if ((fHKeycode = gVirtualX->KeysymToKeycode(hotchar)) != 0)
02633 main->BindKey(this, fHKeycode, kKeyMod1Mask);
02634 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask);
02635 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyLockMask);
02636 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyLockMask);
02637
02638 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask);
02639 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask);
02640 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyMod2Mask | kKeyLockMask);
02641 main->BindKey(this, fHKeycode, kKeyMod1Mask | kKeyShiftMask | kKeyMod2Mask | kKeyLockMask);
02642 }
02643
02644 Layout();
02645 }
02646
02647
02648 void TGSplitButton::SetText(const TString &new_label)
02649 {
02650
02651
02652 SetText(new TGHotString(new_label));
02653 }
02654
02655
02656 void TGSplitButton::SetFont(FontStruct_t font, Bool_t global)
02657 {
02658
02659
02660
02661 if (font != fFontStruct) {
02662 FontH_t v = gVirtualX->GetFontHandle(font);
02663 if (!v) return;
02664
02665 fFontStruct = font;
02666 TGGCPool *pool = fClient->GetResourcePool()->GetGCPool();
02667 TGGC *gc = pool->FindGC(fNormGC);
02668
02669 if (!global) {
02670 gc = pool->GetGC((GCValues_t*)gc->GetAttributes(), kTRUE);
02671 fHasOwnFont = kTRUE;
02672 }
02673
02674 gc->SetFont(v);
02675
02676 fNormGC = gc->GetGC();
02677
02678 fClient->NeedRedraw(this);
02679 }
02680 }
02681
02682
02683 void TGSplitButton::SetFont(const char *fontName, Bool_t global)
02684 {
02685
02686
02687
02688 TGFont *font = fClient->GetFont(fontName);
02689 if (font) {
02690 SetFont(font->GetFontStruct(), global);
02691 }
02692 }
02693
02694
02695 void TGSplitButton::SetMBState(EButtonState state)
02696 {
02697
02698
02699 if (state != fMBState) {
02700 fMBState = state;
02701 DoRedraw();
02702 }
02703 }
02704
02705
02706 void TGSplitButton::SetSplit(Bool_t split)
02707 {
02708
02709
02710 if(split) {
02711 fStayDown = kFALSE;
02712 Disconnect(fPopMenu, "PoppedDown()");
02713 fPopMenu->Connect("PoppedDown()", "TGSplitButton", this, "SetMBState(=kButtonUp)");
02714 fPopMenu->Connect("PoppedDown()", "TGSplitButton", this, "MBReleased()");
02715
02716 TGMenuEntry *entry = fPopMenu->GetEntry(fEntryId);
02717
02718 TGHotString *tmp = new TGHotString(*(entry->GetLabel()));
02719 SetText(tmp);
02720
02721 TString str("ItemClicked(=");
02722 str += entry->GetEntryId();
02723 str += ")";
02724 Connect("Clicked()", "TGSplitButton", this, str);
02725 fEntryId = entry->GetEntryId();
02726 fPopMenu->HideEntry(fEntryId);
02727 } else {
02728 fStayDown = kTRUE;
02729 Disconnect(fPopMenu, "PoppedDown()");
02730 Disconnect(this, "Clicked()", this);
02731 fPopMenu->Connect("PoppedDown()", "TGSplitButton", this, "SetState(=kButtonUp)");
02732 fPopMenu->Connect("PoppedDown()", "TGSplitButton", this, "Released()");
02733 fPopMenu->EnableEntry(fEntryId);
02734 TGHotString *tmp = new TGHotString(*fMenuLabel);
02735 SetText(tmp);
02736 }
02737
02738 fSplit = split;
02739 DoRedraw();
02740 }
02741
02742
02743 Bool_t TGSplitButton::HandleButton(Event_t *event)
02744 {
02745
02746
02747 if (fState == kButtonDisabled) return kFALSE;
02748
02749 if (fSplit) return HandleSButton(event);
02750
02751 Bool_t in = (event->fX >= 0) && (event->fY >= 0) &&
02752 (event->fX <= (Int_t)fWidth) && (event->fY <= (Int_t)fHeight);
02753
02754 Bool_t activate = kFALSE;
02755 Bool_t click = kFALSE;
02756
02757 if (in) {
02758 if (event->fType == kButtonPress) {
02759 fgReleaseBtn = 0;
02760 if (fState == kButtonEngaged) {
02761 return kTRUE;
02762 }
02763 SetState(kButtonDown);
02764 Pressed();
02765 gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
02766 kPointerMotionMask, kNone, fDefaultCursor);
02767 } else {
02768 if (fState == kButtonEngaged) {
02769 SetState(kButtonUp);
02770 SetMenuState(kFALSE);
02771 Released();
02772 click = kTRUE;
02773 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
02774 } else {
02775 click = (fState == kButtonDown);
02776 if (click && fStayDown) {
02777 SetState(kButtonEngaged);
02778 SetMenuState(kTRUE);
02779 fgReleaseBtn = 0;
02780 } else {
02781 SetState(kButtonUp);
02782 Released();
02783 fgReleaseBtn = fId;
02784 }
02785 }
02786 fKeyNavigate = kFALSE;
02787 }
02788 } else {
02789 if (event->fType == kButtonPress) {
02790 fgReleaseBtn = 0;
02791 } else {
02792 SetState(kButtonUp);
02793 SetMenuState(kFALSE);
02794 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
02795 activate = kTRUE;
02796 }
02797 }
02798 if (click) {
02799 Clicked();
02800 SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
02801 (Long_t) fUserData);
02802 fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
02803 (Long_t) fUserData);
02804 }
02805 if (activate && !fKeyNavigate) {
02806 TGMenuEntry *entry = fPopMenu->GetCurrent();
02807 if (entry) {
02808 if ((entry->GetStatus() & kMenuEnableMask) &&
02809 !(entry->GetStatus() & kMenuHideMask) &&
02810 (entry->GetType() != kMenuSeparator) &&
02811 (entry->GetType() != kMenuLabel)) {
02812 Int_t id = entry->GetEntryId();
02813 fPopMenu->Activated(id);
02814 }
02815 }
02816 }
02817
02818 return kTRUE;
02819
02820 }
02821
02822
02823 Bool_t TGSplitButton::HandleCrossing(Event_t *event)
02824 {
02825
02826
02827 if (fSplit) {
02828 return HandleSCrossing(event);
02829 } else {
02830 return TGButton::HandleCrossing(event);
02831 }
02832 }
02833
02834
02835 Bool_t TGSplitButton::HandleKey(Event_t *event)
02836 {
02837
02838
02839 Bool_t click = kFALSE;
02840
02841 if (fState == kButtonDisabled) return kTRUE;
02842
02843 if(fSplit) return HandleSKey(event);
02844
02845 if (event->fType == kGKeyPress) {
02846 gVirtualX->SetKeyAutoRepeat(kFALSE);
02847 } else {
02848 gVirtualX->SetKeyAutoRepeat(kTRUE);
02849 }
02850
02851 if (fTip && event->fType == kGKeyPress) fTip->Hide();
02852
02853
02854
02855 if (event->fState & kKeyMod1Mask) {
02856 RequestFocus();
02857 fKeyNavigate = kTRUE;
02858 if (event->fType == kGKeyPress) {
02859 if (fState == kButtonEngaged) return kTRUE;
02860 SetState(kButtonDown);
02861 Pressed();
02862 } else if (event->fType == kKeyRelease) {
02863 click = kTRUE;
02864 if (fState == kButtonEngaged) {
02865 SetState(kButtonUp);
02866 SetMenuState(kFALSE);
02867 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
02868 } else if (fState == kButtonDown && fStayDown) {
02869 SetState(kButtonEngaged);
02870 SetMenuState(kTRUE);
02871 gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
02872 kPointerMotionMask, kNone, fDefaultCursor);
02873 TGMenuEntry *entry = 0;
02874 TIter next(fPopMenu->GetListOfEntries());
02875
02876 while ((entry = (TGMenuEntry *) next())) {
02877 if ((entry->GetStatus() & kMenuEnableMask) &&
02878 !(entry->GetStatus() & kMenuHideMask) &&
02879 (entry->GetType() != kMenuSeparator) &&
02880 (entry->GetType() != kMenuLabel)) break;
02881 }
02882 if (entry) {
02883 fPopMenu->Activate(entry);
02884 }
02885 } else {
02886 Released();
02887 SetState(kButtonUp);
02888 }
02889 }
02890 } else {
02891 fKeyNavigate = kTRUE;
02892 if (event->fType == kGKeyPress) {
02893 Event_t ev;
02894 ev.fX = ev.fY = 1;
02895 UInt_t keysym;
02896 char tmp[2];
02897
02898 gVirtualX->LookupString(event, tmp, sizeof(tmp), keysym);
02899
02900 TGMenuEntry *ce = 0;
02901 TIter next(fPopMenu->GetListOfEntries());
02902
02903 while ((ce = (TGMenuEntry*)next())) {
02904 UInt_t hot = 0;
02905 if (ce->GetLabel()) hot = ce->GetLabel()->GetHotChar();
02906 if (!hot || (hot != keysym)) continue;
02907
02908 fPopMenu->Activate(ce);
02909 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
02910 SetMenuState(kFALSE);
02911 ev.fType = kButtonRelease;
02912 ev.fWindow = fPopMenu->GetId();
02913 fKeyNavigate = kFALSE;
02914 return HandleButton(&ev);
02915 }
02916
02917 ce = fPopMenu->GetCurrent();
02918
02919 switch ((EKeySym)keysym) {
02920 case kKey_Up:
02921 if (ce) ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->Before(ce);
02922 while (ce && ((ce->GetType() == kMenuSeparator) ||
02923 (ce->GetType() == kMenuLabel) ||
02924 !(ce->GetStatus() & kMenuEnableMask))) {
02925 ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->Before(ce);
02926 }
02927 if (!ce) ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->Last();
02928 break;
02929 case kKey_Down:
02930 if (ce) ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->After(ce);
02931 while (ce && ((ce->GetType() == kMenuSeparator) ||
02932 (ce->GetType() == kMenuLabel) ||
02933 !(ce->GetStatus() & kMenuEnableMask))) {
02934 ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->After(ce);
02935 }
02936 if (!ce) ce = (TGMenuEntry*)fPopMenu->GetListOfEntries()->First();
02937 break;
02938 case kKey_Enter:
02939 case kKey_Return:
02940 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
02941 SetMenuState(kFALSE);
02942 ev.fType = kButtonRelease;
02943 ev.fWindow = fPopMenu->GetId();
02944 fKeyNavigate = kFALSE;
02945 HandleButton(&ev);
02946 break;
02947 case kKey_Escape:
02948 gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
02949 SetMenuState(kFALSE);
02950 break;
02951 default:
02952 break;
02953 }
02954 if (ce) fPopMenu->Activate(ce);
02955 }
02956 }
02957 if (click) {
02958 Clicked();
02959 SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
02960 (Long_t) fUserData);
02961 fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
02962 (Long_t) fUserData);
02963 }
02964
02965 return kTRUE;
02966 }
02967
02968
02969 Bool_t TGSplitButton::HandleMotion(Event_t *event)
02970 {
02971
02972
02973 if (fKeyNavigate) return kTRUE;
02974
02975 if (fSplit) {
02976 if (fMBState == kButtonDown) {
02977 if (event->fX < (Int_t)fTBWidth) {
02978 SetMBState(kButtonUp);
02979 SetState(kButtonDown);
02980 }
02981 } else if (fState == kButtonDown) {
02982 if (event->fX > (Int_t)fTBWidth) {
02983 SetState(kButtonUp);
02984 SetMBState(kButtonDown);
02985 }
02986
02987 }
02988 }
02989 return kTRUE;
02990 }
02991
02992
02993 void TGSplitButton::Layout()
02994 {
02995
02996
02997 UInt_t dummya = 0, dummyb = 0;
02998 delete fTLayout;
02999
03000 TGFont *font = fClient->GetFontPool()->FindFont(fFontStruct);
03001 if (!font) {
03002 font = fClient->GetFontPool()->GetFont(fgDefaultFont);
03003 fFontStruct = font->GetFontStruct();
03004 }
03005
03006 fTLayout = font->ComputeTextLayout(fLabel->GetString(),
03007 fLabel->GetLength(),
03008 fWrapLength, kTextLeft, 0,
03009 &dummya, &dummyb);
03010
03011 UInt_t dummy = 0;
03012 font->ComputeTextLayout(fWidestLabel.GetString(), fWidestLabel.GetLength(),
03013 fWrapLength, kTextLeft, 0,
03014 &fTWidth, &dummy);
03015 font->ComputeTextLayout(fHeighestLabel.GetString(), fHeighestLabel.GetLength(),
03016 fWrapLength, kTextLeft, 0,
03017 &dummy, &fTHeight);
03018
03019 fTBWidth = fTWidth + 8;
03020 fWidth = fTBWidth + fMBWidth;
03021 fHeight = fTHeight + 7;
03022 fClient->NeedRedraw(this);
03023 }
03024
03025
03026 void TGSplitButton::HandleMenu(Int_t id)
03027 {
03028
03029
03030 SetMenuState(kFALSE);
03031
03032 if (fSplit) {
03033 SetMBState(kButtonUp);
03034 Disconnect(this, "Clicked()", this);
03035
03036 Connect("Clicked()", "TGSplitButton", this,
03037 TString::Format("ItemClicked(=%d)", id));
03038
03039
03040 const TList *list = fPopMenu->GetListOfEntries();
03041 TIter iter(list);
03042 fPopMenu->EnableEntry(fEntryId);
03043 TGHotString *label = fPopMenu->GetEntry(id)->GetLabel();
03044 TGHotString *tmp = new TGHotString(*label);
03045 SetText(tmp);
03046 fPopMenu->HideEntry(id);
03047 fEntryId = fPopMenu->GetEntry(id)->GetEntryId();
03048 } else {
03049 SetState(kButtonUp);
03050 ItemClicked(id);
03051 }
03052 DoRedraw();
03053 }