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