1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef _FMTFIELD_HXX_ 25 #define _FMTFIELD_HXX_ 26 27 #include "svtools/svtdllapi.h" 28 #include <vcl/spinfld.hxx> 29 #include <svl/zforlist.hxx> 30 31 //#define REGEXP_SUPPORT 32 33 #ifdef REGEXP_SUPPORT 34 #ifndef _UNOTOOLS_TEXTSEARCH_HXX 35 #include <unotools/textsearch.hxx> 36 #endif 37 #else 38 // use a hand-made regular expression parsing for the small expression we're interested in 39 // as soon as OOo does have regular expression support, we can switch on the REGEXP_SUPPORT define 40 namespace validation { class NumberValidator; } 41 #endif 42 43 typedef sal_uInt16 FORMAT_CHANGE_TYPE; 44 #define FCT_KEYONLY 0x00 // only a new key was set 45 #define FCT_FORMATTER 0x01 // a new formatter weas set, usually implies a change of the key, too 46 #define FCT_PRECISION 0x02 // a new precision was set 47 #define FCT_THOUSANDSSEP 0x03 // the thousands separator setting changed 48 49 //------------------------------------------------------------------------------ 50 class SVT_DLLPUBLIC FormattedField : public SpinField 51 { 52 private: 53 // Da ein SvNumberFormatter eine ziemlich teure (sowohl zeit- als auch platz-maessig) Angelegenheit ist, 54 // haelt sich nicht jedes Field, an dem kein Formatter gesetzt wurde, eine eigenen Instanz, sondern es gibt nur eine 55 // einzige statische. 56 class StaticFormatter 57 { 58 static SvNumberFormatter* s_cFormatter; 59 static sal_uLong s_nReferences; 60 public: 61 StaticFormatter(); 62 ~StaticFormatter(); 63 operator SvNumberFormatter*()64 operator SvNumberFormatter* () { return GetFormatter(); } 65 SVT_DLLPUBLIC SvNumberFormatter* GetFormatter(); 66 }; 67 68 protected: 69 String m_sLastValidText; 70 // hat nichts mit dem current value zu tun, ist der letzte Text, der waehrend einer Eingabe als gueltig erkannt 71 // wurde (also durch CheckText geprueft, nicht durch den Formatter gejagt) 72 Selection m_aLastSelection; 73 74 double m_dMinValue; 75 double m_dMaxValue; 76 sal_Bool m_bHasMin : 1; 77 sal_Bool m_bHasMax : 1; 78 79 sal_Bool m_bStrictFormat : 1; 80 81 sal_Bool m_bValueDirty : 1; 82 sal_Bool m_bEnableEmptyField : 1; 83 sal_Bool m_bAutoColor : 1; 84 sal_Bool m_bEnableNaN : 1; 85 double m_dCurrentValue; 86 double m_dDefaultValue; 87 88 sal_uLong m_nFormatKey; 89 SvNumberFormatter* m_pFormatter; 90 StaticFormatter m_aStaticFormatter; 91 92 double m_dSpinSize; 93 double m_dSpinFirst; 94 double m_dSpinLast; 95 96 // es macht einen Unterschied, ob man bei eingestellter Textformatierung beim LostFocus den aktuellen String durch 97 // den Formatter jagt und das Ergebnis anzeigt oder erst aus dem String ein double macht, das formatiert und dann 98 // ausgibt 99 sal_Bool m_bTreatAsNumber; 100 // und mit den folgenden Members koennen wir das Ganze hier auch zur formatierten Text-Ausgabe benutzen ... 101 String m_sCurrentTextValue; 102 String m_sDefaultText; 103 104 // die bei der letzten Ausgabe-Operation vom Formatter gelieferte Farbe (nicht dass wir sie beachten wuerden, aber 105 // man kann sie von aussen abfragen) 106 Color* m_pLastOutputColor; 107 108 bool m_bUseInputStringForFormatting; 109 110 public: 111 FormattedField(Window* pParent, WinBits nStyle = 0, SvNumberFormatter* pInitialFormatter = NULL, sal_Int32 nFormatKey = 0); 112 FormattedField(Window* pParent, const ResId& rResId, SvNumberFormatter* pInitialFormatter = NULL, sal_Int32 nFormatKey = 0); 113 virtual ~FormattedField(); 114 115 // Min-/Max-Verwaltung HasMinValue() const116 sal_Bool HasMinValue() const { return m_bHasMin; } ClearMinValue()117 void ClearMinValue() { m_bHasMin = sal_False; } 118 void SetMinValue(double dMin); GetMinValue() const119 double GetMinValue() const { return m_dMinValue; } 120 HasMaxValue() const121 sal_Bool HasMaxValue() const { return m_bHasMax; } ClearMaxValue()122 void ClearMaxValue() { m_bHasMax = sal_False; } 123 void SetMaxValue(double dMax); GetMaxValue() const124 double GetMaxValue() const { return m_dMaxValue; } 125 126 // aktueller Wert 127 virtual void SetValue(double dVal); 128 virtual double GetValue(); 129 // die Standard-Implementierung jagt die Eingabe jeweils durch den Formatter, so einer vorhanden ist 130 131 void GetColor() const; 132 133 void SetTextValue(const XubString& rText); 134 // der String wird in ein double umgewandelt (durch den Formatter) und anschliessen in SetValue gesteckt 135 IsEmptyFieldEnabled() const136 sal_Bool IsEmptyFieldEnabled() const { return m_bEnableEmptyField; } 137 void EnableEmptyField(sal_Bool bEnable); 138 // wenn nicht enabled, wird beim Verlassen des Feldes der Text auf den letzten gueltigen zurueckgesetzt 139 SetDefaultValue(double dDefault)140 void SetDefaultValue(double dDefault) { m_dDefaultValue = dDefault; m_bValueDirty = sal_True; } 141 // wenn der aktuelle String ungueltig ist, liefert GetValue() diesen Default-Wert GetDefaultValue() const142 double GetDefaultValue() const { return m_dDefaultValue; } 143 144 // Einstellungen fuer das Format GetFormatKey() const145 sal_uLong GetFormatKey() const { return m_nFormatKey; } 146 void SetFormatKey(sal_uLong nFormatKey); 147 GetFormatter() const148 SvNumberFormatter* GetFormatter() const { return m_pFormatter; } 149 void SetFormatter(SvNumberFormatter* pFormatter, sal_Bool bResetFormat = sal_True); 150 // wenn bResetFormat sal_False ist, wird versucht, das alte eingestellte Format mit 'hinueberzuretten' (teuer, wenn es sich nicht 151 // um eines der Standard-Formate handelt, die in allen Formattern gleich sind) 152 // wenn sal_True, wird als neuer FormatKey 0 gesetzt 153 154 sal_Bool GetThousandsSep() const; 155 void SetThousandsSep(sal_Bool _bUseSeparator); 156 // the is no check if the current format is numeric, so be cautious when calling these functions 157 158 sal_uInt16 GetDecimalDigits() const; 159 void SetDecimalDigits(sal_uInt16 _nPrecision); 160 // the is no check if the current format is numeric, so be cautious when calling these functions 161 StandardFormatter()162 SvNumberFormatter* StandardFormatter() { return m_aStaticFormatter; } 163 // Wenn man keinen eigenen Formatter explizit anlegen will, kann man diesen hier in SetFormatter stecken ... 164 // Das hier gelieferte Objekt wird allerdings zwischen allen Instanzen der Klasse geteilt (aus Zeit- und Platzgruenden), 165 // also ist etwas Vorsicht angebracht ... 166 167 void GetFormat(XubString& rFormatString, LanguageType& eLang) const; 168 sal_Bool SetFormat(const XubString& rFormatString, LanguageType eLang); 169 // sal_False, wenn der FormatString nicht gesetzt werden konnte (also wahrscheinlich ungueltig ist) 170 IsStrictFormat() const171 sal_Bool IsStrictFormat() const { return m_bStrictFormat; } SetStrictFormat(sal_Bool bEnable)172 void SetStrictFormat(sal_Bool bEnable) { m_bStrictFormat = bEnable; } 173 // Formatueberpruefung waehrend der Eingabe ? 174 175 // Spin-Handling 176 virtual void Up(); 177 virtual void Down(); 178 // Standard-Implementierung : hoch- oder runterzaehlen des aktuellen double einfach um die gesetzte SpinSize 179 virtual void First(); 180 virtual void Last(); 181 // Standard-Implementierung : aktuelles double setzen auf eingestellten first respektive last value 182 SetSpinSize(double dStep)183 void SetSpinSize(double dStep) { m_dSpinSize = dStep; } GetSpinSize() const184 double GetSpinSize() const { return m_dSpinSize; } 185 SetSpinFirst(double dFirst)186 void SetSpinFirst(double dFirst) { m_dSpinFirst = dFirst; } GetSpinFirst() const187 double GetSpinFirst() const { return m_dSpinFirst; } 188 SetSpinLast(double dLast)189 void SetSpinLast(double dLast) { m_dSpinLast = dLast; } GetSpinLast() const190 double GetSpinLast() const { return m_dSpinLast; } 191 TreatingAsNumber() const192 sal_Bool TreatingAsNumber() const { return m_bTreatAsNumber; } TreatAsNumber(sal_Bool bDoSo)193 void TreatAsNumber(sal_Bool bDoSo) { m_bTreatAsNumber = bDoSo; } 194 195 public: 196 virtual void SetText( const XubString& rStr ); 197 virtual void SetText( const XubString& rStr, const Selection& rNewSelection ); 198 void SetValidateText(const XubString& rText, const String* pErrorText = NULL); 199 200 // die folgenden Methoden sind interesant, wenn m_bTreatAsNumber auf sal_False sitzt 201 /** nehmen wir mal an, irgendjemand will das ganze schoene double-Handling gar nicht haben, sondern 202 einfach den Text formatiert ausgeben ... 203 (der Text wird einfach nur durch den Formatter gejagt und dann gesetzt) 204 */ 205 void SetTextFormatted(const XubString& rText); 206 String GetTextValue() const; 207 SetDefaultText(const XubString & rDefault)208 void SetDefaultText(const XubString& rDefault) { m_sDefaultText = rDefault; } GetDefaultText() const209 String GetDefaultText() const { return m_sDefaultText; } 210 211 // die bei der letzten Ausgabe-Operation vom Formatter gelieferte Farbe (Ausgabe-Operationen werden getriggert durch 212 // SetValue, SetTextValue, SetTextFormatted, also indirekt eventuell auch durch SetMin-/-MaxValue) GetLastOutputColor() const213 Color* GetLastOutputColor() const { return m_pLastOutputColor; } 214 215 /** reformats the current text. Interesting if the user entered some text in an "input format", and 216 this should be formatted in the "output format" (which may differ, e.g. by additional numeric 217 digits or such). 218 */ 219 void Commit(); 220 221 // enable automatic coloring. if set to sal_True, and the format the field is working with for any current value 222 // says that it has to be painted in a special color (e.g. a format where negative numbers should be printed 223 // red), the text is painted with that color automatically. 224 // The color used is the same as returned by GetLastOutputColor() 225 void SetAutoColor(sal_Bool _bAutomatic); GetAutoColor() const226 sal_Bool GetAutoColor() const { return m_bAutoColor; } 227 228 /** enables handling of not-a-number value. 229 230 When this is set to <FALSE/> (the default), then invalid inputs (i.e. text which cannot be 231 intepreted, according to the current formatting) will be handled as if the default value 232 has been entered. GetValue the will return this default value. 233 234 When set to <TRUE/>, then GetValue will return NaN (not a number, see <method scope="rtl::math">isNan</method>) 235 when the current input is invalid. 236 237 Note that setting this to <TRUE/> implies that upon leaving the control, the input 238 will *not* be corrected to a valid value. For example, if the user enters "foo" in the 239 control, and then tabs out of it, the text "foo" will persist, and GetValue will 240 return NaN in subsequent calls. 241 */ 242 void EnableNotANumber( sal_Bool _bEnable ); IsNotANumberEnabled() const243 sal_Bool IsNotANumberEnabled( ) const { return m_bEnableNaN; } 244 245 /** When being set to true, the strings in the field are formatted using the 246 InputLine format. That's also what you get in Calc when you edit a cell 247 using F2 248 */ 249 void UseInputStringForFormatting( bool bUseInputStr = true ); 250 bool IsUsingInputStringForFormatting() const; 251 252 protected: 253 virtual long Notify(NotifyEvent& rNEvt); 254 virtual void Modify(); 255 256 // CheckText ueberschreiben fuer Ueberpruefung zur Eingabezeit CheckText(const XubString &) const257 virtual sal_Bool CheckText(const XubString&) const { return sal_True; } 258 259 // any aspect of the current format has changed 260 virtual void FormatChanged(FORMAT_CHANGE_TYPE nWhat); 261 262 void ImplSetTextImpl(const XubString& rNew, Selection* pNewSel); 263 void ImplSetValue(double dValue, sal_Bool bForce); 264 sal_Bool ImplGetValue(double& dNewVal); 265 266 void ImplSetFormatKey(sal_uLong nFormatKey); 267 // SetFormatKey without FormatChanged notification 268 CreateFormatter()269 virtual SvNumberFormatter* CreateFormatter() { SetFormatter(StandardFormatter()); return m_pFormatter; } ImplGetFormatter() const270 SvNumberFormatter* ImplGetFormatter() const { return m_pFormatter ? m_pFormatter : ((FormattedField*)this)->CreateFormatter(); } 271 272 long PreNotify(NotifyEvent& rNEvt); 273 274 virtual void ReFormat(); 275 }; 276 277 //------------------------------------------------------------------------------ 278 class SVT_DLLPUBLIC DoubleNumericField : public FormattedField 279 { 280 protected: 281 #ifdef REGEXP_SUPPORT 282 ::utl::TextSearch* m_pConformanceTester; 283 #else 284 validation::NumberValidator* m_pNumberValidator; 285 #endif 286 287 public: DoubleNumericField(Window * pParent,WinBits nStyle=0)288 DoubleNumericField(Window* pParent, WinBits nStyle = 0) 289 :FormattedField(pParent, nStyle) 290 #ifdef REGEXP_SUPPORT 291 ,m_pConformanceTester( NULL ) 292 #else 293 ,m_pNumberValidator( NULL ) 294 #endif 295 { 296 ResetConformanceTester(); 297 } 298 DoubleNumericField(Window * pParent,const ResId & rResId)299 DoubleNumericField(Window* pParent, const ResId& rResId) 300 :FormattedField(pParent, rResId) 301 #ifdef REGEXP_SUPPORT 302 ,m_pConformanceTester( NULL ) 303 #else 304 ,m_pNumberValidator( NULL ) 305 #endif 306 { 307 ResetConformanceTester(); 308 } 309 virtual ~DoubleNumericField(); 310 311 protected: 312 virtual sal_Bool CheckText(const XubString& sText) const; 313 314 virtual void FormatChanged(FORMAT_CHANGE_TYPE nWhat); 315 void ResetConformanceTester(); 316 }; 317 318 //============================================================================== 319 #define FCT_CURRENCY_SYMBOL 0x10 320 #define FCT_CURRSYM_POSITION 0x20 321 322 //------------------------------------------------------------------------------ 323 class DoubleCurrencyField : public FormattedField 324 { 325 XubString m_sCurrencySymbol; 326 sal_Bool m_bPrependCurrSym; 327 sal_Bool m_bChangingFormat; 328 329 public: 330 DoubleCurrencyField(Window* pParent, WinBits nStyle = 0); 331 DoubleCurrencyField(Window* pParent, const ResId& rResId); 332 getCurrencySymbol() const333 XubString getCurrencySymbol() const { return m_sCurrencySymbol; } 334 void setCurrencySymbol(const XubString& _sSymbol); 335 getPrependCurrSym() const336 sal_Bool getPrependCurrSym() const { return m_bPrependCurrSym; } 337 void setPrependCurrSym(sal_Bool _bPrepend); 338 339 protected: 340 virtual void FormatChanged(FORMAT_CHANGE_TYPE nWhat); 341 342 void UpdateCurrencyFormat(); 343 }; 344 345 #endif // _FMTFIELD_HXX_ 346 347