Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <toolkit/controls/formattedcontrol.hxx>
21 : #include <toolkit/helper/property.hxx>
22 :
23 : #include <com/sun/star/awt/XVclWindowPeer.hpp>
24 : #include <com/sun/star/uno/XComponentContext.hpp>
25 : #include <com/sun/star/util/NumberFormatter.hpp>
26 : #include <com/sun/star/util/NumberFormatsSupplier.hpp>
27 :
28 : #include <tools/diagnose_ex.h>
29 : #include <comphelper/processfactory.hxx>
30 : #include <osl/diagnose.h>
31 :
32 : #include "helper/unopropertyarrayhelper.hxx"
33 :
34 : namespace toolkit
35 : {
36 :
37 :
38 : using namespace ::com::sun::star::uno;
39 : using namespace ::com::sun::star::awt;
40 : using namespace ::com::sun::star::lang;
41 : using namespace ::com::sun::star::beans;
42 : using namespace ::com::sun::star::util;
43 :
44 :
45 : namespace
46 : {
47 :
48 32 : ::osl::Mutex& getDefaultFormatsMutex()
49 : {
50 32 : static ::osl::Mutex s_aDefaultFormatsMutex;
51 32 : return s_aDefaultFormatsMutex;
52 : }
53 :
54 :
55 6 : Reference< XNumberFormatsSupplier >& lcl_getDefaultFormatsAccess_nothrow()
56 : {
57 6 : static Reference< XNumberFormatsSupplier > s_xDefaultFormats;
58 6 : return s_xDefaultFormats;
59 : }
60 :
61 :
62 6 : bool& lcl_getTriedCreation()
63 : {
64 : static bool s_bTriedCreation = false;
65 6 : return s_bTriedCreation;
66 : }
67 :
68 :
69 0 : const Reference< XNumberFormatsSupplier >& lcl_getDefaultFormats_throw()
70 : {
71 0 : ::osl::MutexGuard aGuard( getDefaultFormatsMutex() );
72 :
73 0 : bool& rbTriedCreation = lcl_getTriedCreation();
74 0 : Reference< XNumberFormatsSupplier >& rDefaultFormats( lcl_getDefaultFormatsAccess_nothrow() );
75 0 : if ( !rDefaultFormats.is() && !rbTriedCreation )
76 : {
77 0 : rbTriedCreation = true;
78 0 : rDefaultFormats = NumberFormatsSupplier::createWithDefaultLocale( ::comphelper::getProcessComponentContext() );
79 : }
80 0 : if ( !rDefaultFormats.is() )
81 0 : throw RuntimeException();
82 :
83 0 : return rDefaultFormats;
84 : }
85 :
86 :
87 : static oslInterlockedCount s_refCount(0);
88 :
89 :
90 38 : void lcl_registerDefaultFormatsClient()
91 : {
92 38 : osl_atomic_increment( &s_refCount );
93 38 : }
94 :
95 :
96 32 : void lcl_revokeDefaultFormatsClient()
97 : {
98 32 : ::osl::ClearableMutexGuard aGuard( getDefaultFormatsMutex() );
99 32 : if ( 0 == osl_atomic_decrement( &s_refCount ) )
100 : {
101 6 : Reference< XNumberFormatsSupplier >& rDefaultFormats( lcl_getDefaultFormatsAccess_nothrow() );
102 6 : Reference< XNumberFormatsSupplier > xReleasePotentialLastReference( rDefaultFormats );
103 6 : rDefaultFormats.clear();
104 6 : lcl_getTriedCreation() = false;
105 :
106 6 : aGuard.clear();
107 6 : xReleasePotentialLastReference.clear();
108 32 : }
109 32 : }
110 : }
111 :
112 :
113 : // = UnoControlFormattedFieldModel
114 :
115 :
116 38 : UnoControlFormattedFieldModel::UnoControlFormattedFieldModel( const Reference< XComponentContext >& rxContext )
117 : :UnoControlModel( rxContext )
118 : ,m_bRevokedAsClient( false )
119 38 : ,m_bSettingValueAndText( false )
120 : {
121 38 : ImplRegisterProperty( BASEPROPERTY_ALIGN );
122 38 : ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
123 38 : ImplRegisterProperty( BASEPROPERTY_BORDER );
124 38 : ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
125 38 : ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
126 38 : ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_DEFAULT );
127 38 : ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_VALUE );
128 38 : ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_MAX );
129 38 : ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_MIN );
130 38 : ImplRegisterProperty( BASEPROPERTY_ENABLED );
131 38 : ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
132 38 : ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
133 38 : ImplRegisterProperty( BASEPROPERTY_FORMATKEY );
134 38 : ImplRegisterProperty( BASEPROPERTY_FORMATSSUPPLIER );
135 38 : ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
136 38 : ImplRegisterProperty( BASEPROPERTY_HELPURL );
137 38 : ImplRegisterProperty( BASEPROPERTY_MAXTEXTLEN );
138 38 : ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
139 38 : ImplRegisterProperty( BASEPROPERTY_REPEAT );
140 38 : ImplRegisterProperty( BASEPROPERTY_REPEAT_DELAY );
141 38 : ImplRegisterProperty( BASEPROPERTY_READONLY );
142 38 : ImplRegisterProperty( BASEPROPERTY_SPIN );
143 38 : ImplRegisterProperty( BASEPROPERTY_STRICTFORMAT );
144 38 : ImplRegisterProperty( BASEPROPERTY_TABSTOP );
145 38 : ImplRegisterProperty( BASEPROPERTY_TEXT );
146 38 : ImplRegisterProperty( BASEPROPERTY_TEXTCOLOR );
147 38 : ImplRegisterProperty( BASEPROPERTY_HIDEINACTIVESELECTION );
148 38 : ImplRegisterProperty( BASEPROPERTY_ENFORCE_FORMAT );
149 38 : ImplRegisterProperty( BASEPROPERTY_VERTICALALIGN );
150 38 : ImplRegisterProperty( BASEPROPERTY_WRITING_MODE );
151 38 : ImplRegisterProperty( BASEPROPERTY_CONTEXT_WRITING_MODE );
152 38 : ImplRegisterProperty( BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR );
153 :
154 38 : Any aTreatAsNumber;
155 38 : aTreatAsNumber <<= true;
156 38 : ImplRegisterProperty( BASEPROPERTY_TREATASNUMBER, aTreatAsNumber );
157 :
158 38 : lcl_registerDefaultFormatsClient();
159 38 : }
160 :
161 :
162 80 : UnoControlFormattedFieldModel::~UnoControlFormattedFieldModel()
163 : {
164 80 : }
165 :
166 :
167 2 : OUString UnoControlFormattedFieldModel::getServiceName() throw(RuntimeException, std::exception)
168 : {
169 2 : return OUString::createFromAscii( szServiceName_UnoControlFormattedFieldModel );
170 : }
171 :
172 :
173 654 : void SAL_CALL UnoControlFormattedFieldModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception, std::exception)
174 : {
175 654 : UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );
176 :
177 654 : switch ( nHandle )
178 : {
179 : case BASEPROPERTY_EFFECTIVE_VALUE:
180 16 : if ( !m_bSettingValueAndText )
181 10 : impl_updateTextFromValue_nothrow();
182 16 : break;
183 : case BASEPROPERTY_FORMATSSUPPLIER:
184 58 : impl_updateCachedFormatter_nothrow();
185 58 : impl_updateTextFromValue_nothrow();
186 58 : break;
187 : case BASEPROPERTY_FORMATKEY:
188 28 : impl_updateCachedFormatKey_nothrow();
189 28 : impl_updateTextFromValue_nothrow();
190 28 : break;
191 : }
192 654 : }
193 :
194 :
195 96 : void UnoControlFormattedFieldModel::impl_updateTextFromValue_nothrow()
196 : {
197 96 : if ( !m_xCachedFormatter.is() )
198 0 : impl_updateCachedFormatter_nothrow();
199 96 : if ( !m_xCachedFormatter.is() )
200 96 : return;
201 :
202 : try
203 : {
204 96 : Any aEffectiveValue;
205 96 : getFastPropertyValue( aEffectiveValue, BASEPROPERTY_EFFECTIVE_VALUE );
206 :
207 192 : OUString sStringValue;
208 96 : if ( !( aEffectiveValue >>= sStringValue ) )
209 : {
210 86 : double nDoubleValue(0);
211 86 : if ( aEffectiveValue >>= nDoubleValue )
212 : {
213 0 : sal_Int32 nFormatKey( 0 );
214 0 : if ( m_aCachedFormat.hasValue() )
215 0 : m_aCachedFormat >>= nFormatKey;
216 0 : sStringValue = m_xCachedFormatter->convertNumberToString( nFormatKey, nDoubleValue );
217 : }
218 : }
219 :
220 192 : Reference< XPropertySet > xThis( *this, UNO_QUERY );
221 192 : xThis->setPropertyValue( GetPropertyName( BASEPROPERTY_TEXT ), makeAny( sStringValue ) );
222 : }
223 0 : catch( const Exception& )
224 : {
225 : DBG_UNHANDLED_EXCEPTION();
226 : }
227 : }
228 :
229 :
230 58 : void UnoControlFormattedFieldModel::impl_updateCachedFormatter_nothrow()
231 : {
232 58 : Any aFormatsSupplier;
233 58 : getFastPropertyValue( aFormatsSupplier, BASEPROPERTY_FORMATSSUPPLIER );
234 : try
235 : {
236 58 : Reference< XNumberFormatsSupplier > xSupplier( aFormatsSupplier, UNO_QUERY );
237 58 : if ( !xSupplier.is() )
238 0 : xSupplier = lcl_getDefaultFormats_throw();
239 :
240 58 : if ( !m_xCachedFormatter.is() )
241 : {
242 60 : m_xCachedFormatter = Reference< XNumberFormatter >(
243 : NumberFormatter::create(::comphelper::getProcessComponentContext()),
244 : UNO_QUERY_THROW
245 30 : );
246 : }
247 58 : m_xCachedFormatter->attachNumberFormatsSupplier( xSupplier );
248 : }
249 0 : catch( const Exception& )
250 : {
251 : DBG_UNHANDLED_EXCEPTION();
252 58 : }
253 58 : }
254 :
255 :
256 28 : void UnoControlFormattedFieldModel::impl_updateCachedFormatKey_nothrow()
257 : {
258 28 : Any aFormatKey;
259 28 : getFastPropertyValue( aFormatKey, BASEPROPERTY_FORMATKEY );
260 28 : m_aCachedFormat = aFormatKey;
261 28 : }
262 :
263 :
264 32 : void UnoControlFormattedFieldModel::dispose( ) throw(RuntimeException, std::exception)
265 : {
266 32 : UnoControlModel::dispose();
267 :
268 32 : ::osl::MutexGuard aGuard( GetMutex() );
269 32 : if ( !m_bRevokedAsClient )
270 : {
271 32 : lcl_revokeDefaultFormatsClient();
272 32 : m_bRevokedAsClient = true;
273 32 : }
274 32 : }
275 :
276 :
277 90 : void UnoControlFormattedFieldModel::ImplNormalizePropertySequence( const sal_Int32 _nCount, sal_Int32* _pHandles,
278 : Any* _pValues, sal_Int32* _pValidHandles ) const
279 : {
280 90 : ImplEnsureHandleOrder( _nCount, _pHandles, _pValues, BASEPROPERTY_EFFECTIVE_VALUE, BASEPROPERTY_TEXT );
281 :
282 90 : UnoControlModel::ImplNormalizePropertySequence( _nCount, _pHandles, _pValues, _pValidHandles );
283 90 : }
284 :
285 :
286 : namespace
287 : {
288 : class ResetFlagOnExit
289 : {
290 : private:
291 : bool& m_rFlag;
292 :
293 : public:
294 92 : ResetFlagOnExit( bool& _rFlag )
295 92 : :m_rFlag( _rFlag )
296 : {
297 92 : }
298 92 : ~ResetFlagOnExit()
299 : {
300 92 : m_rFlag = false;
301 92 : }
302 : };
303 : }
304 :
305 :
306 92 : void SAL_CALL UnoControlFormattedFieldModel::setPropertyValues( const Sequence< OUString >& _rPropertyNames, const Sequence< Any >& _rValues ) throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception)
307 : {
308 92 : bool bSettingValue = false;
309 92 : bool bSettingText = false;
310 6160 : for ( const OUString* pPropertyNames = _rPropertyNames.getConstArray();
311 3080 : pPropertyNames != _rPropertyNames.getConstArray() + _rPropertyNames.getLength();
312 : ++pPropertyNames
313 : )
314 : {
315 2988 : if ( BASEPROPERTY_EFFECTIVE_VALUE == GetPropertyId( *pPropertyNames ) )
316 12 : bSettingValue = true;
317 :
318 2988 : if ( BASEPROPERTY_TEXT == GetPropertyId( *pPropertyNames ) )
319 90 : bSettingText = true;
320 : }
321 :
322 92 : m_bSettingValueAndText = ( bSettingValue && bSettingText );
323 92 : ResetFlagOnExit aResetFlag( m_bSettingValueAndText );
324 92 : UnoControlModel::setPropertyValues( _rPropertyNames, _rValues );
325 92 : }
326 :
327 :
328 2356 : sal_Bool UnoControlFormattedFieldModel::convertFastPropertyValue(
329 : Any& rConvertedValue, Any& rOldValue, sal_Int32 nPropId,
330 : const Any& rValue ) throw (IllegalArgumentException)
331 : {
332 2356 : if ( BASEPROPERTY_EFFECTIVE_DEFAULT == nPropId && rValue.hasValue() )
333 : {
334 0 : double dVal = 0;
335 0 : OUString sVal;
336 0 : bool bStreamed = (rValue >>= dVal);
337 0 : if ( bStreamed )
338 : {
339 0 : rConvertedValue <<= dVal;
340 : }
341 : else
342 : {
343 0 : sal_Int32 nVal = 0;
344 0 : bStreamed = (rValue >>= nVal);
345 0 : if ( bStreamed )
346 : {
347 0 : rConvertedValue <<= static_cast<double>(nVal);
348 : }
349 : else
350 : {
351 0 : bStreamed = (rValue >>= sVal);
352 0 : if ( bStreamed )
353 : {
354 0 : rConvertedValue <<= sVal;
355 : }
356 : }
357 : }
358 :
359 0 : if ( bStreamed )
360 : {
361 0 : getFastPropertyValue( rOldValue, nPropId );
362 0 : return !CompareProperties( rConvertedValue, rOldValue );
363 : }
364 :
365 : throw IllegalArgumentException(
366 : ( OUString("Unable to convert the given value for the property ")
367 0 : += GetPropertyName((sal_uInt16)nPropId) )
368 0 : += " (double, integer, or string expected).",
369 : static_cast< XPropertySet* >(this),
370 0 : 1);
371 : }
372 :
373 2356 : return UnoControlModel::convertFastPropertyValue( rConvertedValue, rOldValue, nPropId, rValue );
374 : }
375 :
376 :
377 1432 : Any UnoControlFormattedFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
378 : {
379 1432 : Any aReturn;
380 1432 : switch (nPropId)
381 : {
382 40 : case BASEPROPERTY_DEFAULTCONTROL: aReturn <<= OUString( OUString::createFromAscii( szServiceName_UnoControlFormattedField ) ); break;
383 :
384 0 : case BASEPROPERTY_TREATASNUMBER: aReturn <<= true; break;
385 :
386 : case BASEPROPERTY_EFFECTIVE_DEFAULT:
387 : case BASEPROPERTY_EFFECTIVE_VALUE:
388 : case BASEPROPERTY_EFFECTIVE_MAX:
389 : case BASEPROPERTY_EFFECTIVE_MIN:
390 : case BASEPROPERTY_FORMATKEY:
391 : case BASEPROPERTY_FORMATSSUPPLIER:
392 : // (void)
393 236 : break;
394 :
395 1156 : default : aReturn = UnoControlModel::ImplGetDefaultValue( nPropId ); break;
396 : }
397 :
398 1432 : return aReturn;
399 : }
400 :
401 :
402 4416 : ::cppu::IPropertyArrayHelper& UnoControlFormattedFieldModel::getInfoHelper()
403 : {
404 : static UnoPropertyArrayHelper* pHelper = NULL;
405 4416 : if ( !pHelper )
406 : {
407 6 : Sequence<sal_Int32> aIDs = ImplGetPropertyIds();
408 6 : pHelper = new UnoPropertyArrayHelper( aIDs );
409 : }
410 4416 : return *pHelper;
411 : }
412 :
413 : // beans::XMultiPropertySet
414 :
415 182 : Reference< XPropertySetInfo > UnoControlFormattedFieldModel::getPropertySetInfo( ) throw(RuntimeException, std::exception)
416 : {
417 182 : static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
418 182 : return xInfo;
419 : }
420 :
421 :
422 : // = UnoFormattedFieldControl
423 :
424 :
425 2 : UnoFormattedFieldControl::UnoFormattedFieldControl()
426 2 : :UnoSpinFieldControl()
427 : {
428 2 : }
429 :
430 :
431 2 : OUString UnoFormattedFieldControl::GetComponentServiceName()
432 : {
433 2 : return OUString("FormattedField");
434 : }
435 :
436 :
437 12 : void UnoFormattedFieldControl::textChanged(const TextEvent& e) throw(RuntimeException, std::exception)
438 : {
439 12 : Reference< XVclWindowPeer > xPeer(getPeer(), UNO_QUERY);
440 : OSL_ENSURE(xPeer.is(), "UnoFormattedFieldControl::textChanged : what kind of peer do I have ?");
441 :
442 24 : Sequence< OUString > aNames( 2 );
443 12 : aNames[0] = GetPropertyName( BASEPROPERTY_EFFECTIVE_VALUE );
444 12 : aNames[1] = GetPropertyName( BASEPROPERTY_TEXT );
445 :
446 24 : Sequence< Any > aValues( 2 );
447 12 : aValues[0] = xPeer->getProperty( aNames[0] );
448 12 : aValues[1] = xPeer->getProperty( aNames[1] );
449 :
450 12 : ImplSetPropertyValues( aNames, aValues, false );
451 :
452 12 : if ( GetTextListeners().getLength() )
453 24 : GetTextListeners().textChanged( e );
454 12 : }
455 :
456 :
457 : } // namespace toolkit
458 :
459 :
460 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
461 36 : stardiv_Toolkit_UnoControlFormattedFieldModel_get_implementation(
462 : css::uno::XComponentContext *context,
463 : css::uno::Sequence<css::uno::Any> const &)
464 : {
465 36 : return cppu::acquire(new toolkit::UnoControlFormattedFieldModel(context));
466 : }
467 :
468 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
469 2 : stardiv_Toolkit_UnoFormattedFieldControl_get_implementation(
470 : css::uno::XComponentContext *,
471 : css::uno::Sequence<css::uno::Any> const &)
472 : {
473 2 : return cppu::acquire(new toolkit::UnoFormattedFieldControl());
474 1227 : }
475 :
476 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|