TGButton.cxx

Go to the documentation of this file.
00001 // @(#)root/gui:$Id: TGButton.cxx 35582 2010-09-22 13:38:27Z bellenot $
00002 // Author: Fons Rademakers   06/01/98
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 /**************************************************************************
00012 
00013     This source is based on Xclass95, a Win95-looking GUI toolkit.
00014     Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
00015 
00016     Xclass95 is free software; you can redistribute it and/or
00017     modify it under the terms of the GNU Library General Public
00018     License as published by the Free Software Foundation; either
00019     version 2 of the License, or (at your option) any later version.
00020 
00021 **************************************************************************/
00022 
00023 //////////////////////////////////////////////////////////////////////////
00024 //                                                                      //
00025 // TGButton, TGTextButton, TGPictureButton, TGCheckButton,              //
00026 // TGRadioButton and TGSplitButton                                      //
00027 //                                                                      //
00028 // This header defines all GUI button widgets.                          //
00029 //                                                                      //
00030 // TGButton is a button abstract base class. It defines general button  //
00031 // behaviour.                                                           //
00032 //                                                                      //
00033 // TGTextButton and TGPictureButton yield an action as soon as they are //
00034 // clicked. These buttons usually provide fast access to frequently     //
00035 // used or critical commands. They may appear alone or placed in a      //
00036 // group.                                                               //
00037 //                                                                      //
00038 // The action they perform can be inscribed with a meaningful tooltip   //
00039 // set by SetToolTipText(const char* text, Long_t delayms=400).         //
00040 //                                                                      //
00041 // The text button has a label indicating the action to be taken when   //
00042 // the button is pressed. The text can be a hot string ("&Exit") that   //
00043 // defines the label "Exit" and keyboard mnemonics Alt+E for button     //
00044 // selection. A button label can be changed by SetText(new_label).      //
00045 //                                                                      //
00046 // Selecting a text or picture button will generate the event:          //
00047 // kC_COMMAND, kCM_BUTTON, button id, user data.                        //
00048 //                                                                      //
00049 // The purpose of TGCheckButton and TGRadioButton is for selecting      //
00050 // different options. Like text buttons, they have text or hot string   //
00051 // as a label.                                                          //
00052 //                                                                      //
00053 // Radio buttons are grouped usually in logical sets of two or more     //
00054 // buttons to present mutually exclusive choices.                       //
00055 //                                                                      //
00056 // Selecting a check button will generate the event:                    //
00057 // kC_COMMAND, kCM_CHECKBUTTON, button id, user data.                   //
00058 //                                                                      //
00059 // Selecting a radio button will generate the event:                    //
00060 // kC_COMMAND, kCM_RADIOBUTTON, button id, user data.                   //
00061 //                                                                      //
00062 // If a command string has been specified (via SetCommand()) then this  //
00063 // command string will be executed via the interpreter whenever a       //
00064 // button is selected. A command string can contain the macros:         //
00065 // $MSG   -- kC_COMMAND, kCM[CHECK|RADIO]BUTTON packed message          //
00066 //           (use GET_MSG() and GET_SUBMSG() to unpack)                 //
00067 // $PARM1 -- button id                                                  //
00068 // $PARM2 -- user data pointer                                          //
00069 // Before executing these macros are expanded into the respective       //
00070 // Long_t's                                                             //
00071 //                                                                      //
00072 // TGSplitButton implements a button with added menu functionality.     //
00073 // There are 2 modes of operation available.                            //
00074 //                                                                      //
00075 // If the button is split, a menu will popup when the menu area of the  //
00076 // button is clicked. Activating a menu item changes the functionality  //
00077 // of the button by having it emit a additional signal when it is       //
00078 // clicked. The signal emitted when the button is clicked, is the       //
00079 // ItemClicked(Int_t) signal with a different fixed value for the       //
00080 // Int_t that corresponds to the id of the activated menu entry.        //
00081 //                                                                      //
00082 // If the button is not split, clicking it will popup the menu and the  //
00083 // ItemClicked(Int_t) signal will be emitted when a menu entry is       //
00084 // acitvated. The value of the Int_t is again equal to the value of     //
00085 // the id of the activated menu entry.                                  //
00086 //                                                                      //
00087 // The mode of operation of a SplitButton can be changed on the fly     //
00088 // by calling the SetSplit(Bool_t) method.                              //
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    // Create button base class part.
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    // Delete button.
00160 
00161    // remove from button group
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    // Set button state.
00174 
00175    Bool_t was = !IsDown();   // kTRUE if button was off
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    // Set button state down according to the parameter 'on'.
00205 
00206    if (GetState() == kButtonDisabled) return;
00207 
00208    SetState(on ? kButtonDown : kButtonUp, emit);
00209 }
00210 
00211 //______________________________________________________________________________
00212 void TGButton::SetGroup(TGButtonGroup *group)
00213 {
00214    // Sets new button-group for this button.
00215 
00216    fGroup = group;
00217 }
00218 
00219 //______________________________________________________________________________
00220 Bool_t TGButton::HandleButton(Event_t *event)
00221 {
00222    // Handle mouse button event.
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    // We don't need to check the button number as GrabButton will
00234    // only allow button1 events
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 { // ButtonRelease
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    // Emit button signals.
00275 
00276    Bool_t now = !IsDown();       // kTRUE if button now is off
00277 
00278    // emit signals
00279    if (was && !now) {
00280       Pressed();                 // emit Pressed  = was off , now on
00281       if (fStayDown) Clicked();  // emit Clicked
00282    }
00283    if (!was && now) {
00284       Released();                // emit Released = was on , now off
00285       Clicked();                 // emit Clicked
00286    }
00287    if ((was != now) && IsToggleButton()) Toggled(!now); // emit Toggled  = was != now
00288 }
00289 
00290 //______________________________________________________________________________
00291 Bool_t TGButton::HandleCrossing(Event_t *event)
00292 {
00293    // Handle mouse crossing event.
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    // Set tool tip text associated with this button. The delay is in
00320    // milliseconds (minimum 250). To remove tool tip call method with
00321    // text = 0.
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    // Set enabled or disabled state of button
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    // Return default graphics context.
00347 
00348    if (!fgDefaultGC)
00349       fgDefaultGC = gClient->GetResourcePool()->GetFrameGC();
00350    return *fgDefaultGC;
00351 }
00352 
00353 //______________________________________________________________________________
00354 const TGGC &TGButton::GetHibckgndGC()
00355 {
00356    // Return graphics context for highlighted frame background.
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    // Create a text button widget. The hotstring will be adopted and deleted
00379    // by the text button.
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    // Create a text button widget.
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    // Create a text button widget and set cmd string at same time.
00406 
00407    fLabel = new TGHotString(s);
00408    fFontStruct = font;
00409    fCommand = cmd;
00410 
00411    Init();
00412 }
00413 
00414 //______________________________________________________________________________
00415 void TGTextButton::Init()
00416 {
00417    // Common initialization used by the different ctors.
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; // center
00460    wattr.fWinGravity = 1;
00461    gVirtualX->ChangeWindowAttributes(fId, &wattr);
00462 
00463    SetWindowName();
00464 }
00465 
00466 //______________________________________________________________________________
00467 TGTextButton::~TGTextButton()
00468 {
00469    // Delete a text button widget.
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    // layout text button
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    // Set new button text.
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    // Set new button text.
00556 
00557    SetText(new TGHotString(new_label));
00558 }
00559 
00560 //______________________________________________________________________________
00561 void TGTextButton::SetTextJustify(Int_t mode)
00562 {
00563    // Set text justification. Mode is an OR of the bits:
00564    // kTextTop, kTextBottom, kTextLeft, kTextRight, kTextCenterX and
00565    // kTextCenterY.
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; //NorthWestGravity
00576          break;
00577       case kTextTop | kTextCenterX:
00578       case kTextTop:
00579          wattr.fBitGravity = 2; //NorthGravity
00580          break;
00581       case kTextTop | kTextRight:
00582          wattr.fBitGravity = 3; //NorthEastGravity
00583          break;
00584       case kTextLeft | kTextCenterY:
00585       case kTextLeft:
00586          wattr.fBitGravity = 4; //WestGravity
00587          break;
00588       case kTextCenterY | kTextCenterX:
00589          wattr.fBitGravity = 5; //CenterGravity
00590          break;
00591       case kTextRight | kTextCenterY:
00592       case kTextRight:
00593          wattr.fBitGravity = 6; //EastGravity
00594          break;
00595       case kTextBottom | kTextLeft:
00596          wattr.fBitGravity = 7; //SouthWestGravity
00597          break;
00598       case kTextBottom | kTextCenterX:
00599       case kTextBottom:
00600          wattr.fBitGravity = 8; //SouthGravity
00601          break;
00602       case kTextBottom | kTextRight:
00603          wattr.fBitGravity = 9; //SouthEastGravity
00604          break;
00605       default:
00606          wattr.fBitGravity = 5; //CenterGravity
00607          break;
00608    }
00609 
00610    gVirtualX->ChangeWindowAttributes(fId, &wattr);
00611    Layout();
00612 }
00613 
00614 //______________________________________________________________________________
00615 void TGTextButton::DoRedraw()
00616 {
00617    // Draw the text button.
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    // Handle key event. This function will be called when the hotkey is hit.
00672 
00673    Bool_t click = kFALSE;
00674    Bool_t was = !IsDown();   // kTRUE if button was off
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    // We don't need to check the key number as GrabKey will only
00687    // allow fHotchar events if Alt button is pressed (kKeyMod1Mask)
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 /*&& !allowRelease*/) 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    // returns default size
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    // Return default font structure.
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    // Changes text font.
00736    // If global is kTRUE font is changed globally, otherwise - locally.
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); // copy
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    // Changes text font specified by name.
00762    // If global is true color is changed globally, otherwise - locally.
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    // Changes text color.
00774    // If global is true color is changed globally, otherwise - locally.
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); // copy
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    // Returns kTRUE if text attributes are unique,
00793    // returns kFALSE if text attributes are shared (global).
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    // Create a picture button widget. The picture is not adopted and must
00803    // later be freed by the user once the picture button is deleted (a single
00804    // picture reference might be used by other buttons).
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); // *3
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    // Create a picture button widget and set action command. The picture is
00831    // not adopted and must later be freed by the user once the picture button
00832    // is deleted (a single picture reference might be used by other
00833    // buttons).
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); // *3
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    // Create a picture button. Where pic is the file name of the picture.
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); // *3
00876    }
00877    fPicD = 0;
00878    fOwnDisabledPic = kFALSE;
00879    SetWindowName();
00880 }
00881 
00882 //______________________________________________________________________________
00883 TGPictureButton::~TGPictureButton()
00884 {
00885    // Destructor.
00886 
00887    if (fOwnDisabledPic) fClient->FreePicture(fPicD);
00888 }
00889 
00890 //______________________________________________________________________________
00891 void TGPictureButton::SetPicture(const TGPicture *new_pic)
00892 {
00893    // Change a picture in a picture button. The picture is not adopted and
00894    // must later be freed by the user once the picture button is deleted
00895    // (a single picture reference might be used by other buttons).
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    // Redraw picture button.
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    // Creates disabled picture.
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    // Changes disabled picture.
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    // Create a check button widget. The hotstring will be adopted and deleted
00987    // by the check button.
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    // Create a check button widget.
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    // Create a check button widget.
01008 
01009    Init();
01010 }
01011 
01012 //______________________________________________________________________________
01013 void TGCheckButton::Init()
01014 {
01015    // Common check button initialization.
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    // Delete a check button.
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    // default size
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    // Set check button state.
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 /*wasUp*/)
01095 {
01096    // Emit signals.
01097 
01098    if (fState == kButtonUp)   Released();            // emit Released
01099    if (fState == kButtonDown) Pressed();             // emit Pressed
01100    Clicked();                                        // emit Clicked
01101    Toggled(fStateOn);                                // emit Toggled
01102 }
01103 
01104 //______________________________________________________________________________
01105 void TGCheckButton::PSetState(EButtonState state, Bool_t emit)
01106 {
01107    // Set check button state.
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          // button signals
01134          EmitSignals();
01135       }
01136       DoRedraw();
01137    }
01138 }
01139 
01140 //______________________________________________________________________________
01141 void TGCheckButton::SetDisabledAndSelected(Bool_t enable) 
01142 {
01143    // Set the state of a check button to disabled and either on or
01144    // off.
01145 
01146    if (!enable) {
01147       if (fState == kButtonDisabled && fStateOn) {
01148          PSetState(kButtonUp, kFALSE);         // enable button
01149          PSetState(kButtonUp, kFALSE);         // set button up
01150          PSetState(kButtonDisabled, kFALSE);   // disable button
01151       } else {
01152          PSetState(kButtonUp, kFALSE);
01153          PSetState(kButtonDisabled, kFALSE);
01154       }
01155    } else {
01156       PSetState(kButtonDown, kFALSE);          // set button down
01157       PSetState(kButtonDisabled, kFALSE);      // disable button
01158    }
01159 }
01160 
01161 //______________________________________________________________________________
01162 Bool_t TGCheckButton::HandleButton(Event_t *event)
01163 {
01164    // Handle mouse button event.
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    // We don't need to check the button number as GrabButton will
01176    // only allow button1 events
01177    if (event->fType == kButtonPress) {
01178       fgReleaseBtn = 0;
01179       if (in) {
01180          fOptions |= kSunkenFrame;
01181          Pressed();
01182       }
01183    } else { // ButtonRelease
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    // Handle mouse crossing event.
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    // Handle key event. This function will be called when the hotkey is hit.
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    // We don't need to check the key number as GrabKey will only
01251    // allow fHotchar events if Alt button is pressed (kKeyMod1Mask)
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    // Draw the check button widget.
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    // Return default font structure.
01323 
01324    if (!fgDefaultFont)
01325       fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
01326    return fgDefaultFont->GetFontStruct();
01327 }
01328 
01329 //______________________________________________________________________________
01330 const TGGC &TGCheckButton::GetDefaultGC()
01331 {
01332    // Return default graphics context.
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    // Create a radio button widget. The hotstring will be adopted and deleted
01346    // by the radio button.
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    // Create a radio button widget.
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    // Create a radio button widget.
01367 
01368    Init();
01369 }
01370 
01371 //______________________________________________________________________________
01372 void TGRadioButton::Init()
01373 {
01374    // Common radio button initialization.
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    // Delete a radio button.
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    // default size
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    // Set radio button state.
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    // Set the state of a radio button to disabled and either on or
01453    // off.
01454 
01455    if (!enable) {
01456       if (fState == kButtonDisabled && fStateOn) {
01457          PSetState(kButtonUp, kFALSE);         // enable button
01458          PSetState(kButtonUp, kFALSE);         // set button up
01459          PSetState(kButtonDisabled, kFALSE);   // disable button
01460       } else {
01461          PSetState(kButtonUp, kFALSE);
01462          PSetState(kButtonDisabled, kFALSE);
01463       }
01464    } else {
01465       PSetState(kButtonDown, kFALSE);          // set button down
01466       PSetState(kButtonDisabled, kFALSE);      // disable button
01467    }
01468 }
01469 
01470 //______________________________________________________________________________
01471 void TGRadioButton::EmitSignals(Bool_t /*wasUp*/)
01472 {
01473    // Emit signals.
01474 
01475    if (fState == kButtonUp) Released();              // emit Released
01476    if (fState == kButtonDown) Pressed();             // emit Pressed
01477    Clicked();                                        // emit Clicked
01478    Toggled(fStateOn);                                // emit Toggled
01479 }
01480 
01481 //______________________________________________________________________________
01482 void TGRadioButton::PSetState(EButtonState state, Bool_t emit)
01483 {
01484    // Set radio button state.
01485 
01486    if (state != fState) {
01487       //      fPrevState = fState = state;
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          // button signals
01512          EmitSignals();
01513       }
01514       DoRedraw();
01515    }
01516 }
01517 
01518 //______________________________________________________________________________
01519 Bool_t TGRadioButton::HandleButton(Event_t *event)
01520 {
01521    // Handle mouse button event.
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) { // button pressed
01535       fgReleaseBtn = 0;
01536       if (in) {
01537          fOptions |= kSunkenFrame;
01538          Pressed();
01539       }
01540    } else { // ButtonRelease
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    // Handle mouse crossing event.
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    // Handle key event. This function will be called when the hotkey is hit.
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    // We don't need to check the key number as GrabKey will only
01612    // allow fHotchar events if Alt button is pressed (kKeyMod1Mask)
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    // Draw a radio button.
01630 
01631    Int_t tx, ty, y0;
01632 
01633    TGFrame::DoRedraw();
01634 
01635    tx = 20;
01636    ty = (fHeight - fTHeight) >> 1;
01637 
01638 //   pw = 12;
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    // Return default font structure.
01681 
01682    if (!fgDefaultFont)
01683       fgDefaultFont = gClient->GetResourcePool()->GetDefaultFont();
01684    return fgDefaultFont->GetFontStruct();
01685 }
01686 
01687 //______________________________________________________________________________
01688 const TGGC &TGRadioButton::GetDefaultGC()
01689 {
01690    // Return default graphics context.
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    // Save a button widget as a C++ statement(s) on output stream out.
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    // Save a text button widget as a C++ statement(s) on output stream out.
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    // font + GC
01747    option = GetName()+5;         // unique digit id of the name
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    // Save a picture button widget as a C++ statement(s) on output stream out.
01805 
01806    if (!fPic) {
01807       Error("SavePrimitive()", "pixmap not found for picture button %d ", fWidgetId);
01808       return;
01809    }
01810 
01811    // GC
01812    option = GetName()+5;         // unique digit id of the name
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    // Save a check button widget as a C++ statement(s) on output stream out.
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    // font + GC
01869    option = GetName()+5;         // unique digit id of the name
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    // Save a radio button widget as a C++ statement(s) on output stream out.
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    // font + GC
01937    option = GetName()+5;         // unique digit id of the name
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    // Create a menu button widget. The hotstring will be adopted and
01994    // deleted by the menu button. This constructior creates a
01995    // menubutton with a popup menu attached that appears when the
01996    // button for it is clicked. The popup menu is adopted.
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    // Find and set the correct size for the menu and the button.
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    // Save the id of the 1st item on the menu.
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    // An additional connection that is needed.
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    // Common initialization used by the different ctors.
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; // center
02116    wattr.fWinGravity = 1;
02117    gVirtualX->ChangeWindowAttributes(fId, &wattr);
02118 
02119    // Make sure motion is detected too.
02120    AddInput(kPointerMotionMask | kEnterWindowMask | kLeaveWindowMask);
02121 
02122    SetWindowName();
02123 }
02124 
02125 //______________________________________________________________________________
02126 TGSplitButton::~TGSplitButton()
02127 {
02128    // Delete a split button widget.
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    // Draw triangle (arrow) on which user can click to open Popup.
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    // Calculate the size of the button.
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    // Handle mouse button event in case the button is split.
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    // We don't need to check the button number as GrabButton will
02186    // only allow button1 events
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 { // ButtonRelease
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 { // ButtonRelease
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);  // ungrab pointer
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 { // ButtonRelease
02259          if(outpress) {
02260             outpress = kFALSE;
02261             SetMBState(kButtonUp);
02262             SetMenuState(kFALSE);
02263             gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);  // ungrab pointer
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    //   if (mbclick) {
02288    //      MBClicked();
02289    //      SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
02290    //             (Long_t) fUserData);
02291    //      fClient->ProcessLine(fCommand, MK_MSG(kC_COMMAND, kCM_BUTTON), fWidgetId,
02292    //                      (Long_t) fUserData);
02293    // }
02294    return kTRUE;
02295 }
02296 
02297 //______________________________________________________________________________
02298 Bool_t TGSplitButton::HandleSCrossing(Event_t *event)
02299 {
02300    // Handle mouse crossing event in case of split menu.
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    //   Bool_t inMB = (event->fX >= (Int_t)(fWidth -fMBWidth)) && (event->fY >= 0) &&
02319    //      (event->fX <= (Int_t)fWidth) && (event->fY <= (Int_t)fHeight);
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       // kLeaveNotify
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    // Handle key event. This function will be called when the hotkey is hit.
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    // We don't need to check the key number as GrabKey will only
02357    // allow fHotchar events if Alt button is pressed (kKeyMod1Mask)
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    // Popup the attached menu. 
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       // place the menu just under the window:
02417       fPopMenu->PlaceMenu(ax-1, ay+fHeight, kTRUE, kFALSE); //kTRUE);
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    // Draw the text button.
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    // Draw the parts of the button needed when a menu is attached.
02484    
02485    // triangle position
02486    x = fWidth - 11;
02487    y = fHeight - 10;
02488    
02489    if (fSplit) {
02490       // separator position
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    // If on kTRUE bind arrow, popup menu hot keys, otherwise
02535    // remove key bindings.
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    // If on kTRUE bind Menu hot keys, otherwise remove key bindings.
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    // returns default size
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    // Set new button text.
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    // Set new button text.
02651 
02652    SetText(new TGHotString(new_label));
02653 }
02654 
02655 //______________________________________________________________________________
02656 void TGSplitButton::SetFont(FontStruct_t font, Bool_t global)
02657 {
02658    // Changes text font.
02659    // If global is kTRUE font is changed globally, otherwise - locally.
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); // copy
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    // Changes text font specified by name.
02686    // If global is true color is changed globally, otherwise - locally.
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    // Set the state of the Menu Button part
02698    
02699    if (state != fMBState) {
02700       fMBState = state;
02701       DoRedraw();
02702    }
02703 }
02704 
02705 //______________________________________________________________________________
02706 void TGSplitButton::SetSplit(Bool_t split)
02707 {
02708    // Set the split status of a button.
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    // Handle button events.
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 { // ButtonRelease
02768          if (fState == kButtonEngaged) {
02769             SetState(kButtonUp);
02770             SetMenuState(kFALSE);
02771             Released();
02772             click = kTRUE;
02773             gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);  // ungrab pointer
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 { // ButtonRelease
02792          SetState(kButtonUp);
02793          SetMenuState(kFALSE);
02794          gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);  // ungrab pointer
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    // Handle mouse crossing event.
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    // Handle key event. This function will be called when the hotkey is hit.
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    // We don't need to check the key number as GrabKey will only
02854    // allow fHotchar events if Alt button is pressed (kKeyMod1Mask)
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    // Handle a motion event in a TGSplitButton.
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    // layout text button
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    // Handle a menu item activation.
03029    
03030    SetMenuState(kFALSE);
03031 
03032    if (fSplit) {
03033       SetMBState(kButtonUp);
03034       Disconnect(this, "Clicked()", this);
03035       // connect clicked to the ItemClicked signal with the correct id
03036       Connect("Clicked()", "TGSplitButton", this, 
03037               TString::Format("ItemClicked(=%d)", id));
03038 
03039       // reenable hidden entries
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 }

Generated on Tue Jul 5 14:21:56 2011 for ROOT_528-00b_version by  doxygen 1.5.1