Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <stdio.h>
31 : : #include <tools/debug.hxx>
32 : : #include <comphelper/processfactory.hxx>
33 : : #include <comphelper/string.hxx>
34 : : #include <unotools/localedatawrapper.hxx>
35 : : #include <vcl/svapp.hxx>
36 : : #include <svl/zformat.hxx>
37 : : #include <svtools/fmtfield.hxx>
38 : : #include <i18npool/mslangid.hxx>
39 : : #include <com/sun/star/lang/Locale.hpp>
40 : : #include <com/sun/star/util/SearchOptions.hpp>
41 : : #include <com/sun/star/util/SearchAlgorithms.hpp>
42 : : #include <com/sun/star/util/SearchResult.hpp>
43 : : #include <com/sun/star/util/SearchFlags.hpp>
44 : : #include <unotools/syslocale.hxx>
45 : : #include <map>
46 : : #include <rtl/math.hxx>
47 : :
48 : : using namespace ::com::sun::star::lang;
49 : : using namespace ::com::sun::star::util;
50 : :
51 : : // hmm. No support for regular expression. Well, I always (not really :) wanted to write a finite automat
52 : : // so here comes a finite automat ...
53 : :
54 : : namespace validation
55 : : {
56 : : // the states of our automat.
57 : : enum State
58 : : {
59 : : START, // at the very start of the string
60 : : NUM_START, // the very start of the number
61 : :
62 : : DIGIT_PRE_COMMA, // some pre-comma digits are read, perhaps including some thousand separators
63 : :
64 : : DIGIT_POST_COMMA, // reading digits after the comma
65 : : EXPONENT_START, // at the very start of the exponent value
66 : : // (means: not including the "e" which denotes the exponent)
67 : : EXPONENT_DIGIT, // currently reading the digits of the exponent
68 : :
69 : : END // reached the end of the string
70 : : };
71 : :
72 : : // a row in the transition table (means the set of states to be reached from a given state)
73 : : typedef ::std::map< sal_Unicode, State > StateTransitions;
74 : :
75 : : // a single transition
76 : : typedef StateTransitions::value_type Transition;
77 : :
78 : : // the complete transition table
79 : : typedef ::std::map< State, StateTransitions > TransitionTable;
80 : :
81 : : // the validator class
82 : 148 : class NumberValidator
83 : : {
84 : : private:
85 : : TransitionTable m_aTransitions;
86 : : const sal_Unicode m_cThSep;
87 : : const sal_Unicode m_cDecSep;
88 : :
89 : : public:
90 : : NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep );
91 : :
92 : : sal_Bool isValidNumericFragment( const String& _rText );
93 : :
94 : : private:
95 : : sal_Bool implValidateNormalized( const String& _rText );
96 : : };
97 : :
98 : : //--------------------------------------------------------------------------
99 : : //..........................................................................
100 : 592 : static void lcl_insertStopTransition( StateTransitions& _rRow )
101 : : {
102 [ + - ][ + - ]: 592 : _rRow.insert( Transition( '_', END ) );
103 : 592 : }
104 : :
105 : : //..........................................................................
106 : 444 : static void lcl_insertStartExponentTransition( StateTransitions& _rRow )
107 : : {
108 [ + - ][ + - ]: 444 : _rRow.insert( Transition( 'e', EXPONENT_START ) );
109 : 444 : }
110 : :
111 : : //..........................................................................
112 : 296 : static void lcl_insertSignTransitions( StateTransitions& _rRow, const State eNextState )
113 : : {
114 [ + - ][ + - ]: 296 : _rRow.insert( Transition( '-', eNextState ) );
115 [ + - ][ + - ]: 296 : _rRow.insert( Transition( '+', eNextState ) );
116 : 296 : }
117 : :
118 : : //..........................................................................
119 : 740 : static void lcl_insertDigitTransitions( StateTransitions& _rRow, const State eNextState )
120 : : {
121 [ + + ]: 8140 : for ( sal_Unicode aChar = '0'; aChar <= '9'; ++aChar )
122 [ + - ][ + - ]: 7400 : _rRow.insert( Transition( aChar, eNextState ) );
123 : 740 : }
124 : :
125 : : //..........................................................................
126 : 296 : static void lcl_insertCommonPreCommaTransitions( StateTransitions& _rRow, const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
127 : : {
128 : : // digits are allowed
129 : 296 : lcl_insertDigitTransitions( _rRow, DIGIT_PRE_COMMA );
130 : :
131 : : // the thousand separator is allowed
132 [ + - ][ + - ]: 296 : _rRow.insert( Transition( _cThSep, DIGIT_PRE_COMMA ) );
133 : :
134 : : // a comma is allowed
135 [ + - ][ + - ]: 296 : _rRow.insert( Transition( _cDecSep, DIGIT_POST_COMMA ) );
136 : 296 : }
137 : :
138 : : //--------------------------------------------------------------------------
139 : 148 : NumberValidator::NumberValidator( const sal_Unicode _cThSep, const sal_Unicode _cDecSep )
140 : : :m_cThSep( _cThSep )
141 : 148 : ,m_cDecSep( _cDecSep )
142 : : {
143 : : // build up our transition table
144 : :
145 : : // how to procede from START
146 : : {
147 [ + - ]: 148 : StateTransitions& rRow = m_aTransitions[ START ];
148 [ + - ][ + - ]: 148 : rRow.insert( Transition( '_', NUM_START ) );
149 : : // if we encounter the normalizing character, we want to procede with the number
150 : : }
151 : :
152 : : // how to procede from NUM_START
153 : : {
154 [ + - ]: 148 : StateTransitions& rRow = m_aTransitions[ NUM_START ];
155 : :
156 : : // a sign is allowed
157 [ + - ]: 148 : lcl_insertSignTransitions( rRow, DIGIT_PRE_COMMA );
158 : :
159 : : // common transitions for the two pre-comma states
160 [ + - ]: 148 : lcl_insertCommonPreCommaTransitions( rRow, m_cThSep, m_cDecSep );
161 : :
162 : : // the exponent may start here
163 : : // (this would mean string like "_+e10_", but this is a valid fragment, though no valid number)
164 [ + - ]: 148 : lcl_insertStartExponentTransition( rRow );
165 : : }
166 : :
167 : : // how to procede from DIGIT_PRE_COMMA
168 : : {
169 [ + - ]: 148 : StateTransitions& rRow = m_aTransitions[ DIGIT_PRE_COMMA ];
170 : :
171 : : // common transitions for the two pre-comma states
172 [ + - ]: 148 : lcl_insertCommonPreCommaTransitions( rRow, m_cThSep, m_cDecSep );
173 : :
174 : : // the exponent may start here
175 [ + - ]: 148 : lcl_insertStartExponentTransition( rRow );
176 : :
177 : : // the final transition indicating the end of the string
178 : : // (if there is no comma and no post-comma, then the string may end here)
179 [ + - ]: 148 : lcl_insertStopTransition( rRow );
180 : : }
181 : :
182 : : // how to procede from DIGIT_POST_COMMA
183 : : {
184 [ + - ]: 148 : StateTransitions& rRow = m_aTransitions[ DIGIT_POST_COMMA ];
185 : :
186 : : // there might be digits, which would keep the state at DIGIT_POST_COMMA
187 [ + - ]: 148 : lcl_insertDigitTransitions( rRow, DIGIT_POST_COMMA );
188 : :
189 : : // the exponent may start here
190 [ + - ]: 148 : lcl_insertStartExponentTransition( rRow );
191 : :
192 : : // the string may end here
193 [ + - ]: 148 : lcl_insertStopTransition( rRow );
194 : : }
195 : :
196 : : // how to procede from EXPONENT_START
197 : : {
198 [ + - ]: 148 : StateTransitions& rRow = m_aTransitions[ EXPONENT_START ];
199 : :
200 : : // there may be a sign
201 [ + - ]: 148 : lcl_insertSignTransitions( rRow, EXPONENT_DIGIT );
202 : :
203 : : // there may be digits
204 [ + - ]: 148 : lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
205 : :
206 : : // the string may end here
207 [ + - ]: 148 : lcl_insertStopTransition( rRow );
208 : : }
209 : :
210 : : // how to procede from EXPONENT_DIGIT
211 : : {
212 [ + - ]: 148 : StateTransitions& rRow = m_aTransitions[ EXPONENT_DIGIT ];
213 : :
214 : : // there may be digits
215 [ + - ]: 148 : lcl_insertDigitTransitions( rRow, EXPONENT_DIGIT );
216 : :
217 : : // the string may end here
218 [ + - ]: 148 : lcl_insertStopTransition( rRow );
219 : : }
220 : :
221 : : // how to procede from END
222 : : {
223 [ + - ]: 148 : /*StateTransitions& rRow =*/ m_aTransitions[ EXPONENT_DIGIT ];
224 : : // no valid transition to leave this state
225 : : // (note that we, for consistency, nevertheless want to have a row in the table)
226 : : }
227 : 148 : }
228 : :
229 : : //--------------------------------------------------------------------------
230 : 56 : sal_Bool NumberValidator::implValidateNormalized( const String& _rText )
231 : : {
232 : 56 : const sal_Unicode* pCheckPos = _rText.GetBuffer();
233 : 56 : State eCurrentState = START;
234 : :
235 [ + + ]: 368 : while ( END != eCurrentState )
236 : : {
237 : : // look up the transition row for the current state
238 [ + - ][ + - ]: 328 : TransitionTable::const_iterator aRow = m_aTransitions.find( eCurrentState );
239 : : DBG_ASSERT( m_aTransitions.end() != aRow,
240 : : "NumberValidator::implValidateNormalized: invalid transition table (row not found)!" );
241 : :
242 [ + - ][ + - ]: 328 : if ( m_aTransitions.end() != aRow )
243 : : {
244 : : // look up the current character in this row
245 [ + - ][ + - ]: 328 : StateTransitions::const_iterator aTransition = aRow->second.find( *pCheckPos );
246 [ + - ][ + - ]: 328 : if ( aRow->second.end() != aTransition )
[ + + ]
247 : : {
248 : : // there is a valid transition for this character
249 [ + - ]: 312 : eCurrentState = aTransition->second;
250 : 312 : ++pCheckPos;
251 : 328 : continue;
252 : : }
253 : : }
254 : :
255 : : // if we're here, there is no valid transition
256 : : break;
257 : : }
258 : :
259 : : DBG_ASSERT( ( END != eCurrentState ) || ( 0 == *pCheckPos ),
260 : : "NumberValidator::implValidateNormalized: inconsistency!" );
261 : : // if we're at END, then the string should be done, too - the string should be normalized, means ending
262 : : // a "_" and not containing any other "_" (except at the start), and "_" is the only possibility
263 : : // to reach the END state
264 : :
265 : : // the string is valid if and only if we reached the final state
266 : 56 : return ( END == eCurrentState );
267 : : }
268 : :
269 : : //--------------------------------------------------------------------------
270 : 56 : sal_Bool NumberValidator::isValidNumericFragment( const String& _rText )
271 : : {
272 [ - + ]: 56 : if ( !_rText.Len() )
273 : : // empty strings are always allowed
274 : 0 : return sal_True;
275 : :
276 : : // normalize the string
277 [ + - ]: 56 : String sNormalized( RTL_CONSTASCII_USTRINGPARAM("_") );
278 [ + - ]: 56 : sNormalized.Append( _rText );
279 [ + - ]: 56 : sNormalized.AppendAscii( "_" );
280 : :
281 [ + - ][ + - ]: 56 : return implValidateNormalized( sNormalized );
282 : : }
283 : : }
284 : :
285 : : //==============================================================================
286 : : SvNumberFormatter* FormattedField::StaticFormatter::s_cFormatter = NULL;
287 : : sal_uLong FormattedField::StaticFormatter::s_nReferences = 0;
288 : :
289 : : //------------------------------------------------------------------------------
290 : 70 : SvNumberFormatter* FormattedField::StaticFormatter::GetFormatter()
291 : : {
292 [ + - ]: 70 : if (!s_cFormatter)
293 : : {
294 : : // get the Office's locale and translate
295 : : LanguageType eSysLanguage = MsLangId::convertLocaleToLanguage(
296 [ + - ][ + - ]: 70 : SvtSysLocale().GetLocaleData().getLocale() );
[ + - ]
297 : : s_cFormatter = new SvNumberFormatter(
298 : : ::comphelper::getProcessServiceFactory(),
299 [ + - ][ + - ]: 70 : eSysLanguage);
300 : : }
301 : 70 : return s_cFormatter;
302 : : }
303 : :
304 : : //------------------------------------------------------------------------------
305 : 126 : FormattedField::StaticFormatter::StaticFormatter()
306 : : {
307 : 126 : ++s_nReferences;
308 : 126 : }
309 : :
310 : : //------------------------------------------------------------------------------
311 : 126 : FormattedField::StaticFormatter::~StaticFormatter()
312 : : {
313 [ + + ]: 126 : if (--s_nReferences == 0)
314 : : {
315 [ + + ]: 72 : delete s_cFormatter;
316 : 72 : s_cFormatter = NULL;
317 : : }
318 : 126 : }
319 : :
320 : : //==============================================================================
321 : : DBG_NAME(FormattedField);
322 : :
323 : : #define INIT_MEMBERS() \
324 : : m_aLastSelection(0,0) \
325 : : ,m_dMinValue(0) \
326 : : ,m_dMaxValue(0) \
327 : : ,m_bHasMin(sal_False) \
328 : : ,m_bHasMax(sal_False) \
329 : : ,m_bStrictFormat(sal_True) \
330 : : ,m_bValueDirty(sal_True) \
331 : : ,m_bEnableEmptyField(sal_True) \
332 : : ,m_bAutoColor(sal_False) \
333 : : ,m_bEnableNaN(sal_False) \
334 : : ,m_dCurrentValue(0) \
335 : : ,m_dDefaultValue(0) \
336 : : ,m_nFormatKey(0) \
337 : : ,m_pFormatter(NULL) \
338 : : ,m_dSpinSize(1) \
339 : : ,m_dSpinFirst(-1000000) \
340 : : ,m_dSpinLast(1000000) \
341 : : ,m_bTreatAsNumber(sal_True) \
342 : : ,m_pLastOutputColor(NULL) \
343 : : ,m_bUseInputStringForFormatting(false)
344 : :
345 : : //------------------------------------------------------------------------------
346 : 126 : FormattedField::FormattedField(Window* pParent, WinBits nStyle, SvNumberFormatter* pInitialFormatter, sal_Int32 nFormatKey)
347 : : :SpinField(pParent, nStyle)
348 [ + - ][ + - ]: 126 : ,INIT_MEMBERS()
[ + - ][ + - ]
349 : : {
350 : : DBG_CTOR(FormattedField, NULL);
351 : :
352 [ - + ]: 126 : if (pInitialFormatter)
353 : : {
354 : 0 : m_pFormatter = pInitialFormatter;
355 : 0 : m_nFormatKey = nFormatKey;
356 : : }
357 : 126 : }
358 : :
359 : : //------------------------------------------------------------------------------
360 : 0 : FormattedField::FormattedField(Window* pParent, const ResId& rResId, SvNumberFormatter* pInitialFormatter, sal_Int32 nFormatKey)
361 : : :SpinField(pParent, rResId)
362 [ # # ][ # # ]: 0 : ,INIT_MEMBERS()
[ # # ][ # # ]
363 : : {
364 : : DBG_CTOR(FormattedField, NULL);
365 : :
366 [ # # ]: 0 : if (pInitialFormatter)
367 : : {
368 : 0 : m_pFormatter = pInitialFormatter;
369 : 0 : m_nFormatKey = nFormatKey;
370 : : }
371 : 0 : }
372 : :
373 : : //------------------------------------------------------------------------------
374 [ + - ][ + - ]: 126 : FormattedField::~FormattedField()
[ + - ][ + - ]
375 : : {
376 : : DBG_DTOR(FormattedField, NULL);
377 [ - + ]: 184 : }
378 : :
379 : : //------------------------------------------------------------------------------
380 : 156 : void FormattedField::SetText(const XubString& rStr)
381 : : {
382 : : DBG_CHKTHIS(FormattedField, NULL);
383 : :
384 : 156 : SpinField::SetText(rStr);
385 : 156 : m_bValueDirty = sal_True;
386 : 156 : }
387 : :
388 : : //------------------------------------------------------------------------------
389 : 0 : void FormattedField::SetText( const XubString& rStr, const Selection& rNewSelection )
390 : : {
391 : : DBG_CHKTHIS(FormattedField, NULL);
392 : :
393 : 0 : SpinField::SetText( rStr, rNewSelection );
394 : 0 : m_bValueDirty = sal_True;
395 : 0 : }
396 : :
397 : : //------------------------------------------------------------------------------
398 : 32 : void FormattedField::SetTextFormatted(const XubString& rStr)
399 : : {
400 : : DBG_CHKTHIS(FormattedField, NULL);
401 : :
402 : : #if defined DBG_UTIL
403 : : if (ImplGetFormatter()->IsTextFormat(m_nFormatKey))
404 : : DBG_WARNING("FormattedField::SetTextFormatted : valid only with text formats !");
405 : : #endif
406 : :
407 [ + - ]: 32 : m_sCurrentTextValue = rStr;
408 : :
409 [ + - ]: 32 : String sFormatted;
410 : 32 : double dNumber = 0.0;
411 : : // IsNumberFormat changes the format key parameter
412 : 32 : sal_uInt32 nTempFormatKey = static_cast< sal_uInt32 >( m_nFormatKey );
413 [ + - ][ - + ]: 32 : if( IsUsingInputStringForFormatting() &&
[ # # ][ - + ]
414 [ # # ][ # # ]: 0 : ImplGetFormatter()->IsNumberFormat(m_sCurrentTextValue, nTempFormatKey, dNumber) )
415 [ # # ][ # # ]: 0 : ImplGetFormatter()->GetInputLineString(dNumber, m_nFormatKey, sFormatted);
416 : : else
417 [ + - ][ + - ]: 32 : ImplGetFormatter()->GetOutputString(m_sCurrentTextValue, m_nFormatKey, sFormatted, &m_pLastOutputColor);
418 : :
419 : : // calculate the new selection
420 [ + - ]: 32 : Selection aSel(GetSelection());
421 : 32 : Selection aNewSel(aSel);
422 : 32 : aNewSel.Justify();
423 : 32 : sal_uInt16 nNewLen = sFormatted.Len();
424 [ + - ][ + - ]: 32 : sal_uInt16 nCurrentLen = GetText().Len();
425 [ + + ][ + - ]: 32 : if ((nNewLen > nCurrentLen) && (aNewSel.Max() == nCurrentLen))
[ + + ]
426 : : { // the new text is longer and the cursor was behind the last char (of the old text)
427 [ + - ]: 4 : if (aNewSel.Min() == 0)
428 : : { // the whole text was selected -> select the new text on the whole, too
429 : 4 : aNewSel.Max() = nNewLen;
430 [ + - ]: 4 : if (!nCurrentLen)
431 : : { // there wasn't really a previous selection (as there was no previous text), we're setting a new one -> check the selection options
432 : 4 : sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
433 [ - + ]: 4 : if (nSelOptions & SELECTION_OPTION_SHOWFIRST)
434 : : { // selection should be from right to left -> swap min and max
435 : 0 : aNewSel.Min() = aNewSel.Max();
436 : 0 : aNewSel.Max() = 0;
437 : : }
438 : : }
439 : : }
440 [ # # ]: 0 : else if (aNewSel.Max() == aNewSel.Min())
441 : : { // there was no selection -> set the cursor behind the new last char
442 : 0 : aNewSel.Max() = nNewLen;
443 : 0 : aNewSel.Min() = nNewLen;
444 : : }
445 : : }
446 [ - + ]: 28 : else if (aNewSel.Max() > nNewLen)
447 : 0 : aNewSel.Max() = nNewLen;
448 : : else
449 : 28 : aNewSel = aSel; // don't use the justified version
450 [ + - ]: 32 : SpinField::SetText(sFormatted, aNewSel);
451 [ + - ]: 32 : m_bValueDirty = sal_False;
452 : 32 : }
453 : :
454 : : //------------------------------------------------------------------------------
455 : 0 : String FormattedField::GetTextValue() const
456 : : {
457 [ # # ]: 0 : if (m_bValueDirty)
458 : : {
459 [ # # ]: 0 : ((FormattedField*)this)->m_sCurrentTextValue = GetText();
460 : 0 : ((FormattedField*)this)->m_bValueDirty = sal_False;
461 : : }
462 : 0 : return m_sCurrentTextValue;
463 : : }
464 : :
465 : : //------------------------------------------------------------------------------
466 : 107 : void FormattedField::EnableNotANumber( sal_Bool _bEnable )
467 : : {
468 [ + + ]: 107 : if ( m_bEnableNaN == _bEnable )
469 : 107 : return;
470 : :
471 : 54 : m_bEnableNaN = _bEnable;
472 : : }
473 : :
474 : : //------------------------------------------------------------------------------
475 : 140 : void FormattedField::SetAutoColor(sal_Bool _bAutomatic)
476 : : {
477 [ + + ]: 140 : if (_bAutomatic == m_bAutoColor)
478 : 140 : return;
479 : :
480 : 70 : m_bAutoColor = _bAutomatic;
481 [ + - ]: 70 : if (m_bAutoColor)
482 : : { // if auto color is switched on, adjust the current text color, too
483 [ - + ]: 70 : if (m_pLastOutputColor)
484 : 0 : SetControlForeground(*m_pLastOutputColor);
485 : : else
486 : 70 : SetControlForeground();
487 : : }
488 : : }
489 : :
490 : : //------------------------------------------------------------------------------
491 : 138 : void FormattedField::Modify()
492 : : {
493 : : DBG_CHKTHIS(FormattedField, NULL);
494 : :
495 [ - + ]: 138 : if (!IsStrictFormat())
496 : : {
497 : 0 : m_bValueDirty = sal_True;
498 [ # # ]: 0 : SpinField::Modify();
499 : 138 : return;
500 : : }
501 : :
502 [ + - ]: 138 : String sCheck = GetText();
503 [ + - ][ + + ]: 138 : if (CheckText(sCheck))
504 : : {
505 [ + - ]: 122 : m_sLastValidText = sCheck;
506 [ + - ]: 122 : m_aLastSelection = GetSelection();
507 : 122 : m_bValueDirty = sal_True;
508 : : }
509 : : else
510 : : {
511 [ + - ]: 16 : ImplSetTextImpl(m_sLastValidText, &m_aLastSelection);
512 : : }
513 : :
514 [ + - ][ + - ]: 138 : SpinField::Modify();
515 : : }
516 : :
517 : : //------------------------------------------------------------------------------
518 : 164 : void FormattedField::ImplSetTextImpl(const XubString& rNew, Selection* pNewSel)
519 : : {
520 : : DBG_CHKTHIS(FormattedField, NULL);
521 : :
522 [ + - ]: 164 : if (m_bAutoColor)
523 : : {
524 [ - + ]: 164 : if (m_pLastOutputColor)
525 : 0 : SetControlForeground(*m_pLastOutputColor);
526 : : else
527 : 164 : SetControlForeground();
528 : : }
529 : :
530 [ + + ]: 164 : if (pNewSel)
531 : 16 : SpinField::SetText(rNew, *pNewSel);
532 : : else
533 : : {
534 [ + - ]: 148 : Selection aSel(GetSelection());
535 : 148 : aSel.Justify();
536 : :
537 : 148 : sal_uInt16 nNewLen = rNew.Len();
538 [ + - ][ + - ]: 148 : sal_uInt16 nCurrentLen = GetText().Len();
539 : :
540 [ + + ][ + + ]: 148 : if ((nNewLen > nCurrentLen) && (aSel.Max() == nCurrentLen))
[ + + ]
541 : : { // new new text is longer and the cursor is behind the last char
542 [ + + ]: 50 : if (aSel.Min() == 0)
543 : : { // the whole text was selected -> select the new text on the whole, too
544 : 46 : aSel.Max() = nNewLen;
545 [ + + ]: 46 : if (!nCurrentLen)
546 : : { // there wasn't really a previous selection (as there was no previous text), we're setting a new one -> check the selection options
547 : 22 : sal_uLong nSelOptions = GetSettings().GetStyleSettings().GetSelectionOptions();
548 [ - + ]: 22 : if (nSelOptions & SELECTION_OPTION_SHOWFIRST)
549 : : { // selection should be from right to left -> swap min and max
550 : 0 : aSel.Min() = aSel.Max();
551 : 0 : aSel.Max() = 0;
552 : : }
553 : : }
554 : : }
555 [ - + ]: 4 : else if (aSel.Max() == aSel.Min())
556 : : { // there was no selection -> set the cursor behind the new last char
557 : 0 : aSel.Max() = nNewLen;
558 : 0 : aSel.Min() = nNewLen;
559 : : }
560 : : }
561 [ + + ]: 98 : else if (aSel.Max() > nNewLen)
562 : 8 : aSel.Max() = nNewLen;
563 [ + - ]: 148 : SpinField::SetText(rNew, aSel);
564 : : }
565 : :
566 : 164 : m_bValueDirty = sal_True;
567 : : // muss nicht stimmen, aber sicherheitshalber ...
568 : 164 : }
569 : :
570 : : //------------------------------------------------------------------------------
571 : 0 : long FormattedField::PreNotify(NotifyEvent& rNEvt)
572 : : {
573 : : DBG_CHKTHIS(FormattedField, NULL);
574 [ # # ]: 0 : if (rNEvt.GetType() == EVENT_KEYINPUT)
575 : 0 : m_aLastSelection = GetSelection();
576 : 0 : return SpinField::PreNotify(rNEvt);
577 : : }
578 : :
579 : : //------------------------------------------------------------------------------
580 : 406 : void FormattedField::ImplSetFormatKey(sal_uLong nFormatKey)
581 : : {
582 : : DBG_CHKTHIS(FormattedField, NULL);
583 : :
584 : 406 : m_nFormatKey = nFormatKey;
585 [ - + ][ # # ]: 406 : sal_Bool bNeedFormatter = (m_pFormatter == NULL) && (nFormatKey != 0);
586 [ - + ]: 406 : if (bNeedFormatter)
587 : : {
588 : 0 : ImplGetFormatter(); // damit wird ein Standard-Formatter angelegt
589 : :
590 : 0 : m_nFormatKey = nFormatKey;
591 : : // kann sein, dass das in dem Standard-Formatter keinen Sinn macht, aber der nimmt dann ein Default-Format an.
592 : : // Auf diese Weise kann ich einfach einen der - formatteruebergreifended gleichen - Standard-Keys setzen.
593 : : DBG_ASSERT(m_pFormatter->GetEntry(nFormatKey) != NULL, "FormattedField::ImplSetFormatKey : invalid format key !");
594 : : // Wenn SetFormatKey aufgerufen wird, ohne dass ein Formatter existiert, muss der Key einer der Standard-Werte
595 : : // sein, der in allen Formattern (also auch in meinem neu angelegten) vorhanden ist.
596 : : }
597 : 406 : }
598 : :
599 : : //------------------------------------------------------------------------------
600 : 246 : void FormattedField::SetFormatKey(sal_uLong nFormatKey)
601 : : {
602 : : DBG_CHKTHIS(FormattedField, NULL);
603 : 246 : sal_Bool bNoFormatter = (m_pFormatter == NULL);
604 : 246 : ImplSetFormatKey(nFormatKey);
605 [ # # ][ - + ]: 246 : FormatChanged((bNoFormatter && (m_pFormatter != NULL)) ? FCT_FORMATTER : FCT_KEYONLY);
606 : 246 : }
607 : :
608 : : //------------------------------------------------------------------------------
609 : 128 : void FormattedField::SetFormatter(SvNumberFormatter* pFormatter, sal_Bool bResetFormat)
610 : : {
611 : : DBG_CHKTHIS(FormattedField, NULL);
612 : :
613 [ + + ]: 128 : if (bResetFormat)
614 : : {
615 : 126 : m_pFormatter = pFormatter;
616 : :
617 : : // calc the default format key from the Office's UI locale
618 [ + - ]: 126 : if ( m_pFormatter )
619 : : {
620 : : // get the Office's locale and translate
621 : : LanguageType eSysLanguage = MsLangId::convertLocaleToLanguage(
622 [ + - ][ + - ]: 126 : SvtSysLocale().GetLocaleData().getLocale() );
[ + - ]
623 : : // get the standard numeric format for this language
624 : 126 : m_nFormatKey = m_pFormatter->GetStandardFormat( NUMBERFORMAT_NUMBER, eSysLanguage );
625 : : }
626 : : else
627 : 0 : m_nFormatKey = 0;
628 : : }
629 : : else
630 : : {
631 [ + - ]: 2 : XubString sOldFormat;
632 : : LanguageType aOldLang;
633 [ + - ]: 2 : GetFormat(sOldFormat, aOldLang);
634 : :
635 [ + - ]: 2 : sal_uInt32 nDestKey = pFormatter->TestNewString(sOldFormat);
636 [ - + ]: 2 : if (nDestKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
637 : : {
638 : : // die Sprache des neuen Formatters
639 [ # # ]: 0 : const SvNumberformat* pDefaultEntry = pFormatter->GetEntry(0);
640 [ # # ]: 0 : LanguageType aNewLang = pDefaultEntry ? pDefaultEntry->GetLanguage() : LANGUAGE_DONTKNOW;
641 : :
642 : : // den alten Format-String in die neue Sprache konvertieren
643 : : sal_uInt16 nCheckPos;
644 : : short nType;
645 [ # # ]: 0 : pFormatter->PutandConvertEntry(sOldFormat, nCheckPos, nType, nDestKey, aOldLang, aNewLang);
646 : 0 : m_nFormatKey = nDestKey;
647 : : }
648 [ + - ]: 2 : m_pFormatter = pFormatter;
649 : : }
650 : :
651 : 128 : FormatChanged(FCT_FORMATTER);
652 : 128 : }
653 : :
654 : : //------------------------------------------------------------------------------
655 : 384 : void FormattedField::GetFormat(XubString& rFormatString, LanguageType& eLang) const
656 : : {
657 : : DBG_CHKTHIS(FormattedField, NULL);
658 : 384 : const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
659 : : DBG_ASSERT(pFormatEntry != NULL, "FormattedField::GetFormat: no number format for the given format key.");
660 [ + - ][ + - ]: 384 : rFormatString = pFormatEntry ? pFormatEntry->GetFormatstring() : XubString();
661 [ + - ]: 384 : eLang = pFormatEntry ? pFormatEntry->GetLanguage() : LANGUAGE_DONTKNOW;
662 : 384 : }
663 : :
664 : : //------------------------------------------------------------------------------
665 : 222 : sal_Bool FormattedField::SetFormat(const XubString& rFormatString, LanguageType eLang)
666 : : {
667 : : DBG_CHKTHIS(FormattedField, NULL);
668 [ + - ][ + - ]: 222 : sal_uInt32 nNewKey = ImplGetFormatter()->TestNewString(rFormatString, eLang);
669 [ + + ]: 222 : if (nNewKey == NUMBERFORMAT_ENTRY_NOT_FOUND)
670 : : {
671 : : sal_uInt16 nCheckPos;
672 : : short nType;
673 [ + - ]: 188 : XubString rFormat(rFormatString);
674 [ + - ][ + - ]: 188 : if (!ImplGetFormatter()->PutEntry(rFormat, nCheckPos, nType, nNewKey, eLang))
[ - + ]
675 : 188 : return sal_False;
676 [ + - ][ + - ]: 188 : DBG_ASSERT(nNewKey != NUMBERFORMAT_ENTRY_NOT_FOUND, "FormattedField::SetFormatString : PutEntry returned an invalid key !");
677 : : }
678 : :
679 [ + + ]: 222 : if (nNewKey != m_nFormatKey)
680 [ + - ]: 188 : SetFormatKey(nNewKey);
681 : 222 : return sal_True;
682 : : }
683 : :
684 : : //------------------------------------------------------------------------------
685 : 222 : sal_Bool FormattedField::GetThousandsSep() const
686 : : {
687 : : DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
688 : : "FormattedField::GetThousandsSep : your'e sure what your'e doing when setting the precision of a text format ?");
689 : :
690 : : bool bThousand, IsRed;
691 : : sal_uInt16 nPrecision, nAnzLeading;
692 [ + - ][ + - ]: 222 : ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
693 : :
694 : 222 : return bThousand;
695 : : }
696 : :
697 : : //------------------------------------------------------------------------------
698 : 100 : void FormattedField::SetThousandsSep(sal_Bool _bUseSeparator)
699 : : {
700 : : DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
701 : : "FormattedField::SetThousandsSep : your'e sure what your'e doing when setting the precision of a text format ?");
702 : :
703 : : // get the current settings
704 : : bool bThousand, IsRed;
705 : : sal_uInt16 nPrecision, nAnzLeading;
706 [ + - ][ + - ]: 100 : ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
707 [ + + ]: 100 : if (bThousand == (bool)_bUseSeparator)
708 : 100 : return;
709 : :
710 : : // we need the language for the following
711 : : LanguageType eLang;
712 [ + - ]: 52 : String sFmtDescription;
713 [ + - ]: 52 : GetFormat(sFmtDescription, eLang);
714 : :
715 : : // generate a new format ...
716 [ + - ][ + - ]: 52 : ImplGetFormatter()->GenerateFormat(sFmtDescription, m_nFormatKey, eLang, _bUseSeparator, IsRed, nPrecision, nAnzLeading);
717 : : // ... and introduce it to the formatter
718 : : sal_uInt16 nCheckPos;
719 : : sal_uInt32 nNewKey;
720 : : short nType;
721 [ + - ][ + - ]: 52 : ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
722 : :
723 : : // set the new key
724 [ + - ]: 52 : ImplSetFormatKey(nNewKey);
725 [ + - ][ + - ]: 100 : FormatChanged(FCT_THOUSANDSSEP);
726 : : }
727 : :
728 : : //------------------------------------------------------------------------------
729 : 222 : sal_uInt16 FormattedField::GetDecimalDigits() const
730 : : {
731 : : DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
732 : : "FormattedField::GetDecimalDigits : your'e sure what your'e doing when setting the precision of a text format ?");
733 : :
734 : : bool bThousand, IsRed;
735 : : sal_uInt16 nPrecision, nAnzLeading;
736 [ + - ][ + - ]: 222 : ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
737 : :
738 : 222 : return nPrecision;
739 : : }
740 : :
741 : : //------------------------------------------------------------------------------
742 : 108 : void FormattedField::SetDecimalDigits(sal_uInt16 _nPrecision)
743 : : {
744 : : DBG_ASSERT(!ImplGetFormatter()->IsTextFormat(m_nFormatKey),
745 : : "FormattedField::SetDecimalDigits : your'e sure what your'e doing when setting the precision of a text format ?");
746 : :
747 : : // get the current settings
748 : : bool bThousand, IsRed;
749 : : sal_uInt16 nPrecision, nAnzLeading;
750 [ + - ][ + - ]: 108 : ImplGetFormatter()->GetFormatSpecialInfo(m_nFormatKey, bThousand, IsRed, nPrecision, nAnzLeading);
751 [ + - ]: 108 : if (nPrecision == _nPrecision)
752 : 108 : return;
753 : :
754 : : // we need the language for the following
755 : : LanguageType eLang;
756 [ + - ]: 108 : String sFmtDescription;
757 [ + - ]: 108 : GetFormat(sFmtDescription, eLang);
758 : :
759 : : // generate a new format ...
760 [ + - ][ + - ]: 108 : ImplGetFormatter()->GenerateFormat(sFmtDescription, m_nFormatKey, eLang, bThousand, IsRed, _nPrecision, nAnzLeading);
761 : : // ... and introduce it to the formatter
762 : : sal_uInt16 nCheckPos;
763 : : sal_uInt32 nNewKey;
764 : : short nType;
765 [ + - ][ + - ]: 108 : ImplGetFormatter()->PutEntry(sFmtDescription, nCheckPos, nType, nNewKey, eLang);
766 : :
767 : : // set the new key
768 [ + - ]: 108 : ImplSetFormatKey(nNewKey);
769 [ + - ][ + - ]: 108 : FormatChanged(FCT_PRECISION);
770 : : }
771 : :
772 : : //------------------------------------------------------------------------------
773 : 608 : void FormattedField::FormatChanged( FORMAT_CHANGE_TYPE _nWhat )
774 : : {
775 : : DBG_CHKTHIS(FormattedField, NULL);
776 : 608 : m_pLastOutputColor = NULL;
777 : :
778 [ + + ][ + - ]: 608 : if ( ( 0 != ( _nWhat & FCT_FORMATTER ) ) && m_pFormatter )
779 : 180 : m_pFormatter->SetEvalDateFormat( NF_EVALDATEFORMAT_INTL_FORMAT );
780 : :
781 : 608 : ReFormat();
782 : 608 : }
783 : :
784 : : //------------------------------------------------------------------------------
785 : 0 : void FormattedField::Commit()
786 : : {
787 : : // remember the old text
788 [ # # ]: 0 : String sOld( GetText() );
789 : :
790 : : // do the reformat
791 [ # # ]: 0 : ReFormat();
792 : :
793 : : // did the text change?
794 [ # # ][ # # ]: 0 : if ( GetText() != sOld )
[ # # ][ # # ]
795 : : { // consider the field as modified
796 [ # # ]: 0 : Modify();
797 : : // but we have the most recent value now
798 : 0 : m_bValueDirty = sal_False;
799 [ # # ]: 0 : }
800 : 0 : }
801 : :
802 : : //------------------------------------------------------------------------------
803 : 840 : void FormattedField::ReFormat()
804 : : {
805 [ + - ][ + - ]: 840 : if (!IsEmptyFieldEnabled() || GetText().Len())
[ + + ][ + - ]
[ + + # # ]
806 : : {
807 [ + - ]: 94 : if (TreatingAsNumber())
808 : : {
809 : 94 : double dValue = GetValue();
810 [ - + ][ - + ]: 94 : if ( m_bEnableNaN && ::rtl::math::isNan( dValue ) )
[ + + ]
811 : 840 : return;
812 : 94 : ImplSetValue( dValue, sal_True );
813 : : }
814 : : else
815 [ # # ]: 0 : SetTextFormatted(GetTextValue());
816 : : }
817 : : }
818 : :
819 : : //------------------------------------------------------------------------------
820 : 50 : long FormattedField::Notify(NotifyEvent& rNEvt)
821 : : {
822 : : DBG_CHKTHIS(FormattedField, NULL);
823 : :
824 [ - + ][ # # ]: 50 : if ((rNEvt.GetType() == EVENT_KEYINPUT) && !IsReadOnly())
[ - + ]
825 : : {
826 : 0 : const KeyEvent& rKEvt = *rNEvt.GetKeyEvent();
827 : 0 : sal_uInt16 nMod = rKEvt.GetKeyCode().GetModifier();
828 [ # # ]: 0 : switch ( rKEvt.GetKeyCode().GetCode() )
829 : : {
830 : : case KEY_UP:
831 : : case KEY_DOWN:
832 : : case KEY_PAGEUP:
833 : : case KEY_PAGEDOWN:
834 [ # # ][ # # ]: 0 : if (!nMod && ImplGetFormatter()->IsTextFormat(m_nFormatKey))
[ # # ]
835 : : {
836 : : // the base class would translate this into calls to Up/Down/First/Last,
837 : : // but we don't want this if we are text-formatted
838 : 0 : return 1;
839 : : }
840 : : }
841 : : }
842 : :
843 [ - + ][ # # ]: 50 : if ((rNEvt.GetType() == EVENT_COMMAND) && !IsReadOnly())
[ - + ]
844 : : {
845 : 0 : const CommandEvent* pCommand = rNEvt.GetCommandEvent();
846 [ # # ]: 0 : if (pCommand->GetCommand() == COMMAND_WHEEL)
847 : : {
848 : 0 : const CommandWheelData* pData = rNEvt.GetCommandEvent()->GetWheelData();
849 [ # # ][ # # ]: 0 : if ((pData->GetMode() == COMMAND_WHEEL_SCROLL) && ImplGetFormatter()->IsTextFormat(m_nFormatKey))
[ # # ]
850 : : {
851 : : // same as above : prevent the base class from doing Up/Down-calls
852 : : // (normally I should put this test into the Up/Down methods itself, shouldn't I ?)
853 : : // FS - 71553 - 19.01.00
854 : 0 : return 1;
855 : : }
856 : : }
857 : : }
858 : :
859 [ - + ]: 50 : if (rNEvt.GetType() == EVENT_LOSEFOCUS)
860 : : {
861 : : // Sonderbehandlung fuer leere Texte
862 [ # # ]: 0 : if (GetText().Len() == 0)
863 : : {
864 [ # # ]: 0 : if (!IsEmptyFieldEnabled())
865 : : {
866 [ # # ]: 0 : if (TreatingAsNumber())
867 : : {
868 : 0 : ImplSetValue(m_dCurrentValue, sal_True);
869 : 0 : Modify();
870 : : }
871 : : else
872 : : {
873 [ # # ]: 0 : String sNew = GetTextValue();
874 [ # # ]: 0 : if (sNew.Len())
875 [ # # ]: 0 : SetTextFormatted(sNew);
876 : : else
877 [ # # ][ # # ]: 0 : SetTextFormatted(m_sDefaultText);
878 : : }
879 : 0 : m_bValueDirty = sal_False;
880 : : }
881 : : }
882 : : else
883 : : {
884 : 0 : Commit();
885 : : }
886 : : }
887 : :
888 : 50 : return SpinField::Notify( rNEvt );
889 : : }
890 : :
891 : : //------------------------------------------------------------------------------
892 : 116 : void FormattedField::SetMinValue(double dMin)
893 : : {
894 : : DBG_CHKTHIS(FormattedField, NULL);
895 : : DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMinValue : only to be used in numeric mode !");
896 : :
897 : 116 : m_dMinValue = dMin;
898 : 116 : m_bHasMin = sal_True;
899 : : // fuer die Ueberpruefung des aktuellen Wertes an der neuen Grenze -> ImplSetValue
900 : 116 : ReFormat();
901 : 116 : }
902 : :
903 : : //------------------------------------------------------------------------------
904 : 116 : void FormattedField::SetMaxValue(double dMax)
905 : : {
906 : : DBG_CHKTHIS(FormattedField, NULL);
907 : : DBG_ASSERT(m_bTreatAsNumber, "FormattedField::SetMaxValue : only to be used in numeric mode !");
908 : :
909 : 116 : m_dMaxValue = dMax;
910 : 116 : m_bHasMax = sal_True;
911 : : // fuer die Ueberpruefung des aktuellen Wertes an der neuen Grenze -> ImplSetValue
912 : 116 : ReFormat();
913 : 116 : }
914 : :
915 : : //------------------------------------------------------------------------------
916 : 0 : void FormattedField::SetTextValue(const XubString& rText)
917 : : {
918 : : DBG_CHKTHIS(FormattedField, NULL);
919 : 0 : SetText(rText);
920 : 0 : ReFormat();
921 : 0 : }
922 : :
923 : : //------------------------------------------------------------------------------
924 : 2 : void FormattedField::EnableEmptyField(sal_Bool bEnable)
925 : : {
926 : : DBG_CHKTHIS(FormattedField, NULL);
927 [ + - ]: 2 : if (bEnable == m_bEnableEmptyField)
928 : 2 : return;
929 : :
930 : 0 : m_bEnableEmptyField = bEnable;
931 [ # # ][ # # ]: 0 : if (!m_bEnableEmptyField && GetText().Len()==0)
[ # # ][ # # ]
[ # # # # ]
932 : 0 : ImplSetValue(m_dCurrentValue, sal_True);
933 : : }
934 : :
935 : : //------------------------------------------------------------------------------
936 : 160 : void FormattedField::ImplSetValue(double dVal, sal_Bool bForce)
937 : : {
938 : : DBG_CHKTHIS(FormattedField, NULL);
939 : :
940 [ + + ][ - + ]: 160 : if (m_bHasMin && (dVal<m_dMinValue))
941 : 0 : dVal = m_dMinValue;
942 [ + + ][ + + ]: 160 : if (m_bHasMax && (dVal>m_dMaxValue))
943 : 12 : dVal = m_dMaxValue;
944 [ + + ][ + - ]: 160 : if (!bForce && (dVal == GetValue()))
[ + + ][ + + ]
945 : 160 : return;
946 : :
947 : : DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplSetValue : can't set a value without a formatter !");
948 : :
949 : 148 : m_bValueDirty = sal_False;
950 : 148 : m_dCurrentValue = dVal;
951 : :
952 [ + - ]: 148 : String sNewText;
953 [ + - ][ + - ]: 148 : if (ImplGetFormatter()->IsTextFormat(m_nFormatKey))
[ - + ]
954 : : {
955 : : // zuerst die Zahl als String im Standard-Format
956 [ # # ]: 0 : String sTemp;
957 [ # # ][ # # ]: 0 : ImplGetFormatter()->GetOutputString(dVal, 0, sTemp, &m_pLastOutputColor);
958 : : // dann den String entsprechend dem Text-Format
959 [ # # ][ # # ]: 0 : ImplGetFormatter()->GetOutputString(sTemp, m_nFormatKey, sNewText, &m_pLastOutputColor);
[ # # ]
960 : : }
961 : : else
962 : : {
963 [ + - ][ - + ]: 148 : if( IsUsingInputStringForFormatting())
964 [ # # ][ # # ]: 0 : ImplGetFormatter()->GetInputLineString(dVal, m_nFormatKey, sNewText);
965 : : else
966 [ + - ][ + - ]: 148 : ImplGetFormatter()->GetOutputString(dVal, m_nFormatKey, sNewText, &m_pLastOutputColor);
967 : : }
968 : :
969 [ + - ]: 148 : ImplSetTextImpl(sNewText, NULL);
970 : 148 : m_bValueDirty = sal_False;
971 [ + - ]: 160 : DBG_ASSERT(CheckText(sNewText), "FormattedField::ImplSetValue : formatted string doesn't match the criteria !");
972 : : }
973 : :
974 : : //------------------------------------------------------------------------------
975 : 582 : sal_Bool FormattedField::ImplGetValue(double& dNewVal)
976 : : {
977 : : DBG_CHKTHIS(FormattedField, NULL);
978 : :
979 : 582 : dNewVal = m_dCurrentValue;
980 [ + + ]: 582 : if (!m_bValueDirty)
981 : 438 : return sal_True;
982 : :
983 : 144 : dNewVal = m_dDefaultValue;
984 [ + - ]: 144 : String sText(GetText());
985 [ + + ]: 144 : if (!sText.Len())
986 : 10 : return sal_True;
987 : :
988 : : DBG_ASSERT(ImplGetFormatter() != NULL, "FormattedField::ImplGetValue : can't give you a current value without a formatter !");
989 : :
990 : 134 : sal_uInt32 nFormatKey = m_nFormatKey; // IsNumberFormat veraendert den FormatKey ...
991 : :
992 [ + - ][ + - ]: 134 : if (ImplGetFormatter()->IsTextFormat(nFormatKey) && m_bTreatAsNumber)
[ - + ][ # # ]
[ - + ]
993 : : // damit wir in einem als Text formatierten Feld trotzdem eine Eingabe wie '1,1' erkennen ...
994 : 0 : nFormatKey = 0;
995 : :
996 : : // Sonderbehandlung fuer %-Formatierung
997 [ + - ][ + - ]: 134 : if (ImplGetFormatter()->GetType(m_nFormatKey) == NUMBERFORMAT_PERCENT)
[ - + ]
998 : : {
999 : : // the language of our format
1000 [ # # ]: 0 : LanguageType eLanguage = m_pFormatter->GetEntry(m_nFormatKey)->GetLanguage();
1001 : : // the default number format for this language
1002 [ # # ]: 0 : sal_uLong nStandardNumericFormat = m_pFormatter->GetStandardFormat(NUMBERFORMAT_NUMBER, eLanguage);
1003 : :
1004 : 0 : sal_uInt32 nTempFormat = nStandardNumericFormat;
1005 : : double dTemp;
1006 [ # # ][ # # ]: 0 : if (m_pFormatter->IsNumberFormat(sText, nTempFormat, dTemp) &&
[ # # ][ # # ]
1007 [ # # ]: 0 : NUMBERFORMAT_NUMBER == m_pFormatter->GetType(nTempFormat))
1008 : : // der String entspricht einer Number-Formatierung, hat also nur kein %
1009 : : // -> append it
1010 [ # # ]: 0 : sText += '%';
1011 : : // (with this, a input of '3' becomes '3%', which then by the formatter is translated
1012 : : // into 0.03. Without this, the formatter would give us the double 3 for an input '3',
1013 : : // which equals 300 percent.
1014 : : }
1015 [ + - ][ + - ]: 134 : if (!ImplGetFormatter()->IsNumberFormat(sText, nFormatKey, dNewVal))
[ + + ]
1016 : 26 : return sal_False;
1017 : :
1018 : :
1019 [ + + ][ - + ]: 108 : if (m_bHasMin && (dNewVal<m_dMinValue))
1020 : 0 : dNewVal = m_dMinValue;
1021 [ + + ][ - + ]: 108 : if (m_bHasMax && (dNewVal>m_dMaxValue))
1022 : 0 : dNewVal = m_dMaxValue;
1023 [ + - ]: 582 : return sal_True;
1024 : : }
1025 : :
1026 : : //------------------------------------------------------------------------------
1027 : 66 : void FormattedField::SetValue(double dVal)
1028 : : {
1029 : : DBG_CHKTHIS(FormattedField, NULL);
1030 : 66 : ImplSetValue(dVal, m_bValueDirty);
1031 : 66 : }
1032 : :
1033 : : //------------------------------------------------------------------------------
1034 : 582 : double FormattedField::GetValue()
1035 : : {
1036 : : DBG_CHKTHIS(FormattedField, NULL);
1037 : :
1038 [ + + ]: 582 : if ( !ImplGetValue( m_dCurrentValue ) )
1039 : : {
1040 [ - + ]: 26 : if ( m_bEnableNaN )
1041 : 0 : ::rtl::math::setNan( &m_dCurrentValue );
1042 : : else
1043 : 26 : m_dCurrentValue = m_dDefaultValue;
1044 : : }
1045 : :
1046 : 582 : m_bValueDirty = sal_False;
1047 : 582 : return m_dCurrentValue;
1048 : : }
1049 : :
1050 : : //------------------------------------------------------------------------------
1051 : 20 : void FormattedField::Up()
1052 : : {
1053 : : DBG_CHKTHIS(FormattedField, NULL);
1054 : 20 : SetValue(GetValue() + m_dSpinSize);
1055 : : // das setValue handelt Bereichsueberschreitungen (min/max) automatisch
1056 : 20 : SetModifyFlag();
1057 : 20 : Modify();
1058 : :
1059 : 20 : SpinField::Up();
1060 : 20 : }
1061 : :
1062 : : //------------------------------------------------------------------------------
1063 : 10 : void FormattedField::Down()
1064 : : {
1065 : : DBG_CHKTHIS(FormattedField, NULL);
1066 : 10 : SetValue(GetValue() - m_dSpinSize);
1067 : 10 : SetModifyFlag();
1068 : 10 : Modify();
1069 : :
1070 : 10 : SpinField::Down();
1071 : 10 : }
1072 : :
1073 : : //------------------------------------------------------------------------------
1074 : 10 : void FormattedField::First()
1075 : : {
1076 : : DBG_CHKTHIS(FormattedField, NULL);
1077 [ + + ]: 10 : if (m_bHasMin)
1078 : : {
1079 : 8 : SetValue(m_dMinValue);
1080 : 8 : SetModifyFlag();
1081 : 8 : Modify();
1082 : : }
1083 : :
1084 : 10 : SpinField::First();
1085 : 10 : }
1086 : :
1087 : : //------------------------------------------------------------------------------
1088 : 10 : void FormattedField::Last()
1089 : : {
1090 : : DBG_CHKTHIS(FormattedField, NULL);
1091 [ + + ]: 10 : if (m_bHasMax)
1092 : : {
1093 : 8 : SetValue(m_dMaxValue);
1094 : 8 : SetModifyFlag();
1095 : 8 : Modify();
1096 : : }
1097 : :
1098 : 10 : SpinField::Last();
1099 : 10 : }
1100 : :
1101 : : //------------------------------------------------------------------------------
1102 : 0 : void FormattedField::UseInputStringForFormatting( bool bUseInputStr /* = true */ )
1103 : : {
1104 : 0 : m_bUseInputStringForFormatting = bUseInputStr;
1105 : 0 : }
1106 : :
1107 : : //------------------------------------------------------------------------------
1108 : 180 : bool FormattedField::IsUsingInputStringForFormatting() const
1109 : : {
1110 : 180 : return m_bUseInputStringForFormatting;
1111 : : }
1112 : :
1113 : :
1114 : : //==============================================================================
1115 : : //------------------------------------------------------------------------------
1116 : 34 : DoubleNumericField::~DoubleNumericField()
1117 : : {
1118 [ + - ]: 34 : delete m_pNumberValidator;
1119 [ - + ]: 68 : }
1120 : :
1121 : : //------------------------------------------------------------------------------
1122 : 114 : void DoubleNumericField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
1123 : : {
1124 : 114 : ResetConformanceTester();
1125 : 114 : FormattedField::FormatChanged(nWhat);
1126 : 114 : }
1127 : :
1128 : : //------------------------------------------------------------------------------
1129 : 56 : sal_Bool DoubleNumericField::CheckText(const XubString& sText) const
1130 : : {
1131 : : // We'd like to implement this using the NumberFormatter::IsNumberFormat, but unfortunately, this doesn't
1132 : : // recognize fragments of numbers (like, for instance "1e", which happens during entering e.g. "1e10")
1133 : : // Thus, the roundabout way via a regular expression
1134 : 56 : return m_pNumberValidator->isValidNumericFragment( sText );
1135 : : }
1136 : :
1137 : : //------------------------------------------------------------------------------
1138 : 148 : void DoubleNumericField::ResetConformanceTester()
1139 : : {
1140 : : // the thousands and the decimal separator are language dependent
1141 : 148 : const SvNumberformat* pFormatEntry = ImplGetFormatter()->GetEntry(m_nFormatKey);
1142 : :
1143 : 148 : sal_Unicode cSeparatorThousand = ',';
1144 : 148 : sal_Unicode cSeparatorDecimal = '.';
1145 [ + - ]: 148 : if (pFormatEntry)
1146 : : {
1147 : 148 : Locale aLocale;
1148 [ + - ]: 148 : MsLangId::convertLanguageToLocale( pFormatEntry->GetLanguage(), aLocale );
1149 [ + - ][ + - ]: 148 : LocaleDataWrapper aLocaleInfo(::comphelper::getProcessServiceFactory(), aLocale);
1150 : :
1151 [ + - ][ + - ]: 148 : String sSeparator = aLocaleInfo.getNumThousandSep();
1152 [ + - ]: 148 : if (sSeparator.Len())
1153 : 148 : cSeparatorThousand = sSeparator.GetBuffer()[0];
1154 : :
1155 [ + - ][ + - ]: 148 : sSeparator = aLocaleInfo.getNumDecimalSep();
1156 [ + - ]: 148 : if (sSeparator.Len())
1157 [ + - ][ + - ]: 148 : cSeparatorDecimal = sSeparator.GetBuffer()[0];
1158 : : }
1159 : :
1160 [ + + ]: 148 : delete m_pNumberValidator;
1161 [ + - ]: 148 : m_pNumberValidator = new validation::NumberValidator( cSeparatorThousand, cSeparatorDecimal );
1162 : 148 : }
1163 : :
1164 : :
1165 : : //==============================================================================
1166 : :
1167 : : //------------------------------------------------------------------------------
1168 : 34 : DoubleCurrencyField::DoubleCurrencyField(Window* pParent, WinBits nStyle)
1169 : : :FormattedField(pParent, nStyle)
1170 [ + - ]: 34 : ,m_bChangingFormat(sal_False)
1171 : : {
1172 : 34 : m_bPrependCurrSym = sal_False;
1173 : :
1174 : : // initialize with a system currency format
1175 [ + - ][ + - ]: 34 : m_sCurrencySymbol = SvtSysLocale().GetLocaleData().getCurrSymbol();
[ + - ][ + - ]
[ + - ]
1176 [ + - ]: 34 : UpdateCurrencyFormat();
1177 : 34 : }
1178 : :
1179 : : //------------------------------------------------------------------------------
1180 : 376 : void DoubleCurrencyField::FormatChanged(FORMAT_CHANGE_TYPE nWhat)
1181 : : {
1182 [ + + ]: 376 : if (m_bChangingFormat)
1183 : : {
1184 : 188 : FormattedField::FormatChanged(nWhat);
1185 : 376 : return;
1186 : : }
1187 : :
1188 [ + - + ]: 188 : switch (nWhat)
1189 : : {
1190 : : case FCT_FORMATTER:
1191 : : case FCT_PRECISION:
1192 : : case FCT_THOUSANDSSEP:
1193 : : // the aspects which changed don't take our currency settings into account (in fact, they most probably
1194 : : // destroyed them)
1195 : 114 : UpdateCurrencyFormat();
1196 : 114 : break;
1197 : : case FCT_KEYONLY:
1198 : : OSL_FAIL("DoubleCurrencyField::FormatChanged : somebody modified my key !");
1199 : : // We always build our own format from the settings we get via special methods (setCurrencySymbol etc.).
1200 : : // Nobody but ourself should modifiy the format key directly !
1201 : 0 : break;
1202 : : }
1203 : :
1204 : 188 : FormattedField::FormatChanged(nWhat);
1205 : : }
1206 : :
1207 : : //------------------------------------------------------------------------------
1208 : 50 : void DoubleCurrencyField::setCurrencySymbol(const String& _sSymbol)
1209 : : {
1210 [ + + ]: 50 : if (m_sCurrencySymbol == _sSymbol)
1211 : 50 : return;
1212 : :
1213 : 34 : m_sCurrencySymbol = _sSymbol;
1214 : 34 : UpdateCurrencyFormat();
1215 : 34 : FormatChanged(FCT_CURRENCY_SYMBOL);
1216 : : }
1217 : :
1218 : : //------------------------------------------------------------------------------
1219 : 51 : void DoubleCurrencyField::setPrependCurrSym(sal_Bool _bPrepend)
1220 : : {
1221 [ + + ]: 51 : if (m_bPrependCurrSym == _bPrepend)
1222 : 51 : return;
1223 : :
1224 : 40 : m_bPrependCurrSym = _bPrepend;
1225 : 40 : UpdateCurrencyFormat();
1226 : 40 : FormatChanged(FCT_CURRSYM_POSITION);
1227 : : }
1228 : :
1229 : : //------------------------------------------------------------------------------
1230 : 222 : void DoubleCurrencyField::UpdateCurrencyFormat()
1231 : : {
1232 : : // the old settings
1233 [ + - ]: 222 : XubString sOldFormat;
1234 : : LanguageType eLanguage;
1235 [ + - ]: 222 : GetFormat(sOldFormat, eLanguage);
1236 [ + - ]: 222 : sal_Bool bThSep = GetThousandsSep();
1237 [ + - ]: 222 : sal_uInt16 nDigits = GetDecimalDigits();
1238 : :
1239 : : // build a new format string with the base class' and my own settings
1240 : 222 : Locale aLocale;
1241 [ + - ]: 222 : MsLangId::convertLanguageToLocale( eLanguage, aLocale );
1242 [ + - ][ + - ]: 222 : LocaleDataWrapper aLocaleInfo(::comphelper::getProcessServiceFactory(), aLocale);
1243 : :
1244 [ + - ]: 222 : XubString sNewFormat;
1245 [ + + ]: 222 : if (bThSep)
1246 : : {
1247 [ + - ]: 39 : sNewFormat = '#';
1248 [ + - ][ + - ]: 39 : sNewFormat += aLocaleInfo.getNumThousandSep();
1249 [ + - ]: 39 : sNewFormat.AppendAscii("##0");
1250 : : }
1251 : : else
1252 [ + - ]: 183 : sNewFormat = '0';
1253 : :
1254 [ + + ]: 222 : if (nDigits)
1255 : : {
1256 [ + - ][ + - ]: 136 : sNewFormat += aLocaleInfo.getNumDecimalSep();
1257 : :
1258 [ + - ]: 136 : XubString sTemp;
1259 [ + - ]: 136 : sTemp.Fill(nDigits, '0');
1260 [ + - ][ + - ]: 136 : sNewFormat += sTemp;
1261 : : }
1262 : :
1263 [ + + ]: 222 : if (getPrependCurrSym())
1264 : : {
1265 [ + - ]: 60 : XubString sSymbol = getCurrencySymbol();
1266 [ + - ][ + - ]: 60 : sSymbol = comphelper::string::stripStart(sSymbol, ' ');
[ + - ]
1267 [ + - ][ + - ]: 60 : sSymbol = comphelper::string::stripEnd(sSymbol, ' ');
[ + - ]
1268 : :
1269 [ + - ]: 60 : XubString sTemp = rtl::OUString("[$");
1270 [ + - ]: 60 : sTemp += sSymbol;
1271 [ + - ]: 60 : sTemp.AppendAscii("] ");
1272 [ + - ]: 60 : sTemp += sNewFormat;
1273 : :
1274 : : // for negative values : $ -0.00, not -$ 0.00 ...
1275 : : // (the real solution would be a possibility to choose a "positive currency format" and a "negative currency format" ...
1276 : : // But not now ... (and hey, you could take a formatted field for this ....))
1277 : : // FS - 31.03.00 74642
1278 [ + - ]: 60 : sTemp.AppendAscii(";[$");
1279 [ + - ]: 60 : sTemp += sSymbol;
1280 [ + - ]: 60 : sTemp.AppendAscii("] -");
1281 [ + - ]: 60 : sTemp += sNewFormat;
1282 : :
1283 [ + - ][ + - ]: 60 : sNewFormat = sTemp;
[ + - ]
1284 : : }
1285 : : else
1286 : : {
1287 [ + - ]: 162 : XubString sTemp = getCurrencySymbol();
1288 [ + - ][ + - ]: 162 : sTemp = comphelper::string::stripStart(sTemp, ' ');
[ + - ]
1289 [ + - ][ + - ]: 162 : sTemp = comphelper::string::stripEnd(sTemp, ' ');
[ + - ]
1290 : :
1291 [ + - ]: 162 : sNewFormat += rtl::OUString(" [$");
1292 [ + - ]: 162 : sNewFormat += sTemp;
1293 [ + - ][ + - ]: 162 : sNewFormat += ']';
1294 : : }
1295 : :
1296 : : // set this new basic format
1297 : 222 : m_bChangingFormat = sal_True;
1298 [ + - ]: 222 : SetFormat(sNewFormat, eLanguage);
1299 [ + - ][ + - ]: 222 : m_bChangingFormat = sal_False;
[ + - ]
1300 : 222 : }
1301 : :
1302 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|