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