TGNumberEntry.cxx

Go to the documentation of this file.
00001 // @(#)root/gui:$Id: TGNumberEntry.cxx 35582 2010-09-22 13:38:27Z bellenot $
00002 // Author: Daniel Sigg   03/09/2001
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2001, 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 //                                                                      //
00014 // TGNumberEntry, TGNumberEntryField and TGNumberFormat                 //
00015 //                                                                      //
00016 // TGNumberEntry is a number entry input widget with up/down buttons.   //
00017 // TGNumberEntryField is a number entry input widget.                   //
00018 // TGNumberFormat contains enum types to specify the numeric format.    //
00019 //                                                                      //
00020 // The number entry widget is based on TGTextEntry but allows only      //
00021 // numerical input. The widget support numerous formats including       //
00022 // integers, hex numbers, real numbers, fixed fraction reals and        //
00023 // time/date formats. The widget also allows to restrict input values   //
00024 // to non-negative or positive numbers and to specify explicit limits.  //
00025 //                                                                      //
00026 // The following styles are supported:                                  //
00027 // kNESInteger:        integer number                                   //
00028 // kNESRealOne:        real number with one digit (no exponent)         //
00029 // kNESRealTwo:        real number with two digits (no exponent)        //
00030 // kNESRealThree:      real number with three digits (no exponent)      //
00031 // kNESRealFour:       real number with four digits (no exponent)       //
00032 // kNESReal:           arbitrary real number                            //
00033 // kNESDegree:         angle in degree:minutes:seconds format           //
00034 // kNESMinSec:         time in minutes:seconds format                   //
00035 // kNESHourMin:        time in hour:minutes format                      //
00036 // kNESHourMinSec:     time in hour:minutes:seconds format              //
00037 // kNESDayMYear:       date in day/month/year format                    //
00038 // kNESMDayYear:       date in month/day/year format                    //
00039 // kNESHex:            hex number                                       //
00040 //                                                                      //
00041 // The following attributes can be specified:                           //
00042 // kNEAAnyNumber:      any number is allowed                            //
00043 // kNEANonNegative:    only non-negative numbers are allowed            //
00044 // kNEAPositive:       only positive numbers are allowed                //
00045 //                                                                      //
00046 // Explicit limits can be specified individually:                       //
00047 // kNELNoLimits:       no limits                                        //
00048 // kNELLimitMin:       lower limit only                                 //
00049 // kNELLimitMax        upper limit only                                 //
00050 // kNELLimitMinMax     both lower and upper limits                      //
00051 //                                                                      //
00052 // TGNumberEntryField is a plain vanilla entry field, whereas           //
00053 // TGNumberEntry adds two small buttons to increase and decrease the    //
00054 // numerical value in the field. The number entry widgets also support  //
00055 // using the up and down cursor keys to change the numerical values.    //
00056 // The step size can be selected with control and shift keys:           //
00057 // --                  small step (1 unit/factor of 3)                  //
00058 // shift               medium step (10 units/factor of 10)              //
00059 // control             large step (100 units/factor of 30)              //
00060 // shift-control       huge step (1000 units/factor of 100)             //
00061 //                                                                      //
00062 // The steps are either linear or logarithmic. The default behaviour    //
00063 // is set when the entry field is created, but it can be changed by     //
00064 // pressing the alt key at the same time.                               //
00065 //                                                                      //
00066 // Changing the number in the widget will generate the event:           //
00067 // kC_TEXTENTRY, kTE_TEXTCHANGED, widget id, 0.                         //
00068 // Hitting the enter key will generate:                                 //
00069 // kC_TEXTENTRY, kTE_ENTER, widget id, 0.                               //
00070 // Hitting the tab key will generate:                                   //
00071 // kC_TEXTENTRY, kTE_TAB, widget id, 0.                                 //
00072 //                                                                      //
00073 //Begin_Html
00074 /*
00075 <img src="numberentry.jpg">
00076 */
00077 //End_Html
00078 //
00079 
00080 #include "TGNumberEntry.h"
00081 #include "KeySymbols.h"
00082 #include "TTimer.h"
00083 #include "TSystem.h"
00084 #include "TGToolTip.h"
00085 #include "TMath.h"
00086 #include "Riostream.h"
00087 #include <ctype.h>
00088 
00089 
00090 ClassImp(TGNumberFormat);
00091 ClassImp(TGNumberEntryField);
00092 ClassImp(TGNumberEntryLayout);
00093 ClassImp(TGNumberEntry);
00094 
00095 
00096 
00097 //////////////////////////////////////////////////////////////////////////
00098 //                                                                      //
00099 // Miscellanous routines for handling numeric values <-> strings        //
00100 //                                                                      //
00101 //////////////////////////////////////////////////////////////////////////
00102 
00103 //______________________________________________________________________________
00104 enum ERealStyle {         // Style of real
00105    kRSInt = 0,            // Integer
00106    kRSFrac = 1,           // Fraction only
00107    kRSExpo = 2,           // Exponent only
00108    kRSFracExpo = 3        // Fraction and Exponent
00109 };
00110 
00111 //______________________________________________________________________________
00112 struct RealInfo_t {
00113    ERealStyle fStyle;     // Style of real
00114    Int_t fFracDigits;     // Number of fractional digits
00115    Int_t fFracBase;       // Base of fractional digits
00116    Int_t fIntNum;         // Integer number
00117    Int_t fFracNum;        // Fraction
00118    Int_t fExpoNum;        // Exponent
00119    Int_t fSign;           // Sign
00120 };
00121 
00122 //______________________________________________________________________________
00123 const Double_t kEpsilon = 1E-12;
00124 
00125 //______________________________________________________________________________
00126 const Int_t kDays[13] =
00127     { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00128 
00129 //______________________________________________________________________________
00130 static Long_t Round(Double_t x)
00131 {
00132    if (x > 0) {
00133       return (Long_t) (x + 0.5);
00134    } else if (x < 0) {
00135       return (Long_t) (x - 0.5);
00136    } else {
00137       return 0;
00138    }
00139 }
00140 
00141 //______________________________________________________________________________
00142 static Long_t Truncate(Double_t x)
00143 {
00144    if (x > 0) {
00145       return (Long_t) (x + kEpsilon);
00146    } else if (x < 0) {
00147       return (Long_t) (x - kEpsilon);
00148    } else {
00149       return 0;
00150    }
00151 }
00152 
00153 //______________________________________________________________________________
00154 static Bool_t IsLeapYear(Int_t year)
00155 {
00156    return ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)));
00157 }
00158 
00159 //______________________________________________________________________________
00160 static Bool_t IsGoodChar(char c, TGNumberFormat::EStyle style,
00161                          TGNumberFormat::EAttribute attr)
00162 {
00163    if (isdigit(c)) {
00164       return kTRUE;
00165    }
00166    if (isxdigit(c) && (style == TGNumberFormat::kNESHex)) {
00167       return kTRUE;
00168    }
00169    if ((c == '-') && (style == TGNumberFormat::kNESInteger) &&
00170        (attr == TGNumberFormat::kNEAAnyNumber)) {
00171       return kTRUE;
00172    }
00173    if ((c == '-') &&
00174        ((style == TGNumberFormat::kNESRealOne) ||
00175         (style == TGNumberFormat::kNESRealTwo) ||
00176         (style == TGNumberFormat::kNESRealThree) ||
00177         (style == TGNumberFormat::kNESRealFour) ||
00178         (style == TGNumberFormat::kNESReal) ||
00179         (style == TGNumberFormat::kNESDegree) ||
00180         (style == TGNumberFormat::kNESMinSec)) &&
00181        (attr == TGNumberFormat::kNEAAnyNumber)) {
00182       return kTRUE;
00183    }
00184    if ((c == '-') && (style == TGNumberFormat::kNESReal)) {
00185       return kTRUE;
00186    }
00187    if (((c == '.') || (c == ',')) &&
00188        ((style == TGNumberFormat::kNESRealOne) ||
00189         (style == TGNumberFormat::kNESRealTwo) ||
00190         (style == TGNumberFormat::kNESRealThree) ||
00191         (style == TGNumberFormat::kNESRealFour) ||
00192         (style == TGNumberFormat::kNESReal) ||
00193         (style == TGNumberFormat::kNESDegree) ||
00194         (style == TGNumberFormat::kNESMinSec) ||
00195         (style == TGNumberFormat::kNESHourMin) ||
00196         (style == TGNumberFormat::kNESHourMinSec) ||
00197         (style == TGNumberFormat::kNESDayMYear) ||
00198         (style == TGNumberFormat::kNESMDayYear))) {
00199       return kTRUE;
00200    }
00201    if ((c == ':') &&
00202        ((style == TGNumberFormat::kNESDegree) ||
00203         (style == TGNumberFormat::kNESMinSec) ||
00204         (style == TGNumberFormat::kNESHourMin) ||
00205         (style == TGNumberFormat::kNESHourMinSec) ||
00206         (style == TGNumberFormat::kNESDayMYear) ||
00207         (style == TGNumberFormat::kNESMDayYear))) {
00208       return kTRUE;
00209    }
00210    if ((c == '/') &&
00211        ((style == TGNumberFormat::kNESDayMYear) ||
00212         (style == TGNumberFormat::kNESMDayYear))) {
00213       return kTRUE;
00214    }
00215    if (((c == 'e') || (c == 'E')) && (style == TGNumberFormat::kNESReal)) {
00216       return kTRUE;
00217    }
00218    return kFALSE;
00219 }
00220 
00221 //______________________________________________________________________________
00222 static char *EliminateGarbage(char *text,
00223                               TGNumberFormat::EStyle style,
00224                               TGNumberFormat::EAttribute attr)
00225 {
00226    if (text == 0) {
00227       return 0;
00228    }
00229    for (Int_t i = strlen(text) - 1; i >= 0; i--) {
00230       if (!IsGoodChar(text[i], style, attr)) {
00231          memmove(text + i, text + i + 1, strlen(text) - i);
00232       }
00233    }
00234    return text;
00235 }
00236 
00237 //______________________________________________________________________________
00238 static Long_t IntStr(const char *text)
00239 {
00240    Long_t l = 0;
00241    Int_t sign = 1;
00242    for (UInt_t i = 0; i < strlen(text); i++) {
00243       if (text[i] == '-') {
00244          sign = -1;
00245       } else if ((isdigit(text[i])) && (l < kMaxLong)) {
00246          l = 10 * l + (text[i] - '0');
00247       }
00248    }
00249    return sign * l;
00250 }
00251 
00252 //______________________________________________________________________________
00253 static char *StrInt(char *text, Long_t i, Int_t digits)
00254 {
00255    snprintf(text, 250, "%li", TMath::Abs(i));
00256    TString s = text;
00257    while (digits > s.Length()) {
00258       s = "0" + s;
00259    }
00260    if (i < 0) {
00261       s = "-" + s;
00262    }
00263    strlcpy(text, (const char *) s, 250);
00264    return text;
00265 }
00266 
00267 //______________________________________________________________________________
00268 static TString StringInt(Long_t i, Int_t digits)
00269 {
00270    char text[256];
00271    StrInt(text, i, digits);
00272    return TString(text);
00273 }
00274 
00275 //______________________________________________________________________________
00276 static char *RealToStr(char *text, const RealInfo_t & ri)
00277 {
00278    char *p = text;
00279    if (text == 0) {
00280       return 0;
00281    }
00282    strlcpy(p, "", 256);
00283    if (ri.fSign < 0) {
00284       strlcpy(p, "-", 256);
00285       p++;
00286    }
00287    StrInt(p, TMath::Abs(ri.fIntNum), 0);
00288    p += strlen(p);
00289    if ((ri.fStyle == kRSFrac) || (ri.fStyle == kRSFracExpo)) {
00290       strlcpy(p, ".", 256-strlen(p));
00291       p++;
00292       StrInt(p, TMath::Abs(ri.fFracNum), ri.fFracDigits);
00293       p += strlen(p);
00294    }
00295    if ((ri.fStyle == kRSExpo) || (ri.fStyle == kRSFracExpo)) {
00296       strlcpy(p, "e", 256-strlen(p));
00297       p++;
00298       StrInt(p, ri.fExpoNum, 0);
00299       p += strlen(p);
00300    }
00301    return text;
00302 }
00303 
00304 //______________________________________________________________________________
00305 static Double_t StrToReal(const char *text, RealInfo_t & ri)
00306 {
00307    char *s;
00308    char *frac;
00309    char *expo;
00310    char *minus;
00311    char buf[256];
00312 
00313    if ((text == 0) || (strlen(text) == 0)) {
00314       ri.fStyle = kRSInt;
00315       ri.fIntNum = 0;
00316       ri.fSign = 1;
00317       return 0.0;
00318    }
00319    strlcpy(buf, text, sizeof(buf));
00320    s = buf;
00321    frac = strchr(s, '.');
00322    if (frac == 0) {
00323       frac = strchr(s, ',');
00324    }
00325    expo = strchr(s, 'e');
00326    minus = strchr(s, '-');
00327    if (expo == 0) {
00328       expo = strchr(s, 'E');
00329    }
00330    if ((frac != 0) && (expo != 0) && (frac > expo)) {
00331       frac = 0;
00332    }
00333    if ((minus != 0) && ((expo == 0) || (minus < expo))) {
00334       ri.fSign = -1;
00335    } else {
00336       ri.fSign = 1;
00337    }
00338    if ((frac == 0) && (expo == 0)) {
00339       ri.fStyle = kRSInt;
00340    } else if (frac == 0) {
00341       ri.fStyle = kRSExpo;
00342    } else if (expo == 0) {
00343       ri.fStyle = kRSFrac;
00344    } else {
00345       ri.fStyle = kRSFracExpo;
00346    }
00347    if (frac != 0) {
00348       *frac = 0;
00349       frac++;
00350    }
00351    if (expo != 0) {
00352       *expo = 0;
00353       expo++;
00354    }
00355    ri.fIntNum = TMath::Abs(IntStr(s));
00356    if (expo != 0) {
00357       ri.fExpoNum = IntStr(expo);
00358    } else {
00359       ri.fExpoNum = 0;
00360    }
00361    if (ri.fExpoNum > 999) {
00362       ri.fExpoNum = 999;
00363    }
00364    if (ri.fExpoNum < -999) {
00365       ri.fExpoNum = -999;
00366    }
00367    ri.fFracDigits = 0;
00368    ri.fFracBase = 1;
00369    ri.fFracNum = 0;
00370    if (frac != 0) {
00371       for (UInt_t i = 0; i < strlen(frac); i++) {
00372          if (isdigit(frac[i])) {
00373             if (ri.fFracNum < kMaxInt) {
00374                ri.fFracNum = 10 * ri.fFracNum + (frac[i] - '0');
00375                ri.fFracDigits++;
00376                ri.fFracBase *= 10;
00377             }
00378          }
00379       }
00380    }
00381    if ((ri.fFracDigits == 0) && (ri.fStyle == kRSFrac)) {
00382       ri.fStyle = kRSInt;
00383    }
00384    if ((ri.fFracDigits == 0) && (ri.fStyle == kRSFracExpo)) {
00385       ri.fStyle = kRSExpo;
00386    }
00387    switch (ri.fStyle) {
00388    case kRSInt:
00389       return ri.fSign * ri.fIntNum;
00390    case kRSFrac:
00391       return ri.fSign *
00392           (ri.fIntNum + (Double_t) ri.fFracNum / ri.fFracBase);
00393    case kRSExpo:
00394       return ri.fSign * (ri.fIntNum * TMath::Power(10, ri.fExpoNum));
00395    case kRSFracExpo:
00396       return ri.fSign * (ri.fIntNum +
00397                          (Double_t) ri.fFracNum / ri.fFracBase) *
00398           TMath::Power(10, ri.fExpoNum);
00399    }
00400    return 0;
00401 }
00402 
00403 //______________________________________________________________________________
00404 static ULong_t HexStrToInt(const char *s)
00405 {
00406    ULong_t w = 0;
00407    for (UInt_t i = 0; i < strlen(s); i++) {
00408       if ((s[i] >= '0') && (s[i] <= '9')) {
00409          w = 16 * w + (s[i] - '0');
00410       } else if ((toupper(s[i]) >= 'A') && (toupper(s[i]) <= 'F')) {
00411          w = 16 * w + (toupper(s[i]) - 'A' + 10);
00412       }
00413    }
00414    return w;
00415 }
00416 
00417 //______________________________________________________________________________
00418 static char *IntToHexStr(char *text, ULong_t l)
00419 {
00420    const char *const digits = "0123456789ABCDEF";
00421    char buf[64];
00422    char *p = buf + 62;
00423    strcpy(p, "");
00424    while (l > 0) {
00425       *(--p) = digits[l % 16];
00426       l /= 16;
00427    }
00428    if (strlen(p) == 0) {
00429       strcpy(text, "0");
00430    } else {
00431       strcpy(text, p);
00432    }
00433    return text;
00434 }
00435 
00436 //______________________________________________________________________________
00437 static char *MIntToStr(char *text, Long_t l, Int_t digits)
00438 {
00439    TString s;
00440    Int_t base;
00441    switch (digits) {
00442    case 0:
00443       base = 1;
00444       break;
00445    case 1:
00446       base = 10;
00447       break;
00448    case 2:
00449       base = 100;
00450       break;
00451    case 3:
00452       base = 1000;
00453       break;
00454    default:
00455    case 4:
00456       base = 10000;
00457       break;
00458    }
00459    s = StringInt(TMath::Abs(l) / base, 0) + "." +
00460        StringInt(TMath::Abs(l) % base, digits);
00461    if (l < 0) {
00462       s = "-" + s;
00463    }
00464    strlcpy(text, (const char *) s, 256);
00465    return text;
00466 }
00467 
00468 //______________________________________________________________________________
00469 static char *DIntToStr(char *text, Long_t l, Bool_t Sec, char Del)
00470 {
00471    TString s;
00472    if (Sec) {
00473       s = StringInt(TMath::Abs(l) / 3600, 0) + Del +
00474           StringInt((TMath::Abs(l) % 3600) / 60, 2) + Del +
00475           StringInt(TMath::Abs(l) % 60, 2);
00476    } else {
00477       s = StringInt(TMath::Abs(l) / 60, 0) + Del +
00478           StringInt(TMath::Abs(l) % 60, 2);
00479    }
00480    if (l < 0) {
00481       s = "-" + s;
00482    }
00483    strlcpy(text, (const char *) s, 256);
00484    return text;
00485 }
00486 
00487 //______________________________________________________________________________
00488 static void GetNumbers(const char *s, Int_t & Sign,
00489                        Long_t & n1, Int_t maxd1,
00490                        Long_t & n2, Int_t maxd2,
00491                        Long_t & n3, Int_t maxd3, const char *Delimiters)
00492 {
00493    Long_t n;
00494    Long_t d = 0;
00495    Sign = +1;
00496    n1 = 0;
00497    n2 = 0;
00498    n3 = 0;
00499    if (*s == '-') {
00500       Sign = -1;
00501       s++;
00502    }
00503    if (!isdigit(*s) && !strchr(Delimiters, *s)) {
00504       return;
00505    }
00506    while ((*s != 0) && ((strchr(Delimiters, *s) == 0) || (maxd2 == 0))) {
00507       if (isdigit(*s) && (d < maxd1)) {
00508          if (n1 < kMaxLong) {
00509             n1 = 10 * n1 + (*s - '0');
00510          }
00511          d++;
00512       }
00513       s++;
00514    }
00515    if (strcspn(s, Delimiters) == strlen(s)) {
00516       return;
00517    }
00518    Int_t dummy = 0;
00519    GetNumbers(s + 1, dummy, n2, maxd2, n3, maxd3, n, d, Delimiters);
00520 }
00521 
00522 //______________________________________________________________________________
00523 static Long_t GetSignificant(Long_t l, Int_t Max)
00524 {
00525    while (TMath::Abs(l) >= Max) {
00526       l /= 10;
00527    }
00528    return l;
00529 }
00530 
00531 //______________________________________________________________________________
00532 static void AppendFracZero(char *text, Int_t digits)
00533 {
00534    char *p;
00535    Int_t found = 0;
00536    p = strchr(text, '.');
00537    if (p == 0) {
00538       p = strchr(text, ',');
00539    }
00540    if (p == 0) {
00541       return;
00542    }
00543    p++;
00544    for (UInt_t i = 0; i < strlen(p); i++) {
00545       if (isdigit(*p)) {
00546          found++;
00547       }
00548    }
00549    while (found < digits) {
00550       strcpy(p + strlen(p), "0");
00551       found++;
00552    }
00553 }
00554 
00555 //______________________________________________________________________________
00556 static Long_t MakeDateNumber(const char * /*text*/, Long_t Day,
00557                              Long_t Month, Long_t Year)
00558 {
00559    // Create a number entry with year/month/day information.
00560 
00561    Day = TMath::Abs(Day);
00562    Month = TMath::Abs(Month);
00563    Year = TMath::Abs(Year);
00564    if (Year < 100) {
00565       Year += 2000;
00566    }
00567    Month = GetSignificant(Month, 100);
00568    if (Month > 12)
00569       Month = 12;
00570    if (Month == 0)
00571       Month = 1;
00572    Day = GetSignificant(Day, 100);
00573    if (Day == 0)
00574       Day = 1;
00575    if (Day > kDays[Month])
00576       Day = kDays[Month];
00577    if ((Month == 2) && (Day > 28) && !IsLeapYear(Year))
00578       Day = 28;
00579    return 10000 * Year + 100 * Month + Day;
00580 }
00581 
00582 //______________________________________________________________________________
00583 static Long_t TranslateToNum(const char *text,
00584                              TGNumberFormat::EStyle style, RealInfo_t & ri)
00585 {
00586    // Translate a string to a number value.
00587 
00588    Long_t n1;
00589    Long_t n2;
00590    Long_t n3;
00591    Int_t sign;
00592    switch (style) {
00593    case TGNumberFormat::kNESInteger:
00594       GetNumbers(text, sign, n1, 12, n2, 0, n3, 0, "");
00595       return sign * n1;
00596    case TGNumberFormat::kNESRealOne:
00597       GetNumbers(text, sign, n1, 12, n2, 1, n3, 0, ".,");
00598       return sign * (10 * n1 + GetSignificant(n2, 10));
00599    case TGNumberFormat::kNESRealTwo:
00600       {
00601          char buf[256];
00602          strlcpy(buf, text, sizeof(buf));
00603          AppendFracZero(buf, 2);
00604          GetNumbers(buf, sign, n1, 12, n2, 2, n3, 0, ".,");
00605          return sign * (100 * n1 + GetSignificant(n2, 100));
00606       }
00607    case TGNumberFormat::kNESRealThree:
00608       {
00609          char buf[256];
00610          strlcpy(buf, text, sizeof(buf));
00611          AppendFracZero(buf, 3);
00612          GetNumbers(buf, sign, n1, 12, n2, 3, n3, 0, ".,");
00613          return sign * (1000 * n1 + GetSignificant(n2, 1000));
00614       }
00615    case TGNumberFormat::kNESRealFour:
00616       {
00617          char buf[256];
00618          strlcpy(buf, text, sizeof(buf));
00619          AppendFracZero(buf, 4);
00620          GetNumbers(buf, sign, n1, 12, n2, 4, n3, 0, ".,");
00621          return sign * (10000 * n1 + GetSignificant(n2, 10000));
00622       }
00623    case TGNumberFormat::kNESReal:
00624       return (Long_t) StrToReal(text, ri);
00625    case TGNumberFormat::kNESDegree:
00626       GetNumbers(text, sign, n1, 12, n2, 2, n3, 2, ".,:");
00627       return sign * (3600 * n1 + 60 * GetSignificant(n2, 60) +
00628                      GetSignificant(n3, 60));
00629    case TGNumberFormat::kNESHourMinSec:
00630       GetNumbers(text, sign, n1, 12, n2, 2, n3, 2, ".,:");
00631       return 3600 * n1 + 60 * GetSignificant(n2, 60) +
00632           GetSignificant(n3, 60);
00633    case TGNumberFormat::kNESMinSec:
00634       GetNumbers(text, sign, n1, 12, n2, 2, n3, 0, ".,:");
00635       return sign * (60 * n1 + GetSignificant(n2, 60));
00636    case TGNumberFormat::kNESHourMin:
00637       GetNumbers(text, sign, n1, 12, n2, 2, n3, 0, ".,:");
00638       return 60 * n1 + GetSignificant(n2, 60);
00639    case TGNumberFormat::kNESDayMYear:
00640       GetNumbers(text, sign, n1, 2, n2, 2, n3, 4, ".,/");
00641       return MakeDateNumber(text, n1, n2, n3);
00642    case TGNumberFormat::kNESMDayYear:
00643       GetNumbers(text, sign, n2, 2, n1, 2, n3, 4, ".,/");
00644       return MakeDateNumber(text, n1, n2, n3);
00645    case TGNumberFormat::kNESHex:
00646       return HexStrToInt(text);
00647    }
00648    return 0;
00649 }
00650 
00651 //______________________________________________________________________________
00652 static char *TranslateToStr(char *text, Long_t l,
00653                             TGNumberFormat::EStyle style, const RealInfo_t & ri)
00654 {
00655    // Translate a number value to a string.
00656 
00657    switch (style) {
00658    case TGNumberFormat::kNESInteger:
00659       return StrInt(text, l, 0);
00660    case TGNumberFormat::kNESRealOne:
00661       return MIntToStr(text, l, 1);
00662    case TGNumberFormat::kNESRealTwo:
00663       return MIntToStr(text, l, 2);
00664    case TGNumberFormat::kNESRealThree:
00665       return MIntToStr(text, l, 3);
00666    case TGNumberFormat::kNESRealFour:
00667       return MIntToStr(text, l, 4);
00668    case TGNumberFormat::kNESReal:
00669       return RealToStr(text, ri);
00670    case TGNumberFormat::kNESDegree:
00671       return DIntToStr(text, l, kTRUE, '.');
00672    case TGNumberFormat::kNESHourMinSec:
00673       return DIntToStr(text, l % (24 * 3600), kTRUE, ':');
00674    case TGNumberFormat::kNESMinSec:
00675       return DIntToStr(text, l, kFALSE, ':');
00676    case TGNumberFormat::kNESHourMin:
00677       return DIntToStr(text, l % (24 * 60), kFALSE, ':');
00678    case TGNumberFormat::kNESDayMYear:
00679       {
00680          TString date =
00681              StringInt(TMath::Abs(l) % 100, 0) + "/" +
00682              StringInt((TMath::Abs(l) / 100) % 100, 0) + "/" +
00683              StringInt(TMath::Abs(l) / 10000, 0);
00684          strlcpy(text, (const char *) date, 256);
00685          return text;
00686       }
00687    case TGNumberFormat::kNESMDayYear:
00688       {
00689          TString date =
00690              StringInt((TMath::Abs(l) / 100) % 100, 0) + "/" +
00691              StringInt(TMath::Abs(l) % 100, 0) + "/" +
00692              StringInt(TMath::Abs(l) / 10000, 0);
00693          strlcpy(text, (const char *) date, 256);
00694          return text;
00695       }
00696    case TGNumberFormat::kNESHex:
00697       return IntToHexStr(text, (ULong_t) l);
00698    }
00699    return 0;
00700 }
00701 
00702 //______________________________________________________________________________
00703 static Double_t RealToDouble(const RealInfo_t ri)
00704 {
00705    // Convert to double format.
00706 
00707    switch (ri.fStyle) {
00708       // Integer type real
00709    case kRSInt:
00710       return (Double_t) ri.fSign * ri.fIntNum;
00711       // Fraction type real
00712    case kRSFrac:
00713       return (Double_t) ri.fSign * ((Double_t) TMath::Abs(ri.fIntNum) +
00714                                     (Double_t) ri.fFracNum / ri.fFracBase);
00715       // Exponent only
00716    case kRSExpo:
00717       return (Double_t) ri.fSign * ri.fIntNum *
00718           TMath::Power(10, ri.fExpoNum);
00719       // Fraction and exponent
00720    case kRSFracExpo:
00721       return (Double_t) ri.fSign * ((Double_t) TMath::Abs(ri.fIntNum) +
00722                                     (Double_t) ri.fFracNum /
00723                                     ri.fFracBase) * TMath::Power(10,
00724                                                                  ri.fExpoNum);
00725    }
00726    return 0;
00727 }
00728 
00729 //______________________________________________________________________________
00730 static void CheckMinMax(Long_t & l, TGNumberFormat::EStyle style,
00731                         TGNumberFormat::ELimit limits,
00732                         Double_t min, Double_t max)
00733 {
00734    // Check min/max limits for the set value.
00735 
00736    if ((limits == TGNumberFormat::kNELNoLimits) ||
00737        (style == TGNumberFormat::kNESReal)) {
00738       return;
00739    }
00740    // check min
00741    if ((limits == TGNumberFormat::kNELLimitMin) ||
00742        (limits == TGNumberFormat::kNELLimitMinMax)) {
00743       Long_t lower;
00744       switch (style) {
00745       case TGNumberFormat::kNESRealOne:
00746          lower = Round(10.0 * min);
00747          break;
00748       case TGNumberFormat::kNESRealTwo:
00749          lower = Round(100.0 * min);
00750          break;
00751       case TGNumberFormat::kNESRealThree:
00752          lower = Round(1000.0 * min);
00753          break;
00754       case TGNumberFormat::kNESRealFour:
00755          lower = Round(10000.0 * min);
00756          break;
00757       case TGNumberFormat::kNESHex:
00758          lower = (ULong_t) Round(min);
00759          break;
00760       default:
00761          lower = Round(min);
00762          break;
00763       }
00764       if (style != TGNumberFormat::kNESHex) {
00765          if (l < lower)
00766             l = lower;
00767       } else {
00768          if (lower < 0)
00769             lower = 0;
00770          if ((ULong_t) l < (ULong_t) lower)
00771             l = lower;
00772       }
00773    }
00774    // check max
00775    if ((limits == TGNumberFormat::kNELLimitMax) ||
00776        (limits == TGNumberFormat::kNELLimitMinMax)) {
00777       Long_t upper;
00778       switch (style) {
00779       case TGNumberFormat::kNESRealOne:
00780          upper = Round(10.0 * max);
00781          break;
00782       case TGNumberFormat::kNESRealTwo:
00783          upper = Round(100.0 * max);
00784          break;
00785       case TGNumberFormat::kNESRealThree:
00786          upper = Round(1000.0 * max);
00787          break;
00788       case TGNumberFormat::kNESRealFour:
00789          upper = Round(10000.0 * max);
00790          break;
00791       case TGNumberFormat::kNESHex:
00792          upper = (ULong_t) Round(max);
00793          break;
00794       default:
00795          upper = Round(max);
00796          break;
00797       }
00798       if (style != TGNumberFormat::kNESHex) {
00799          if (l > upper)
00800             l = upper;
00801       } else {
00802          if (upper < 0)
00803             upper = 0;
00804          if ((ULong_t) l > (ULong_t) upper)
00805             l = upper;
00806       }
00807    }
00808 }
00809 
00810 //______________________________________________________________________________
00811 static void IncreaseReal(RealInfo_t & ri, Double_t mag, Bool_t logstep,
00812                          TGNumberFormat::ELimit limits =
00813                          TGNumberFormat::kNELNoLimits, Double_t min = 0,
00814                          Double_t max = 1)
00815 {
00816    // Convert to double format.
00817 
00818    Double_t x = RealToDouble(ri);
00819 
00820    // apply step
00821    if (logstep) {
00822       x *= mag;
00823    } else {
00824       switch (ri.fStyle) {
00825       case kRSInt:
00826          x = x + mag;
00827          break;
00828       case kRSFrac:
00829          x = x + mag / ri.fFracBase;
00830          break;
00831       case kRSExpo:
00832          x = x + mag * TMath::Power(10, ri.fExpoNum);
00833          break;
00834       case kRSFracExpo:
00835          x = x + (mag / ri.fFracBase) * TMath::Power(10, ri.fExpoNum);
00836          break;
00837       }
00838    }
00839    // check min
00840    if ((limits == TGNumberFormat::kNELLimitMin) ||
00841        (limits == TGNumberFormat::kNELLimitMinMax)) {
00842       if (x < min)
00843          x = min;
00844    }
00845    // check max
00846    if ((limits == TGNumberFormat::kNELLimitMax) ||
00847        (limits == TGNumberFormat::kNELLimitMinMax)) {
00848       if (x > max)
00849          x = max;
00850    }
00851    // check format after log step
00852    if ((x != 0) && logstep && (TMath::Abs(mag) > kEpsilon)) {
00853       for (int j = 0; j < 10; j++) {
00854          // Integer: special case
00855          if ((ri.fStyle == kRSInt) && (TMath::Abs(x) < 1) &&
00856              (TMath::Abs(x) > kEpsilon)) {
00857             ri.fStyle = kRSFrac;
00858             ri.fFracDigits = 1;
00859             ri.fFracBase = 10;
00860             continue;
00861          }
00862          if ((ri.fStyle == kRSInt) && (TMath::Abs(x) > 10000)) {
00863             ri.fStyle = kRSFracExpo;
00864             ri.fExpoNum = 4;
00865             ri.fFracDigits = 4;
00866             ri.fFracBase = 10000;
00867             Long_t rest = Round(TMath::Abs(x)) % 10000;
00868             for (int k = 0; k < 4; k++) {
00869                if (rest % 10 != 0) {
00870                   break;
00871                }
00872                ri.fFracDigits--;
00873                ri.fFracBase /= 10;
00874                rest /= 10;
00875             }
00876             if (ri.fFracDigits == 0) {
00877                ri.fStyle = kRSExpo;
00878             }
00879             continue;
00880          }
00881          if (ri.fStyle == kRSInt)
00882             break;
00883 
00884          // caluclate first digit
00885          Double_t y;
00886          if ((ri.fStyle == kRSExpo) || (ri.fStyle == kRSFracExpo)) {
00887             y = TMath::Abs(x) * TMath::Power(10, -ri.fExpoNum);
00888          } else {
00889             y = TMath::Abs(x);
00890          }
00891          // adjust exponent if num < 1
00892          if ((Truncate(y) == 0) && (y > 0.001)) {
00893             if ((ri.fStyle == kRSExpo) || (ri.fStyle == kRSFracExpo)) {
00894                ri.fExpoNum--;
00895             } else {
00896                ri.fStyle = kRSFracExpo;
00897                ri.fExpoNum = -1;
00898             }
00899             continue;
00900          }
00901          // adjust exponent if num > 10
00902          if (Truncate(y) >= 10) {
00903             if ((ri.fStyle == kRSExpo) || (ri.fStyle == kRSFracExpo)) {
00904                ri.fExpoNum++;
00905             } else {
00906                ri.fStyle = kRSFracExpo;
00907                ri.fExpoNum = 1;
00908             }
00909             continue;
00910          }
00911          break;
00912       }
00913    }
00914    // convert back to RealInfo_t
00915    switch (ri.fStyle) {
00916       // Integer type real
00917    case kRSInt:
00918       {
00919          ri.fSign = (x < 0) ? -1 : 1;
00920          ri.fIntNum = Round(TMath::Abs(x));
00921          break;
00922       }
00923       // Fraction type real
00924    case kRSFrac:
00925       {
00926          ri.fSign = (x < 0) ? -1 : 1;
00927          ri.fIntNum = Truncate(TMath::Abs(x));
00928          ri.fFracNum = Round((TMath::Abs(x) - TMath::Abs(ri.fIntNum)) * ri.fFracBase);
00929          break;
00930       }
00931       // Exponent only
00932    case kRSExpo:
00933       {
00934          ri.fSign = (x < 0) ? -1 : 1;
00935          ri.fIntNum = Round(TMath::Abs(x) * TMath::Power(10, -ri.fExpoNum));
00936          if (ri.fIntNum == 0) {
00937             ri.fStyle = kRSInt;
00938          }
00939          break;
00940       }
00941       // Fraction and exponent
00942    case kRSFracExpo:
00943       {
00944          ri.fSign = (x < 0) ? -1 : 1;
00945          Double_t y = TMath::Abs(x) * TMath::Power(10, -ri.fExpoNum);
00946          ri.fIntNum = Truncate(y);
00947          ri.fFracNum = Round((y - TMath::Abs(ri.fIntNum)) * ri.fFracBase);
00948          if ((ri.fIntNum == 0) && (ri.fFracNum == 0)) {
00949             ri.fStyle = kRSFrac;
00950          }
00951          break;
00952       }
00953    }
00954 
00955    // check if the back conversion violated limits
00956    if (limits != TGNumberFormat::kNELNoLimits) {
00957       x = RealToDouble(ri);
00958       // check min
00959       if ((limits == TGNumberFormat::kNELLimitMin) ||
00960           (limits == TGNumberFormat::kNELLimitMinMax)) {
00961          if (x < min) {
00962             char text[256];
00963             snprintf(text, 255, "%g", min);
00964             StrToReal(text, ri);
00965          }
00966       }
00967       // check max
00968       if ((limits == TGNumberFormat::kNELLimitMax) ||
00969           (limits == TGNumberFormat::kNELLimitMinMax)) {
00970          if (x > max) {
00971             char text[256];
00972             snprintf(text, 255, "%g", max);
00973             StrToReal(text, ri);
00974          }
00975       }
00976    }
00977 }
00978 
00979 //______________________________________________________________________________
00980 static void IncreaseDate(Long_t & l, TGNumberFormat::EStepSize step, Int_t sign)
00981 {
00982    // Change year/month/day format.
00983 
00984    Long_t year;
00985    Long_t month;
00986    Long_t day;
00987 
00988    // get year/month/day format
00989    year = l / 10000;
00990    month = (TMath::Abs(l) / 100) % 100;
00991    if (month > 12)
00992       month = 12;
00993    if (month == 0)
00994       month = 1;
00995    day = TMath::Abs(l) % 100;
00996    if (day > kDays[month])
00997       day = kDays[month];
00998    if ((month == 2) && (day > 28) && !IsLeapYear(year)) {
00999       day = 28;
01000    }
01001    if (day == 0)
01002       day = 0;
01003 
01004    // apply step
01005    if (step == TGNumberFormat::kNSSHuge) {
01006       year += sign * 10;
01007    } else if (step == TGNumberFormat::kNSSLarge) {
01008       year += sign;
01009    } else if (step == TGNumberFormat::kNSSMedium) {
01010       month += sign;
01011       if (month > 12) {
01012          month = 1;
01013          year++;
01014       }
01015       if (month < 1) {
01016          month = 12;
01017          year--;
01018       }
01019    } else if (step == TGNumberFormat::kNSSSmall) {
01020       day += sign;
01021       if ((sign > 0) &&
01022           ((day > kDays[month]) ||
01023            ((month == 2) && (day > 28) && !IsLeapYear(year)))) {
01024          day = 1;
01025          month++;
01026          if (month > 12) {
01027             month = 1;
01028             year++;
01029          }
01030       }
01031       if ((sign < 0) && (day == 0)) {
01032          month--;
01033          if (month < 1) {
01034             month = 12;
01035             year--;
01036          }
01037          day = kDays[month];
01038       }
01039    }
01040    // check again for valid date
01041    if (year < 0)
01042       year = 0;
01043    if (day > kDays[month])
01044       day = kDays[month];
01045    if ((month == 2) && (day > 28) && !IsLeapYear(year)) {
01046       day = 28;
01047    }
01048    l = 10000 * year + 100 * month + day;
01049 }
01050 
01051 
01052 
01053 
01054 //______________________________________________________________________________
01055 TGNumberEntryField::TGNumberEntryField(const TGWindow * p, Int_t id,
01056                                        Double_t val, GContext_t norm,
01057                                        FontStruct_t font, UInt_t option,
01058                                        ULong_t back)
01059    : TGTextEntry(p, new TGTextBuffer(), id, norm, font, option, back),
01060      fNeedsVerification(kFALSE), fNumStyle(kNESReal), fNumAttr(kNEAAnyNumber),
01061      fNumLimits(kNELNoLimits)
01062 {
01063    // Constructs a number entry field.
01064 
01065    fStepLog = kFALSE;
01066    SetAlignment(kTextRight);
01067    SetNumber(val);
01068    fEditDisabled = kEditDisable | kEditDisableGrab;
01069 }
01070 
01071 //______________________________________________________________________________
01072 TGNumberEntryField::TGNumberEntryField(const TGWindow * parent,
01073                                        Int_t id, Double_t val,
01074                                        EStyle style, EAttribute attr,
01075                                        ELimit limits, Double_t min,
01076                                        Double_t max)
01077    : TGTextEntry(parent, "", id), fNeedsVerification(kFALSE), fNumStyle(style),
01078      fNumAttr(attr), fNumLimits(limits), fNumMin(min), fNumMax(max)
01079 {
01080    // Constructs a number entry field.
01081 
01082    fStepLog = kFALSE;
01083    SetAlignment(kTextRight);
01084    SetNumber(val);
01085    fEditDisabled = kEditDisable | kEditDisableGrab;
01086 }
01087 
01088 //______________________________________________________________________________
01089 void TGNumberEntryField::SetNumber(Double_t val)
01090 {
01091    // Set the numeric value (floating point representation).
01092 
01093    switch (fNumStyle) {
01094    case kNESInteger:
01095       SetIntNumber(Round(val));
01096       break;
01097    case kNESRealOne:
01098       SetIntNumber(Round(10.0 * val));
01099       break;
01100    case kNESRealTwo:
01101       SetIntNumber(Round(100.0 * val));
01102       break;
01103    case kNESRealThree:
01104       SetIntNumber(Round(1000.0 * val));
01105       break;
01106    case kNESRealFour:
01107       SetIntNumber(Round(10000.0 * val));
01108 
01109       break;
01110    case kNESReal:
01111       {
01112          char text[256];
01113          snprintf(text, 255, "%g", val);
01114          SetText(text);
01115          break;
01116       }
01117    case kNESDegree:
01118       SetIntNumber(Round(val));
01119       break;
01120    case kNESHourMinSec:
01121       SetIntNumber(Round(val));
01122       break;
01123    case kNESMinSec:
01124       SetIntNumber(Round(val));
01125       break;
01126    case kNESHourMin:
01127       SetIntNumber(Round(val));
01128       break;
01129    case kNESDayMYear:
01130       SetIntNumber(Round(val));
01131       break;
01132    case kNESMDayYear:
01133       SetIntNumber(Round(val));
01134       break;
01135    case kNESHex:
01136       SetIntNumber((UInt_t) (TMath::Abs(val) + 0.5));
01137       break;
01138    }
01139 }
01140 
01141 //______________________________________________________________________________
01142 void TGNumberEntryField::SetIntNumber(Long_t val)
01143 {
01144    // Set the numeric value (integer representation).
01145 
01146    char text[256];
01147    RealInfo_t ri;
01148    if (fNumStyle == kNESReal) {
01149       TranslateToStr(text, val, kNESInteger, ri);
01150    } else {
01151       TranslateToStr(text, val, fNumStyle, ri);
01152    }
01153    SetText(text);
01154 }
01155 
01156 //______________________________________________________________________________
01157 void TGNumberEntryField::SetTime(Int_t hour, Int_t min, Int_t sec)
01158 {
01159    // Set the numeric value (time format).
01160 
01161    switch (fNumStyle) {
01162    case kNESHourMinSec:
01163       SetIntNumber(3600 * TMath::Abs(hour) + 60 * TMath::Abs(min) +
01164                    TMath::Abs(sec));
01165       break;
01166    case kNESMinSec:
01167       {
01168          SetIntNumber(60 * min + sec);
01169          break;
01170       }
01171    case kNESHourMin:
01172       SetIntNumber(60 * TMath::Abs(hour) + TMath::Abs(min));
01173       break;
01174    default:
01175       break;
01176    }
01177 }
01178 
01179 //______________________________________________________________________________
01180 void TGNumberEntryField::SetDate(Int_t year, Int_t month, Int_t day)
01181 {
01182    // Set the numeric value (date format).
01183 
01184    switch (fNumStyle) {
01185    case kNESDayMYear:
01186    case kNESMDayYear:
01187       {
01188          SetIntNumber(10000 * TMath::Abs(year) + 100 * TMath::Abs(month) +
01189                       TMath::Abs(day));
01190       }
01191    default:
01192       {
01193          break;
01194       }
01195    }
01196 }
01197 
01198 //______________________________________________________________________________
01199 void TGNumberEntryField::SetHexNumber(ULong_t val)
01200 {
01201    // Set the numeric value (hex format).
01202 
01203    SetIntNumber((Long_t) val);
01204 }
01205 
01206 //______________________________________________________________________________
01207 void TGNumberEntryField::SetText(const char *text, Bool_t emit)
01208 {
01209    // Set the value (text format).
01210 
01211    char buf[256];
01212    strlcpy(buf, text, sizeof(buf));
01213    EliminateGarbage(buf, fNumStyle, fNumAttr);
01214    TGTextEntry::SetText(buf, emit);
01215    fNeedsVerification = kFALSE;
01216 }
01217 
01218 //______________________________________________________________________________
01219 Double_t TGNumberEntryField::GetNumber() const
01220 {
01221    // Get the numeric value (floating point representation).
01222 
01223    switch (fNumStyle) {
01224    case kNESInteger:
01225       return (Double_t) GetIntNumber();
01226    case kNESRealOne:
01227       return (Double_t) GetIntNumber() / 10.0;
01228    case kNESRealTwo:
01229       return (Double_t) GetIntNumber() / 100.0;
01230    case kNESRealThree:
01231       return (Double_t) GetIntNumber() / 1000.0;
01232    case kNESRealFour:
01233       return (Double_t) GetIntNumber() / 10000.0;
01234    case kNESReal:
01235       {
01236          char text[256];
01237          RealInfo_t ri;
01238          strlcpy(text, GetText(), sizeof(text));
01239          return StrToReal(text, ri);
01240       }
01241    case kNESDegree:
01242       return (Double_t) GetIntNumber();
01243    case kNESHourMinSec:
01244       return (Double_t) GetIntNumber();
01245    case kNESMinSec:
01246       return (Double_t) GetIntNumber();
01247    case kNESHourMin:
01248       return (Double_t) GetIntNumber();
01249    case kNESDayMYear:
01250       return (Double_t) GetIntNumber();
01251    case kNESMDayYear:
01252       return (Double_t) GetIntNumber();
01253    case kNESHex:
01254       return (Double_t) (ULong_t) GetIntNumber();
01255    }
01256    return 0;
01257 }
01258 
01259 //______________________________________________________________________________
01260 Long_t TGNumberEntryField::GetIntNumber() const
01261 {
01262    // Get the numeric value (integer representation).
01263 
01264    RealInfo_t ri;
01265    return TranslateToNum(GetText(), fNumStyle, ri);
01266 }
01267 
01268 //______________________________________________________________________________
01269 void TGNumberEntryField::GetTime(Int_t & hour, Int_t & min, Int_t & sec) const
01270 {
01271    // Get the numeric value (time format).
01272 
01273    switch (fNumStyle) {
01274    case kNESHourMinSec:
01275       {
01276          Long_t l = GetIntNumber();
01277          hour = TMath::Abs(l) / 3600;
01278          min = (TMath::Abs(l) % 3600) / 60;
01279          sec = TMath::Abs(l) % 60;
01280          break;
01281       }
01282    case kNESMinSec:
01283       {
01284          Long_t l = GetIntNumber();
01285          hour = 0;
01286          min = TMath::Abs(l) / 60;
01287          sec = TMath::Abs(l) % 60;
01288          if (l < 0) {
01289             min *= -1;
01290             sec *= -1;
01291          }
01292          break;
01293       }
01294    case kNESHourMin:
01295       {
01296          Long_t l = GetIntNumber();
01297          hour = TMath::Abs(l) / 60;
01298          min = TMath::Abs(l) % 60;
01299          sec = 0;
01300          break;
01301       }
01302    default:
01303       {
01304          hour = 0;
01305          min = 0;
01306          sec = 0;
01307          break;
01308       }
01309    }
01310 }
01311 
01312 //______________________________________________________________________________
01313 void TGNumberEntryField::GetDate(Int_t & year, Int_t & month, Int_t & day) const
01314 {
01315    // Get the numeric value (date format).
01316 
01317    switch (fNumStyle) {
01318    case kNESDayMYear:
01319    case kNESMDayYear:
01320       {
01321          Long_t l = GetIntNumber();
01322          year = l / 10000;
01323          month = (l % 10000) / 100;
01324          day = l % 100;
01325          break;
01326       }
01327    default:
01328       {
01329          year = 0;
01330          month = 0;
01331          day = 0;
01332          break;
01333       }
01334    }
01335 }
01336 
01337 //______________________________________________________________________________
01338 ULong_t TGNumberEntryField::GetHexNumber() const
01339 {
01340    // Get the numeric value (hex format).
01341 
01342    return (ULong_t) GetIntNumber();
01343 }
01344 
01345 //______________________________________________________________________________
01346 Int_t TGNumberEntryField::GetCharWidth(const char *text) const
01347 {
01348    // Get the text width in pixels.
01349 
01350    return gVirtualX->TextWidth(fFontStruct, text, strlen(text));
01351 }
01352 
01353 //______________________________________________________________________________
01354 void TGNumberEntryField::IncreaseNumber(EStepSize step,
01355                                         Int_t stepsign, Bool_t logstep)
01356 {
01357    // Increase the number value.
01358 
01359    Long_t l;
01360    RealInfo_t ri;
01361    Long_t mag = 0;
01362    Double_t rmag = 0.0;
01363    Int_t sign = stepsign;
01364 
01365    // svae old text field
01366    TString oldtext = GetText();
01367    // Get number
01368    if (fNumStyle != kNESReal) {
01369       l = GetIntNumber();
01370    } else {
01371       StrToReal(oldtext, ri);
01372    }
01373 
01374    // magnitude of step
01375    if ((fNumStyle == kNESDegree) || (fNumStyle == kNESHourMinSec) ||
01376        (fNumStyle == kNESMinSec) || (fNumStyle == kNESHourMin) ||
01377        (fNumStyle == kNESDayMYear) || (fNumStyle == kNESMDayYear) ||
01378        (fNumStyle == kNESHex)) {
01379       logstep = kFALSE;
01380       switch (step) {
01381       case kNSSSmall:
01382          mag = 1;
01383          break;
01384       case kNSSMedium:
01385          mag = 10;
01386          break;
01387       case kNSSLarge:
01388          mag = 100;
01389          break;
01390       case kNSSHuge:
01391          mag = 1000;
01392          break;
01393       }
01394    } else {
01395       Int_t msd = TMath::Abs((fNumStyle == kNESReal) ? ri.fIntNum : l);
01396       while (msd >= 10)
01397          msd /= 10;
01398       Bool_t odd = (msd < 3);
01399       if (sign < 0)
01400          odd = !odd;
01401       switch (step) {
01402       case kNSSSmall:
01403          rmag = (!logstep) ? 1. : (odd ? 3. : 10. / 3.);
01404          break;
01405       case kNSSMedium:
01406          rmag = (!logstep) ? 10. : 10.;
01407          break;
01408       case kNSSLarge:
01409          rmag = (!logstep) ? 100. : (odd ? 30. : 100. / 3.);
01410          break;
01411       case kNSSHuge:
01412          rmag = (!logstep) ? 1000. : 100.;
01413          break;
01414       }
01415       if (sign < 0)
01416          rmag = logstep ? 1. / rmag : -rmag;
01417    }
01418 
01419    // sign of step
01420    if (sign == 0) {
01421       logstep = kFALSE;
01422       rmag = 0;
01423       mag = 0;
01424    } else {
01425       sign = (sign > 0) ? 1 : -1;
01426    }
01427    // add/multiply step
01428    switch (fNumStyle) {
01429    case kNESInteger:
01430    case kNESRealOne:
01431    case kNESRealTwo:
01432    case kNESRealThree:
01433    case kNESRealFour:
01434       {
01435          l = logstep ? Round(l * rmag) : Round(l + rmag);
01436          CheckMinMax(l, fNumStyle, fNumLimits, fNumMin, fNumMax);
01437          if ((l < 0) && (fNumAttr == kNEANonNegative))
01438             l = 0;
01439          if ((l <= 0) && (fNumAttr == kNEAPositive))
01440             l = 1;
01441          break;
01442       }
01443    case kNESReal:
01444       {
01445          IncreaseReal(ri, rmag, logstep, fNumLimits, fNumMin, fNumMax);
01446          if (((fNumAttr == kNEANonNegative) ||
01447               (fNumAttr == kNEAPositive)) && (ri.fSign < 0)) {
01448             ri.fIntNum = 0;
01449             ri.fFracNum = 0;
01450             ri.fExpoNum = 0;
01451             ri.fSign = 1;
01452          }
01453          break;
01454       }
01455    case kNESDegree:
01456       {
01457          if (mag > 60)
01458             l += sign * 36 * mag;
01459          else if (mag > 6)
01460             l += sign * 6 * mag;
01461          else
01462             l += sign * mag;
01463          CheckMinMax(l, fNumStyle, fNumLimits, fNumMin, fNumMax);
01464          if ((l < 0) && (fNumAttr == kNEANonNegative))
01465             l = 0;
01466          if ((l <= 0) && (fNumAttr == kNEAPositive))
01467             l = 1;
01468          break;
01469       }
01470    case kNESHourMinSec:
01471       {
01472          if (mag > 60)
01473             l += sign * 36 * mag;
01474          else if (mag > 6)
01475             l += sign * 6 * mag;
01476          else
01477             l += sign * mag;
01478          CheckMinMax(l, fNumStyle, fNumLimits, fNumMin, fNumMax);
01479          if (l < 0)
01480             l = (24 * 3600) - ((-l) % (24 * 3600));
01481          if (l > 0)
01482             l = l % (24 * 3600);
01483          break;
01484       }
01485    case kNESMinSec:
01486       {
01487          if (mag > 6)
01488             l += sign * 6 * mag;
01489          else
01490             l += sign * mag;
01491          CheckMinMax(l, fNumStyle, fNumLimits, fNumMin, fNumMax);
01492          if ((l < 0) && (fNumAttr == kNEANonNegative))
01493             l = 0;
01494          if ((l <= 0) && (fNumAttr == kNEAPositive))
01495             l = 1;
01496          break;
01497       }
01498    case kNESHourMin:
01499       {
01500          if (mag > 6)
01501             l += sign * 6 * mag;
01502          else
01503             l += sign * mag;
01504          CheckMinMax(l, fNumStyle, fNumLimits, fNumMin, fNumMax);
01505          if (l < 0)
01506             l = (24 * 60) - ((-l) % (24 * 60));
01507          if (l > 0)
01508             l = l % (24 * 60);
01509          break;
01510       }
01511    case kNESDayMYear:
01512    case kNESMDayYear:
01513       {
01514          IncreaseDate(l, step, sign);
01515          CheckMinMax(l, fNumStyle, fNumLimits, fNumMin, fNumMax);
01516          break;
01517       }
01518    case kNESHex:
01519       {
01520          ULong_t ll = (ULong_t) l;
01521          if (mag > 500)
01522             ll += sign * 4096 * mag / 1000;
01523          else if (mag > 50)
01524             ll += sign * 256 * mag / 100;
01525          else if (mag > 5)
01526             ll += sign * 16 * mag / 10;
01527          else
01528             ll += sign * mag;
01529          l = (Long_t) ll;
01530          CheckMinMax(l, fNumStyle, fNumLimits, fNumMin, fNumMax);
01531          break;
01532       }
01533    }
01534    if (fNumStyle != kNESReal) {
01535       SetIntNumber(l);
01536    } else {
01537       char buf[256];
01538       RealToStr(buf, ri);
01539       SetText(buf);
01540    }
01541 }
01542 
01543 //______________________________________________________________________________
01544 void TGNumberEntryField::SetFormat(EStyle style, EAttribute attr)
01545 {
01546    // Set the numerical format.
01547 
01548    Double_t val = GetNumber();
01549    fNumStyle = style;
01550    fNumAttr = attr;
01551    if ((fNumAttr != kNEAAnyNumber) && (val < 0))
01552       val = 0;
01553    SetNumber(val);
01554    // make sure we have a valid number by increasaing it by 0
01555    IncreaseNumber(kNSSSmall, 0, kFALSE);
01556 }
01557 
01558 //______________________________________________________________________________
01559 void TGNumberEntryField::SetLimits(ELimit limits,
01560                                    Double_t min, Double_t max)
01561 {
01562    // Set the numerical limits.
01563 
01564    Double_t val = GetNumber();
01565    fNumLimits = limits;
01566    fNumMin = min;
01567    fNumMax = max;
01568    SetNumber(val);
01569    // make sure we have a valid number by increasaing it by 0
01570    IncreaseNumber(kNSSSmall, 0, kFALSE);
01571 }
01572 
01573 //______________________________________________________________________________
01574 void TGNumberEntryField::SetState(Bool_t state)
01575 {
01576    // Set the active state.
01577 
01578    if (!state && fNeedsVerification) {
01579       // make sure we have a valid number by increasaing it by 0
01580       IncreaseNumber(kNSSSmall, 0, kFALSE);
01581    }
01582    TGTextEntry::SetState(state);
01583 }
01584 
01585 //______________________________________________________________________________
01586 Bool_t TGNumberEntryField::HandleKey(Event_t * event)
01587 {
01588    // Handle keys.
01589 
01590    if (!IsEnabled()) {
01591       return TGTextEntry::HandleKey(event);
01592    }
01593 
01594    Int_t n;
01595    char tmp[10];
01596    UInt_t keysym;
01597    gVirtualX->LookupString(event, tmp, sizeof(tmp), keysym);
01598    n = strlen(tmp);
01599 
01600    // intercept up key
01601    if ((EKeySym) keysym == kKey_Up) {
01602       // Get log step / alt key
01603       Bool_t logstep = fStepLog;
01604       if (event->fState & kKeyMod1Mask)
01605          logstep = !logstep;
01606       // shift-cntrl-up
01607       if ((event->fState & kKeyShiftMask) &&
01608           (event->fState & kKeyControlMask)) {
01609          IncreaseNumber(kNSSHuge, 1, logstep);
01610       }
01611       // cntrl-up
01612       else if (event->fState & kKeyControlMask) {
01613          IncreaseNumber(kNSSLarge, 1, logstep);
01614 
01615       }
01616       // shift-up
01617       else if (event->fState & kKeyShiftMask) {
01618          IncreaseNumber(kNSSMedium, 1, logstep);
01619       }
01620 
01621       // up
01622       else {
01623          IncreaseNumber(kNSSSmall, 1, logstep);
01624       }
01625       return kTRUE;
01626    }
01627    // intercept down key
01628    else if ((EKeySym) keysym == kKey_Down) {
01629       // Get log step / alt key
01630       Bool_t logstep = fStepLog;
01631       if (event->fState & kKeyMod1Mask)
01632          logstep = !logstep;
01633       // shift-cntrl-down
01634       if ((event->fState & kKeyShiftMask) &&
01635           (event->fState & kKeyControlMask)) {
01636          IncreaseNumber(kNSSHuge, -1, logstep);
01637       }
01638       // cntrl-down
01639       else if (event->fState & kKeyControlMask) {
01640          IncreaseNumber(kNSSLarge, -1, logstep);
01641       }
01642       // shift-down
01643       else if (event->fState & kKeyShiftMask) {
01644          IncreaseNumber(kNSSMedium, -1, logstep);
01645       }
01646       // down
01647       else {
01648          IncreaseNumber(kNSSSmall, -1, logstep);
01649       }
01650       return kTRUE;
01651    }
01652    // intercept printable characters
01653    else if (n && (keysym < 127) && (keysym >= 32) &&
01654             ((EKeySym) keysym != kKey_Delete) &&
01655             ((EKeySym) keysym != kKey_Backspace) &&
01656             ((event->fState & kKeyControlMask) == 0)) {
01657       if (IsGoodChar(tmp[0], fNumStyle, fNumAttr)) {
01658          return TGTextEntry::HandleKey(event);
01659       } else {
01660          return kTRUE;
01661       }
01662    }
01663    // otherwise use default behaviour
01664    else {
01665       return TGTextEntry::HandleKey(event);
01666    }
01667 }
01668 
01669 //______________________________________________________________________________
01670 Bool_t TGNumberEntryField::HandleFocusChange(Event_t * event)
01671 {
01672    // Handle focus change.
01673 
01674    if (IsEnabled() && fNeedsVerification &&
01675        (event->fCode == kNotifyNormal) &&
01676        (event->fState != kNotifyPointer) && (event->fType == kFocusOut)) {
01677       // make sure we have a valid number by increasing it by 0
01678       IncreaseNumber(kNSSSmall, 0, kFALSE);
01679    }
01680 
01681    return TGTextEntry::HandleFocusChange(event);
01682 }
01683 
01684 //______________________________________________________________________________
01685 void TGNumberEntryField::TextChanged(const char *text)
01686 {
01687    // Text has changed message.
01688 
01689    TGTextEntry::TextChanged(text);
01690    fNeedsVerification = kTRUE;
01691 }
01692 
01693 //______________________________________________________________________________
01694 void TGNumberEntryField::ReturnPressed()
01695 {
01696    // Return was pressed.
01697 
01698    TString instr, outstr;
01699    instr = TGTextEntry::GetBuffer()->GetString();
01700 
01701    if (fNeedsVerification) {
01702       // make sure we have a valid number by increasing it by 0
01703       IncreaseNumber(kNSSSmall, 0, kFALSE);
01704    }
01705    outstr = TGTextEntry::GetBuffer()->GetString();
01706    if (instr != outstr) {
01707       InvalidInput(instr);
01708       gVirtualX->Bell(0);
01709    }
01710    TGTextEntry::ReturnPressed();
01711 }
01712 
01713 //______________________________________________________________________________
01714 void TGNumberEntryField::Layout()
01715 {
01716    // Layout.
01717 
01718    if (GetAlignment() == kTextRight) {
01719       End(kFALSE);
01720    } else {
01721       Home(kFALSE);
01722    }
01723 }
01724 
01725 //////////////////////////////////////////////////////////////////////////
01726 //                                                                      //
01727 // TGNumberEntryLayout                                                  //
01728 //                                                                      //
01729 // Layout manager for number entry widget                               //
01730 //                                                                      //
01731 //////////////////////////////////////////////////////////////////////////
01732 
01733 
01734 //______________________________________________________________________________
01735 void TGNumberEntryLayout::Layout()
01736 {
01737    // Layout the internal GUI elements in use.
01738 
01739    if (fBox == 0) {
01740       return;
01741    }
01742    UInt_t w = fBox->GetWidth();
01743    UInt_t h = fBox->GetHeight();
01744    UInt_t upw = 2 * h / 3;
01745    UInt_t uph = h / 2;
01746    Int_t upx = (w > h) ? (Int_t) w - (Int_t) upw : -1000;
01747    Int_t upy = 0;
01748    Int_t downx = (w > h) ? (Int_t) w - (Int_t) upw : -1000;
01749    Int_t downy = h / 2;
01750    UInt_t downw = upw;
01751    UInt_t downh = h - downy;
01752    UInt_t numw = (w > h) ? w - upw : w;
01753    UInt_t numh = h;
01754    if (fBox->GetNumberEntry())
01755       fBox->GetNumberEntry()->MoveResize(0, 0, numw, numh);
01756    if (fBox->GetButtonUp())
01757       fBox->GetButtonUp()->MoveResize(upx, upy, upw, uph);
01758    if (fBox->GetButtonDown())
01759       fBox->GetButtonDown()->MoveResize(downx, downy, downw, downh);
01760 }
01761 
01762 //______________________________________________________________________________
01763 TGDimension TGNumberEntryLayout::GetDefaultSize() const
01764 {
01765    // Return the default size of the numeric control box.
01766 
01767    return fBox->GetSize();
01768 }
01769 
01770 
01771 
01772 //////////////////////////////////////////////////////////////////////////
01773 //                                                                      //
01774 // TRepeatTimer                                                         //
01775 //                                                                      //
01776 // Timer for numeric control box buttons.                               //
01777 //                                                                      //
01778 //////////////////////////////////////////////////////////////////////////
01779 
01780 class TGRepeatFireButton;
01781 
01782 //______________________________________________________________________________
01783 class TRepeatTimer : public TTimer {
01784 private:
01785    TGRepeatFireButton *fButton;  // Fire button
01786 
01787 public:
01788    TRepeatTimer(TGRepeatFireButton * button, Long_t ms)
01789     : TTimer(ms, kTRUE), fButton(button) { }
01790    virtual Bool_t Notify();
01791 };
01792 
01793 
01794 
01795 //////////////////////////////////////////////////////////////////////////
01796 //                                                                      //
01797 // TRepeatFireButton                                                    //
01798 //                                                                      //
01799 // Picture button which fires repeatly as long as the button is pressed //
01800 //                                                                      //
01801 //////////////////////////////////////////////////////////////////////////
01802 
01803 //______________________________________________________________________________
01804 class TGRepeatFireButton : public TGPictureButton {
01805 protected:
01806    TRepeatTimer             *fTimer;           // the timer
01807    Int_t                     fIgnoreNextFire;  // flag for skipping next
01808    TGNumberFormat::EStepSize fStep;            // increment/decrement step
01809    Bool_t                    fStepLog;         // logarithmic step flag
01810    Bool_t                    fDoLogStep;       // flag for using logarithmic step
01811 
01812    Bool_t IsEditableParent();
01813 
01814 public:
01815    TGRepeatFireButton(const TGWindow *p, const TGPicture *pic,
01816                       Int_t id, Bool_t logstep)
01817     : TGPictureButton(p, pic, id), fTimer(0), fIgnoreNextFire(0),
01818        fStep(TGNumberFormat::kNSSSmall), fStepLog(logstep), fDoLogStep(logstep)
01819        { fEditDisabled = kEditDisable | kEditDisableGrab; }
01820    virtual ~TGRepeatFireButton() { delete fTimer; }
01821 
01822    virtual  Bool_t HandleButton(Event_t *event);
01823             void   FireButton();
01824    virtual  void   SetLogStep(Bool_t on = kTRUE) { fStepLog = on; }
01825 };
01826 
01827 //______________________________________________________________________________
01828 Bool_t TGRepeatFireButton::IsEditableParent()
01829 {
01830    // Return kTRUE if one of the parents is in edit mode.
01831 
01832    TGWindow *parent = (TGWindow*)GetParent();
01833 
01834    while (parent && (parent != fClient->GetDefaultRoot())) {
01835       if (parent->IsEditable()) {
01836          return kTRUE;
01837       }
01838       parent = (TGWindow*)parent->GetParent();
01839    }
01840    return kFALSE;
01841 }
01842 
01843 //______________________________________________________________________________
01844 Bool_t TGRepeatFireButton::HandleButton(Event_t * event)
01845 {
01846    // Handle messages for number entry widget according to the user input.
01847 
01848    const Int_t t0 = 200;
01849    if (fTip)
01850       fTip->Hide();
01851 
01852    // disable button handling while guibuilding
01853    if (IsEditableParent()) {
01854       return kTRUE;
01855    }
01856 
01857    if (fState == kButtonDisabled)
01858       return kTRUE;
01859 
01860    if (event->fType == kButtonPress) {
01861       // Get log step / alt key
01862       fDoLogStep = fStepLog;
01863       if (event->fState & kKeyMod1Mask)
01864          fDoLogStep = !fDoLogStep;
01865       if ((event->fState & kKeyShiftMask) &&
01866           (event->fState & kKeyControlMask)) {
01867          fStep = TGNumberFormat::kNSSHuge;
01868       } else if (event->fState & kKeyControlMask) {
01869          fStep = TGNumberFormat::kNSSLarge;
01870       } else if (event->fState & kKeyShiftMask) {
01871          fStep = TGNumberFormat::kNSSMedium;
01872       } else {
01873          fStep = TGNumberFormat::kNSSSmall;
01874       }
01875       SetState(kButtonDown);
01876       fIgnoreNextFire = 0;
01877       FireButton();
01878       fIgnoreNextFire = 2;
01879 
01880       if (fTimer == 0) {
01881          fTimer = new TRepeatTimer(this, t0);
01882       }
01883       fTimer->Reset();
01884       gSystem->AddTimer(fTimer);
01885    } else {
01886       SetState(kButtonUp);
01887       if (fTimer != 0) {
01888          fTimer->Remove();
01889          fTimer->SetTime(t0);
01890       }
01891    }
01892 
01893    return kTRUE;
01894 }
01895 
01896 //______________________________________________________________________________
01897 void TGRepeatFireButton::FireButton()
01898 {
01899    // Process messages for fire button.
01900 
01901    if (fIgnoreNextFire <= 0) {
01902       SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_BUTTON),
01903                   fWidgetId, (Long_t) fStep + (fDoLogStep ? 100 : 0));
01904    } else {
01905       fIgnoreNextFire--;
01906    }
01907 }
01908 
01909 //______________________________________________________________________________
01910 Bool_t TRepeatTimer::Notify()
01911 {
01912    // Notify when timer times out and reset the timer.
01913 
01914    fButton->FireButton();
01915    Reset();
01916    if ((Long64_t)fTime > 20) fTime -= 10;
01917    return kFALSE;
01918 }
01919 
01920 //______________________________________________________________________________
01921 TGNumberEntry::TGNumberEntry(const TGWindow *parent,
01922                              Double_t val, Int_t wdigits, Int_t id,
01923                              EStyle style,
01924                              EAttribute attr,
01925                              ELimit limits, Double_t min, Double_t max)
01926  : TGCompositeFrame(parent, 10 * wdigits, 25), fButtonToNum(kTRUE)
01927 {
01928    // Constructs a numeric entry widget.
01929 
01930    fWidgetId  = id;
01931    fMsgWindow = parent;
01932    fPicUp = fClient->GetPicture("arrow_up.xpm");
01933    if (!fPicUp)
01934       Error("TGNumberEntry", "arrow_up.xpm not found");
01935    fPicDown = fClient->GetPicture("arrow_down.xpm");
01936    if (!fPicDown)
01937       Error("TGNumberEntry", "arrow_down.xpm not found");
01938 
01939    // create gui elements
01940    fNumericEntry = new TGNumberEntryField(this, id, val, style, attr,
01941                                           limits, min, max);
01942    fNumericEntry->Connect("ReturnPressed()", "TGNumberEntry", this, "ValueSet(Long_t)");
01943    fNumericEntry->Associate(fMsgWindow);
01944    AddFrame(fNumericEntry, 0);
01945    fButtonUp = new TGRepeatFireButton(this, fPicUp, 1,
01946                                       fNumericEntry->IsLogStep());
01947    fButtonUp->Associate(this);
01948    AddFrame(fButtonUp, 0);
01949    fButtonDown = new TGRepeatFireButton(this, fPicDown, 2,
01950                                         fNumericEntry->IsLogStep());
01951    fButtonDown->Associate(this);
01952    AddFrame(fButtonDown, 0);
01953 
01954    // resize
01955    Int_t h = fNumericEntry->GetDefaultHeight();
01956    Int_t charw = fNumericEntry->GetCharWidth("0123456789");
01957    Int_t w = charw * TMath::Abs(wdigits) / 10 + 8 + 2 * h / 3;
01958    SetLayoutManager(new TGNumberEntryLayout(this));
01959    MapSubwindows();
01960    Resize(w, h);
01961    fEditDisabled = kEditDisableLayout | kEditDisableHeight;
01962 }
01963 
01964 //______________________________________________________________________________
01965 TGNumberEntry::~TGNumberEntry()
01966 {
01967    // Destructs a numeric entry widget.
01968 
01969    gClient->FreePicture(fPicUp);
01970    gClient->FreePicture(fPicDown);
01971 
01972    Cleanup();
01973 }
01974 
01975 //______________________________________________________________________________
01976 void TGNumberEntry::Associate(const TGWindow *w)
01977 {
01978    // Make w the window that will receive the generated messages.
01979 
01980    TGWidget::Associate(w);
01981    fNumericEntry->Associate(w);
01982 }
01983 
01984 //______________________________________________________________________________
01985 void TGNumberEntry::SetLogStep(Bool_t on)
01986 {
01987    // Set log steps.
01988 
01989    fNumericEntry->SetLogStep(on);
01990    ((TGRepeatFireButton *) fButtonUp)->SetLogStep(fNumericEntry->IsLogStep());
01991    ((TGRepeatFireButton *) fButtonDown)->SetLogStep(fNumericEntry->IsLogStep());
01992 }
01993 
01994 //______________________________________________________________________________
01995 void TGNumberEntry::SetState(Bool_t enable)
01996 {
01997    // Set the active state.
01998 
01999    if (enable) {
02000       fButtonUp->SetState(kButtonUp);
02001       fButtonDown->SetState(kButtonUp);
02002       fNumericEntry->SetState(kTRUE);
02003    } else {
02004       fButtonUp->SetState(kButtonDisabled);
02005       fButtonDown->SetState(kButtonDisabled);
02006       fNumericEntry->SetState(kFALSE);
02007    }
02008 }
02009 
02010 //______________________________________________________________________________
02011 void TGNumberEntry::SetButtonToNum(Bool_t state)
02012 {
02013    // Send button messages to the number field (true) or parent widget (false).
02014    // When the message is sent to the parent widget, it is responsible to change
02015    // the numerical value accordingly. This can be useful to implement cursors
02016    // which move from data point to data point. For the message being sent
02017    // see ProcessMessage().
02018 
02019    fButtonToNum = state;
02020 }
02021 
02022 //______________________________________________________________________________
02023 Bool_t TGNumberEntry::ProcessMessage(Long_t msg, Long_t parm1, Long_t parm2)
02024 {
02025    // Process the up/down button messages. If fButtonToNum is false the
02026    // following message is sent: kC_COMMAND, kCM_BUTTON, widget id, param
02027    // param % 100 is the step size
02028    // param % 10000 / 100 != 0 indicates log step
02029    // param / 10000 != 0 indicates button down
02030 
02031    switch (GET_MSG(msg)) {
02032    case kC_COMMAND:
02033       {
02034          if ((GET_SUBMSG(msg) == kCM_BUTTON) &&
02035              (parm1 >= 1) && (parm1 <= 2)) {
02036             if (fButtonToNum) {
02037                Int_t sign = (parm1 == 1) ? 1 : -1;
02038                EStepSize step = (EStepSize) (parm2 % 100);
02039                Bool_t logstep = (parm2 >= 100);
02040                fNumericEntry->IncreaseNumber(step, sign, logstep);
02041             } else {
02042                SendMessage(fMsgWindow, msg, fWidgetId,
02043                            10000 * (parm1 - 1) + parm2);
02044                ValueChanged(10000 * (parm1 - 1) + parm2);
02045             }
02046          // Emit a signal needed by pad editor
02047          ValueSet(10000 * (parm1 - 1) + parm2);
02048          }
02049          break;
02050       }
02051    }
02052    return kTRUE;
02053 }
02054 
02055 
02056 //______________________________________________________________________________
02057 TGLayoutManager *TGNumberEntry::GetLayoutManager() const
02058 {
02059    // Return layout manager.
02060 
02061    TGNumberEntry *entry = (TGNumberEntry*)this;
02062 
02063    if (entry->fLayoutManager->IsA() != TGNumberEntryLayout::Class()) {
02064       entry->SetLayoutManager(new TGNumberEntryLayout(entry));
02065    }
02066 
02067    return entry->fLayoutManager;
02068 }
02069 
02070 //______________________________________________________________________________
02071 void TGNumberEntry::ValueChanged(Long_t val)
02072 {
02073    // Emit ValueChanged(Long_t) signal. This signal is emitted when
02074    // fButtonToNum is false. The val has the following meaning:
02075    // val % 100 is the step size
02076    // val % 10000 / 100 != 0 indicates log step
02077    // val / 10000 != 0 indicates button down
02078 
02079    Emit("ValueChanged(Long_t)", val);
02080 }
02081 
02082 //______________________________________________________________________________
02083 void TGNumberEntry::ValueSet(Long_t val)
02084 {
02085    // Emit ValueSet(Long_t) signal. This signal is emitted when the
02086    // number entry value is changed. The val has the following meaning:
02087    // val % 100 is the step size
02088    // val % 10000 / 100 != 0 indicates log step
02089    // val / 10000 != 0 indicates button down
02090 
02091    Emit("ValueSet(Long_t)", val);
02092 }
02093 
02094 //______________________________________________________________________________
02095 void TGNumberEntry::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
02096 {
02097    // Save a number entry widget as a C++ statement(s) on output stream out.
02098 
02099    char quote = '"';
02100 
02101    // to calculate the digits parameter
02102    Int_t w = fNumericEntry->GetWidth();
02103    Int_t h = fNumericEntry->GetHeight();
02104    Int_t charw  = fNumericEntry->GetCharWidth("0123456789");
02105    Int_t digits = (30*w - 240 -20*h)/(3*charw) + 3;
02106 
02107    // for time format
02108    Int_t hour, min, sec;
02109    GetTime(hour, min, sec);
02110 
02111    // for date format
02112    Int_t yy, mm, dd;
02113    GetDate(yy, mm, dd);
02114 
02115    out << "   TGNumberEntry *";
02116    out << GetName() << " = new TGNumberEntry(" << fParent->GetName() << ", (Double_t) ";
02117    switch (GetNumStyle()){
02118       case kNESInteger:
02119          out << GetIntNumber() << "," << digits << "," << WidgetId()
02120              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02121          break;
02122       case kNESRealOne:
02123          out << GetNumber() << "," << digits << "," << WidgetId()
02124              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02125          break;
02126       case kNESRealTwo:
02127          out << GetNumber() << "," << digits << "," << WidgetId()
02128              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02129          break;
02130       case kNESRealThree:
02131          out << GetNumber() << "," << digits << "," << WidgetId()
02132              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02133          break;
02134       case kNESRealFour:
02135          out << GetNumber() << "," << digits << "," << WidgetId()
02136              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02137          break;
02138       case kNESReal:
02139          out << GetNumber() << "," << digits << "," << WidgetId()
02140              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02141          break;
02142       case kNESDegree:
02143          out << GetIntNumber() << "," << digits << "," << WidgetId()
02144              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02145          break;
02146       case kNESMinSec:
02147          out << min*60 + sec << "," << digits << "," << WidgetId()
02148              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02149          break;
02150       case kNESHourMin:
02151          out << hour*60 + min << "," << digits << "," << WidgetId()
02152              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02153          break;
02154       case kNESHourMinSec:
02155          out << hour*3600 + min*60 + sec << "," << digits << "," << WidgetId()
02156              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02157          break;
02158       case kNESDayMYear:
02159          out << yy << mm << dd << "," << digits << "," << WidgetId()
02160              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02161          break;
02162       case kNESMDayYear:
02163          out << yy << mm << dd << "," << digits << "," << WidgetId()
02164              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02165          break;
02166       case kNESHex:
02167       {  char hex[256];
02168          ULong_t l = GetHexNumber();
02169          IntToHexStr(hex, l);
02170          out << "0x" << hex << "U," << digits << "," << WidgetId()
02171              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02172          break;
02173       }
02174    }
02175    if (GetNumMax() ==1) {
02176       if (GetNumMin() == 0) {
02177          if (GetNumLimits() == kNELNoLimits) {
02178             if (GetNumAttr() == kNEAAnyNumber) {
02179                out << ");" << endl;
02180             } else {
02181                out << ",(TGNumberFormat::EAttribute) " << GetNumAttr() << ");" << endl;
02182             }
02183          } else {
02184             out << ",(TGNumberFormat::EAttribute) " << GetNumAttr()
02185                 << ",(TGNumberFormat::ELimit) " << GetNumLimits() << ");" << endl;
02186          }
02187       } else {
02188          out << ",(TGNumberFormat::EAttribute) " << GetNumAttr()
02189              << ",(TGNumberFormat::ELimit) " << GetNumLimits()
02190              << "," << GetNumMin() << ");" << endl;
02191       }
02192    } else {
02193          out << ",(TGNumberFormat::EAttribute) " << GetNumAttr()
02194              << ",(TGNumberFormat::ELimit) " << GetNumLimits()
02195              << "," << GetNumMin() << "," << GetNumMax() << ");" << endl;
02196    }
02197    if (option && strstr(option, "keep_names"))
02198       out << "   " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
02199    if (fButtonDown->GetState() == kButtonDisabled)
02200       out << "   " << GetName() << "->SetState(kFALSE);" << endl;
02201 
02202    TGToolTip *tip = GetNumberEntry()->GetToolTip();
02203    if (tip) {
02204       TString tiptext = tip->GetText()->GetString();
02205       tiptext.ReplaceAll("\n", "\\n");
02206       out << "   ";
02207       out << GetName() << "->GetNumberEntry()->SetToolTipText(" << quote
02208           << tiptext << quote << ");"  << endl;
02209    }
02210 }
02211 
02212 //______________________________________________________________________________
02213 void TGNumberEntryField::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
02214 {
02215    // Save a number entry widget as a C++ statement(s) on output stream out.
02216 
02217    char quote = '"';
02218 
02219    // for time format
02220    Int_t hour, min, sec;
02221    GetTime(hour, min, sec);
02222 
02223    // for date format
02224    Int_t yy, mm, dd;
02225    GetDate(yy, mm, dd);
02226 
02227    out << "   TGNumberEntryField *";
02228    out << GetName() << " = new TGNumberEntryField(" << fParent->GetName()
02229        << ", " << WidgetId() << ", (Double_t) ";
02230    switch (GetNumStyle()){
02231       case kNESInteger:
02232          out << GetIntNumber()
02233              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02234          break;
02235       case kNESRealOne:
02236          out << GetNumber()
02237              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02238          break;
02239       case kNESRealTwo:
02240          out << GetNumber()
02241              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02242          break;
02243       case kNESRealThree:
02244          out << GetNumber()
02245              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02246          break;
02247       case kNESRealFour:
02248          out << GetNumber()
02249              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02250          break;
02251       case kNESReal:
02252          out << GetNumber()
02253              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02254          break;
02255       case kNESDegree:
02256          out << GetIntNumber()
02257              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02258          break;
02259       case kNESMinSec:
02260          out << min*60 + sec
02261              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02262          break;
02263       case kNESHourMin:
02264          out << hour*60 + min
02265              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02266          break;
02267       case kNESHourMinSec:
02268          out << hour*3600 + min*60 + sec
02269              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02270          break;
02271       case kNESDayMYear:
02272          out << yy << mm << dd
02273              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02274          break;
02275       case kNESMDayYear:
02276          out << yy << mm << dd
02277              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02278          break;
02279       case kNESHex:
02280       {  char hex[256];
02281          ULong_t l = GetHexNumber();
02282          IntToHexStr(hex, l);
02283          out << "0x" << hex << "U"
02284              << ",(TGNumberFormat::EStyle) " << GetNumStyle();
02285          break;
02286       }
02287    }
02288    if (GetNumMax() ==1) {
02289       if (GetNumMin() == 0) {
02290          if (GetNumLimits() == kNELNoLimits) {
02291             if (GetNumAttr() == kNEAAnyNumber) {
02292                out << ");" << endl;
02293             } else {
02294                out << ",(TGNumberFormat::EAttribute) " << GetNumAttr() << ");" << endl;
02295             }
02296          } else {
02297             out << ",(TGNumberFormat::EAttribute) " << GetNumAttr()
02298                 << ",(TGNumberFormat::ELimit) " << GetNumLimits() << ");" << endl;
02299          }
02300       } else {
02301          out << ",(TGNumberFormat::EAttribute) " << GetNumAttr()
02302              << ",(TGNumberFormat::ELimit) " << GetNumLimits()
02303              << "," << GetNumMin() << ");" << endl;
02304       }
02305    } else {
02306          out << ",(TGNumberFormat::EAttribute) " << GetNumAttr()
02307              << ",(TGNumberFormat::ELimit) " << GetNumLimits()
02308              << "," << GetNumMin() << "," << GetNumMax() << ");" << endl;
02309    }
02310    if (option && strstr(option, "keep_names"))
02311       out << "   " << GetName() << "->SetName(\"" << GetName() << "\");" << endl;
02312    if (!IsEnabled())
02313       out << "   " << GetName() << "->SetState(kFALSE);" << endl;
02314 
02315    out << "   " << GetName() << "->Resize("<< GetWidth() << "," << GetName()
02316        << "->GetDefaultHeight());" << endl;
02317 
02318    TGToolTip *tip = GetToolTip();
02319    if (tip) {
02320       TString tiptext = tip->GetText()->GetString();
02321       tiptext.ReplaceAll("\n", "\\n");
02322       out << "   ";
02323       out << GetName() << "->SetToolTipText(" << quote
02324           << tiptext << quote << ");"  << endl;
02325    }
02326 }

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