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