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 18 : ::osl::Mutex& getDefaultFormatsMutex()
49 : {
50 18 : static ::osl::Mutex s_aDefaultFormatsMutex;
51 18 : return s_aDefaultFormatsMutex;
52 : }
53 :
54 :
55 4 : Reference< XNumberFormatsSupplier >& lcl_getDefaultFormatsAccess_nothrow()
56 : {
57 4 : static Reference< XNumberFormatsSupplier > s_xDefaultFormats;
58 4 : return s_xDefaultFormats;
59 : }
60 :
61 :
62 4 : bool& lcl_getTriedCreation()
63 : {
64 : static bool s_bTriedCreation = false;
65 4 : 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 21 : void lcl_registerDefaultFormatsClient()
91 : {
92 21 : osl_atomic_increment( &s_refCount );
93 21 : }
94 :
95 :
96 18 : void lcl_revokeDefaultFormatsClient()
97 : {
98 18 : ::osl::ClearableMutexGuard aGuard( getDefaultFormatsMutex() );
99 18 : if ( 0 == osl_atomic_decrement( &s_refCount ) )
100 : {
101 4 : Reference< XNumberFormatsSupplier >& rDefaultFormats( lcl_getDefaultFormatsAccess_nothrow() );
102 4 : Reference< XNumberFormatsSupplier > xReleasePotentialLastReference( rDefaultFormats );
103 4 : rDefaultFormats.clear();
104 4 : lcl_getTriedCreation() = false;
105 :
106 4 : aGuard.clear();
107 4 : xReleasePotentialLastReference.clear();
108 18 : }
109 18 : }
110 : }
111 :
112 :
113 : // = UnoControlFormattedFieldModel
114 :
115 :
116 21 : UnoControlFormattedFieldModel::UnoControlFormattedFieldModel( const Reference< XComponentContext >& rxContext )
117 : :UnoControlModel( rxContext )
118 : ,m_bRevokedAsClient( false )
119 21 : ,m_bSettingValueAndText( false )
120 : {
121 21 : ImplRegisterProperty( BASEPROPERTY_ALIGN );
122 21 : ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
123 21 : ImplRegisterProperty( BASEPROPERTY_BORDER );
124 21 : ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
125 21 : ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
126 21 : ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_DEFAULT );
127 21 : ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_VALUE );
128 21 : ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_MAX );
129 21 : ImplRegisterProperty( BASEPROPERTY_EFFECTIVE_MIN );
130 21 : ImplRegisterProperty( BASEPROPERTY_ENABLED );
131 21 : ImplRegisterProperty( BASEPROPERTY_ENABLEVISIBLE );
132 21 : ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
133 21 : ImplRegisterProperty( BASEPROPERTY_FORMATKEY );
134 21 : ImplRegisterProperty( BASEPROPERTY_FORMATSSUPPLIER );
135 21 : ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
136 21 : ImplRegisterProperty( BASEPROPERTY_HELPURL );
137 21 : ImplRegisterProperty( BASEPROPERTY_MAXTEXTLEN );
138 21 : ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
139 21 : ImplRegisterProperty( BASEPROPERTY_REPEAT );
140 21 : ImplRegisterProperty( BASEPROPERTY_REPEAT_DELAY );
141 21 : ImplRegisterProperty( BASEPROPERTY_READONLY );
142 21 : ImplRegisterProperty( BASEPROPERTY_SPIN );
143 21 : ImplRegisterProperty( BASEPROPERTY_STRICTFORMAT );
144 21 : ImplRegisterProperty( BASEPROPERTY_TABSTOP );
145 21 : ImplRegisterProperty( BASEPROPERTY_TEXT );
146 21 : ImplRegisterProperty( BASEPROPERTY_TEXTCOLOR );
147 21 : ImplRegisterProperty( BASEPROPERTY_HIDEINACTIVESELECTION );
148 21 : ImplRegisterProperty( BASEPROPERTY_ENFORCE_FORMAT );
149 21 : ImplRegisterProperty( BASEPROPERTY_VERTICALALIGN );
150 21 : ImplRegisterProperty( BASEPROPERTY_WRITING_MODE );
151 21 : ImplRegisterProperty( BASEPROPERTY_CONTEXT_WRITING_MODE );
152 21 : ImplRegisterProperty( BASEPROPERTY_MOUSE_WHEEL_BEHAVIOUR );
153 :
154 21 : Any aTreatAsNumber;
155 21 : aTreatAsNumber <<= true;
156 21 : ImplRegisterProperty( BASEPROPERTY_TREATASNUMBER, aTreatAsNumber );
157 :
158 21 : lcl_registerDefaultFormatsClient();
159 21 : }
160 :
161 :
162 44 : UnoControlFormattedFieldModel::~UnoControlFormattedFieldModel()
163 : {
164 44 : }
165 :
166 :
167 1 : OUString UnoControlFormattedFieldModel::getServiceName() throw(RuntimeException, std::exception)
168 : {
169 1 : return OUString::createFromAscii( szServiceName_UnoControlFormattedFieldModel );
170 : }
171 :
172 :
173 329 : void SAL_CALL UnoControlFormattedFieldModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception, std::exception)
174 : {
175 329 : UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );
176 :
177 329 : switch ( nHandle )
178 : {
179 : case BASEPROPERTY_EFFECTIVE_VALUE:
180 8 : if ( !m_bSettingValueAndText )
181 5 : impl_updateTextFromValue_nothrow();
182 8 : break;
183 : case BASEPROPERTY_FORMATSSUPPLIER:
184 30 : impl_updateCachedFormatter_nothrow();
185 30 : impl_updateTextFromValue_nothrow();
186 30 : break;
187 : case BASEPROPERTY_FORMATKEY:
188 14 : impl_updateCachedFormatKey_nothrow();
189 14 : impl_updateTextFromValue_nothrow();
190 14 : break;
191 : }
192 329 : }
193 :
194 :
195 49 : void UnoControlFormattedFieldModel::impl_updateTextFromValue_nothrow()
196 : {
197 49 : if ( !m_xCachedFormatter.is() )
198 0 : impl_updateCachedFormatter_nothrow();
199 49 : if ( !m_xCachedFormatter.is() )
200 49 : return;
201 :
202 : try
203 : {
204 49 : Any aEffectiveValue;
205 49 : getFastPropertyValue( aEffectiveValue, BASEPROPERTY_EFFECTIVE_VALUE );
206 :
207 98 : OUString sStringValue;
208 49 : if ( !( aEffectiveValue >>= sStringValue ) )
209 : {
210 44 : double nDoubleValue(0);
211 44 : 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 98 : Reference< XPropertySet > xThis( *this, UNO_QUERY );
221 98 : xThis->setPropertyValue( GetPropertyName( BASEPROPERTY_TEXT ), makeAny( sStringValue ) );
222 : }
223 0 : catch( const Exception& )
224 : {
225 : DBG_UNHANDLED_EXCEPTION();
226 : }
227 : }
228 :
229 :
230 30 : void UnoControlFormattedFieldModel::impl_updateCachedFormatter_nothrow()
231 : {
232 30 : Any aFormatsSupplier;
233 30 : getFastPropertyValue( aFormatsSupplier, BASEPROPERTY_FORMATSSUPPLIER );
234 : try
235 : {
236 30 : Reference< XNumberFormatsSupplier > xSupplier( aFormatsSupplier, UNO_QUERY );
237 30 : if ( !xSupplier.is() )
238 0 : xSupplier = lcl_getDefaultFormats_throw();
239 :
240 30 : if ( !m_xCachedFormatter.is() )
241 : {
242 32 : m_xCachedFormatter = Reference< XNumberFormatter >(
243 : NumberFormatter::create(::comphelper::getProcessComponentContext()),
244 : UNO_QUERY_THROW
245 16 : );
246 : }
247 30 : m_xCachedFormatter->attachNumberFormatsSupplier( xSupplier );
248 : }
249 0 : catch( const Exception& )
250 : {
251 : DBG_UNHANDLED_EXCEPTION();
252 30 : }
253 30 : }
254 :
255 :
256 14 : void UnoControlFormattedFieldModel::impl_updateCachedFormatKey_nothrow()
257 : {
258 14 : Any aFormatKey;
259 14 : getFastPropertyValue( aFormatKey, BASEPROPERTY_FORMATKEY );
260 14 : m_aCachedFormat = aFormatKey;
261 14 : }
262 :
263 :
264 18 : void UnoControlFormattedFieldModel::dispose( ) throw(RuntimeException, std::exception)
265 : {
266 18 : UnoControlModel::dispose();
267 :
268 18 : ::osl::MutexGuard aGuard( GetMutex() );
269 18 : if ( !m_bRevokedAsClient )
270 : {
271 18 : lcl_revokeDefaultFormatsClient();
272 18 : m_bRevokedAsClient = true;
273 18 : }
274 18 : }
275 :
276 :
277 45 : void UnoControlFormattedFieldModel::ImplNormalizePropertySequence( const sal_Int32 _nCount, sal_Int32* _pHandles,
278 : Any* _pValues, sal_Int32* _pValidHandles ) const
279 : {
280 45 : ImplEnsureHandleOrder( _nCount, _pHandles, _pValues, BASEPROPERTY_EFFECTIVE_VALUE, BASEPROPERTY_TEXT );
281 :
282 45 : UnoControlModel::ImplNormalizePropertySequence( _nCount, _pHandles, _pValues, _pValidHandles );
283 45 : }
284 :
285 :
286 : namespace
287 : {
288 : class ResetFlagOnExit
289 : {
290 : private:
291 : bool& m_rFlag;
292 :
293 : public:
294 46 : explicit ResetFlagOnExit( bool& _rFlag )
295 46 : :m_rFlag( _rFlag )
296 : {
297 46 : }
298 46 : ~ResetFlagOnExit()
299 : {
300 46 : m_rFlag = false;
301 46 : }
302 : };
303 : }
304 :
305 :
306 46 : void SAL_CALL UnoControlFormattedFieldModel::setPropertyValues( const Sequence< OUString >& _rPropertyNames, const Sequence< Any >& _rValues ) throw(PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception)
307 : {
308 46 : bool bSettingValue = false;
309 46 : bool bSettingText = false;
310 3080 : for ( const OUString* pPropertyNames = _rPropertyNames.getConstArray();
311 1540 : pPropertyNames != _rPropertyNames.getConstArray() + _rPropertyNames.getLength();
312 : ++pPropertyNames
313 : )
314 : {
315 1494 : if ( BASEPROPERTY_EFFECTIVE_VALUE == GetPropertyId( *pPropertyNames ) )
316 6 : bSettingValue = true;
317 :
318 1494 : if ( BASEPROPERTY_TEXT == GetPropertyId( *pPropertyNames ) )
319 45 : bSettingText = true;
320 : }
321 :
322 46 : m_bSettingValueAndText = ( bSettingValue && bSettingText );
323 46 : ResetFlagOnExit aResetFlag( m_bSettingValueAndText );
324 46 : UnoControlModel::setPropertyValues( _rPropertyNames, _rValues );
325 46 : }
326 :
327 :
328 1181 : sal_Bool UnoControlFormattedFieldModel::convertFastPropertyValue(
329 : Any& rConvertedValue, Any& rOldValue, sal_Int32 nPropId,
330 : const Any& rValue ) throw (IllegalArgumentException)
331 : {
332 1181 : 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 1181 : return UnoControlModel::convertFastPropertyValue( rConvertedValue, rOldValue, nPropId, rValue );
374 : }
375 :
376 :
377 788 : Any UnoControlFormattedFieldModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
378 : {
379 788 : Any aReturn;
380 788 : switch (nPropId)
381 : {
382 22 : 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 130 : break;
394 :
395 636 : default : aReturn = UnoControlModel::ImplGetDefaultValue( nPropId ); break;
396 : }
397 :
398 788 : return aReturn;
399 : }
400 :
401 :
402 2233 : ::cppu::IPropertyArrayHelper& UnoControlFormattedFieldModel::getInfoHelper()
403 : {
404 : static UnoPropertyArrayHelper* pHelper = NULL;
405 2233 : if ( !pHelper )
406 : {
407 4 : Sequence<sal_Int32> aIDs = ImplGetPropertyIds();
408 4 : pHelper = new UnoPropertyArrayHelper( aIDs );
409 : }
410 2233 : return *pHelper;
411 : }
412 :
413 : // beans::XMultiPropertySet
414 :
415 93 : Reference< XPropertySetInfo > UnoControlFormattedFieldModel::getPropertySetInfo( ) throw(RuntimeException, std::exception)
416 : {
417 93 : static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
418 93 : return xInfo;
419 : }
420 :
421 5 : OUString UnoControlFormattedFieldModel::getImplementationName()
422 : throw (css::uno::RuntimeException, std::exception)
423 : {
424 5 : return OUString("stardiv.Toolkit.UnoControlFormattedFieldModel");
425 : }
426 :
427 : css::uno::Sequence<OUString>
428 6 : UnoControlFormattedFieldModel::getSupportedServiceNames()
429 : throw (css::uno::RuntimeException, std::exception)
430 : {
431 6 : auto s(UnoControlModel::getSupportedServiceNames());
432 6 : s.realloc(s.getLength() + 2);
433 6 : s[s.getLength() - 2] = "com.sun.star.awt.UnoControlFormattedFieldModel";
434 6 : s[s.getLength() - 1] = "stardiv.vcl.controlmodel.FormattedField";
435 6 : return s;
436 : }
437 :
438 : // = UnoFormattedFieldControl
439 :
440 :
441 3 : UnoFormattedFieldControl::UnoFormattedFieldControl()
442 3 : :UnoSpinFieldControl()
443 : {
444 3 : }
445 :
446 :
447 1 : OUString UnoFormattedFieldControl::GetComponentServiceName()
448 : {
449 1 : return OUString("FormattedField");
450 : }
451 :
452 :
453 6 : void UnoFormattedFieldControl::textChanged(const TextEvent& e) throw(RuntimeException, std::exception)
454 : {
455 6 : Reference< XVclWindowPeer > xPeer(getPeer(), UNO_QUERY);
456 : OSL_ENSURE(xPeer.is(), "UnoFormattedFieldControl::textChanged : what kind of peer do I have ?");
457 :
458 12 : Sequence< OUString > aNames( 2 );
459 6 : aNames[0] = GetPropertyName( BASEPROPERTY_EFFECTIVE_VALUE );
460 6 : aNames[1] = GetPropertyName( BASEPROPERTY_TEXT );
461 :
462 12 : Sequence< Any > aValues( 2 );
463 6 : aValues[0] = xPeer->getProperty( aNames[0] );
464 6 : aValues[1] = xPeer->getProperty( aNames[1] );
465 :
466 6 : ImplSetPropertyValues( aNames, aValues, false );
467 :
468 6 : if ( GetTextListeners().getLength() )
469 12 : GetTextListeners().textChanged( e );
470 6 : }
471 :
472 1 : OUString UnoFormattedFieldControl::getImplementationName()
473 : throw (css::uno::RuntimeException, std::exception)
474 : {
475 1 : return OUString("stardiv.Toolkit.UnoFormattedFieldControl");
476 : }
477 :
478 : css::uno::Sequence<OUString>
479 2 : UnoFormattedFieldControl::getSupportedServiceNames()
480 : throw (css::uno::RuntimeException, std::exception)
481 : {
482 2 : auto s(UnoEditControl::getSupportedServiceNames());
483 2 : s.realloc(s.getLength() + 2);
484 2 : s[s.getLength() - 2] = "com.sun.star.awt.UnoControlFormattedField";
485 2 : s[s.getLength() - 1] = "stardiv.vcl.control.FormattedField";
486 2 : return s;
487 : }
488 : } // namespace toolkit
489 :
490 :
491 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
492 20 : stardiv_Toolkit_UnoControlFormattedFieldModel_get_implementation(
493 : css::uno::XComponentContext *context,
494 : css::uno::Sequence<css::uno::Any> const &)
495 : {
496 20 : return cppu::acquire(new toolkit::UnoControlFormattedFieldModel(context));
497 : }
498 :
499 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
500 3 : stardiv_Toolkit_UnoFormattedFieldControl_get_implementation(
501 : css::uno::XComponentContext *,
502 : css::uno::Sequence<css::uno::Any> const &)
503 : {
504 3 : return cppu::acquire(new toolkit::UnoFormattedFieldControl());
505 : }
506 :
507 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|