xref: /AOO41X/main/svtools/inc/svtools/fmtfield.hxx (revision 01aa44aa134af97080e2cf8e8bf3a0a4cd1cffe0)
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