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_extensions.hxx"
30 #include "xsdvalidationpropertyhandler.hxx"
31 #include "formstrings.hxx"
32 #include "formmetadata.hxx"
33 #include "xsddatatypes.hxx"
34 #include "modulepcr.hxx"
35 #include "formresid.hrc"
36 #include "formlocalid.hrc"
37 #include "propctrlr.hrc"
38 #include "newdatatype.hxx"
39 #include "xsdvalidationhelper.hxx"
40 #include "pcrcommon.hxx"
41 #include "handlerhelper.hxx"
42 
43 /** === begin UNO includes === **/
44 #include <com/sun/star/beans/PropertyAttribute.hpp>
45 #include <com/sun/star/xsd/WhiteSpaceTreatment.hpp>
46 #include <com/sun/star/xsd/DataTypeClass.hpp>
47 #include <com/sun/star/inspection/PropertyControlType.hpp>
48 #include <com/sun/star/beans/Optional.hpp>
49 #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
50 #include <com/sun/star/inspection/PropertyLineElement.hpp>
51 /** === end UNO includes === **/
52 #include <vcl/msgbox.hxx>
53 #include <tools/debug.hxx>
54 #include <svtools/localresaccess.hxx>
55 
56 #include <algorithm>
57 #include <functional>
58 #include <limits>
59 
60 //------------------------------------------------------------------------
61 extern "C" void SAL_CALL createRegistryInfo_XSDValidationPropertyHandler()
62 {
63     ::pcr::XSDValidationPropertyHandler::registerImplementation();
64 }
65 
66 //........................................................................
67 namespace pcr
68 {
69 //........................................................................
70 
71     using namespace ::com::sun::star;
72     using namespace ::com::sun::star::uno;
73     using namespace ::com::sun::star::lang;
74     using namespace ::com::sun::star::beans;
75     using namespace ::com::sun::star::xforms;
76     using namespace ::com::sun::star::xsd;
77     using namespace ::com::sun::star::script;
78     using namespace ::com::sun::star::inspection;
79 
80     using ::com::sun::star::beans::PropertyAttribute::MAYBEVOID;
81 
82     //====================================================================
83 	//= XSDValidationPropertyHandler
84 	//====================================================================
85     DBG_NAME( XSDValidationPropertyHandler )
86 	//--------------------------------------------------------------------
87     XSDValidationPropertyHandler::XSDValidationPropertyHandler( const Reference< XComponentContext >& _rxContext )
88         :XSDValidationPropertyHandler_Base( _rxContext )
89     {
90         DBG_CTOR( XSDValidationPropertyHandler, NULL );
91     }
92 
93 	//--------------------------------------------------------------------
94     XSDValidationPropertyHandler::~XSDValidationPropertyHandler()
95     {
96         DBG_DTOR( XSDValidationPropertyHandler, NULL );
97     }
98 
99     //--------------------------------------------------------------------
100     ::rtl::OUString SAL_CALL XSDValidationPropertyHandler::getImplementationName_static(  ) throw (RuntimeException)
101     {
102         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.XSDValidationPropertyHandler" ) );
103     }
104 
105     //--------------------------------------------------------------------
106     Sequence< ::rtl::OUString > SAL_CALL XSDValidationPropertyHandler::getSupportedServiceNames_static(  ) throw (RuntimeException)
107     {
108         Sequence< ::rtl::OUString > aSupported( 1 );
109         aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.inspection.XSDValidationPropertyHandler" ) );
110         return aSupported;
111     }
112 
113     //--------------------------------------------------------------------
114     Any SAL_CALL XSDValidationPropertyHandler::getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (UnknownPropertyException, RuntimeException)
115     {
116         ::osl::MutexGuard aGuard( m_aMutex );
117         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
118 
119         OSL_ENSURE( m_pHelper.get(), "XSDValidationPropertyHandler::getPropertyValue: inconsistency!" );
120             // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
121 
122         Any aReturn;
123         ::rtl::Reference< XSDDataType > pType = m_pHelper->getValidatingDataType();
124         switch ( nPropId )
125         {
126         // common facets
127         case PROPERTY_ID_XSD_DATA_TYPE:  aReturn = pType.is() ? pType->getFacet( PROPERTY_NAME ) : makeAny( ::rtl::OUString() ); break;
128         case PROPERTY_ID_XSD_WHITESPACES:aReturn = pType.is() ? pType->getFacet( PROPERTY_XSD_WHITESPACES ) : makeAny( WhiteSpaceTreatment::Preserve ); break;
129         case PROPERTY_ID_XSD_PATTERN:    aReturn = pType.is() ? pType->getFacet( PROPERTY_XSD_PATTERN ) : makeAny( ::rtl::OUString() ); break;
130 
131         // all other properties are simply forwarded, if they exist at the given type
132         default:
133         {
134             if ( pType.is() && pType->hasFacet( _rPropertyName ) )
135                 aReturn = pType->getFacet( _rPropertyName );
136         }
137         break;
138         }
139 
140         return aReturn;
141     }
142 
143     //--------------------------------------------------------------------
144     void SAL_CALL XSDValidationPropertyHandler::setPropertyValue( const ::rtl::OUString& _rPropertyName, const Any& _rValue ) throw (UnknownPropertyException, RuntimeException)
145     {
146         ::osl::MutexGuard aGuard( m_aMutex );
147         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
148 
149         OSL_ENSURE( m_pHelper.get(), "XSDValidationPropertyHandler::getPropertyValue: inconsistency!" );
150             // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
151 
152         if ( PROPERTY_ID_XSD_DATA_TYPE == nPropId )
153         {
154             ::rtl::OUString sTypeName;
155             OSL_VERIFY( _rValue >>= sTypeName );
156             m_pHelper->setValidatingDataTypeByName( sTypeName );
157             impl_setContextDocumentModified_nothrow();
158             return;
159         }
160 
161         ::rtl::Reference< XSDDataType > pType = m_pHelper->getValidatingDataType();
162         if ( !pType.is() )
163         {
164             DBG_ERROR( "XSDValidationPropertyHandler::setPropertyValue: you're trying to set a type facet, without a current type!" );
165             return;
166         }
167 
168         pType->setFacet( _rPropertyName, _rValue );
169         impl_setContextDocumentModified_nothrow();
170     }
171 
172     //--------------------------------------------------------------------
173     void XSDValidationPropertyHandler::onNewComponent()
174     {
175         XSDValidationPropertyHandler_Base::onNewComponent();
176 
177         Reference< frame::XModel > xDocument( impl_getContextDocument_nothrow() );
178         DBG_ASSERT( xDocument.is(), "XSDValidationPropertyHandler::onNewComponent: no document!" );
179         if ( EFormsHelper::isEForm( xDocument ) )
180             m_pHelper.reset( new XSDValidationHelper( m_aMutex, m_xComponent, xDocument ) );
181         else
182             m_pHelper.reset( NULL );
183     }
184 
185     //--------------------------------------------------------------------
186     Sequence< Property > XSDValidationPropertyHandler::doDescribeSupportedProperties() const
187     {
188         ::std::vector< Property > aProperties;
189 
190         if ( m_pHelper.get() )
191         {
192             bool bAllowBinding = m_pHelper->canBindToAnyDataType();
193 
194             if ( bAllowBinding )
195             {
196                 aProperties.reserve( 12 );
197 
198                 addStringPropertyDescription( aProperties, PROPERTY_XSD_DATA_TYPE   );
199                 addInt16PropertyDescription ( aProperties, PROPERTY_XSD_WHITESPACES );
200                 addStringPropertyDescription( aProperties, PROPERTY_XSD_PATTERN     );
201 
202                 // string facets
203                 addInt32PropertyDescription( aProperties, PROPERTY_XSD_LENGTH,          MAYBEVOID );
204                 addInt32PropertyDescription( aProperties, PROPERTY_XSD_MIN_LENGTH,      MAYBEVOID );
205                 addInt32PropertyDescription( aProperties, PROPERTY_XSD_MAX_LENGTH,      MAYBEVOID );
206 
207                 // decimal facets
208                 addInt32PropertyDescription( aProperties, PROPERTY_XSD_TOTAL_DIGITS,    MAYBEVOID );
209                 addInt32PropertyDescription( aProperties, PROPERTY_XSD_FRACTION_DIGITS, MAYBEVOID );
210 
211                 // facets for different types
212                 addInt16PropertyDescription( aProperties, PROPERTY_XSD_MAX_INCLUSIVE_INT, MAYBEVOID );
213                 addInt16PropertyDescription( aProperties, PROPERTY_XSD_MAX_EXCLUSIVE_INT, MAYBEVOID );
214                 addInt16PropertyDescription( aProperties, PROPERTY_XSD_MIN_INCLUSIVE_INT, MAYBEVOID );
215                 addInt16PropertyDescription( aProperties, PROPERTY_XSD_MIN_EXCLUSIVE_INT, MAYBEVOID );
216                 addDoublePropertyDescription( aProperties, PROPERTY_XSD_MAX_INCLUSIVE_DOUBLE, MAYBEVOID );
217                 addDoublePropertyDescription( aProperties, PROPERTY_XSD_MAX_EXCLUSIVE_DOUBLE, MAYBEVOID );
218                 addDoublePropertyDescription( aProperties, PROPERTY_XSD_MIN_INCLUSIVE_DOUBLE, MAYBEVOID );
219                 addDoublePropertyDescription( aProperties, PROPERTY_XSD_MIN_EXCLUSIVE_DOUBLE, MAYBEVOID );
220                 addDatePropertyDescription( aProperties, PROPERTY_XSD_MAX_INCLUSIVE_DATE, MAYBEVOID );
221                 addDatePropertyDescription( aProperties, PROPERTY_XSD_MAX_EXCLUSIVE_DATE, MAYBEVOID );
222                 addDatePropertyDescription( aProperties, PROPERTY_XSD_MIN_INCLUSIVE_DATE, MAYBEVOID );
223                 addDatePropertyDescription( aProperties, PROPERTY_XSD_MIN_EXCLUSIVE_DATE, MAYBEVOID );
224                 addTimePropertyDescription( aProperties, PROPERTY_XSD_MAX_INCLUSIVE_TIME, MAYBEVOID );
225                 addTimePropertyDescription( aProperties, PROPERTY_XSD_MAX_EXCLUSIVE_TIME, MAYBEVOID );
226                 addTimePropertyDescription( aProperties, PROPERTY_XSD_MIN_INCLUSIVE_TIME, MAYBEVOID );
227                 addTimePropertyDescription( aProperties, PROPERTY_XSD_MIN_EXCLUSIVE_TIME, MAYBEVOID );
228                 addDateTimePropertyDescription( aProperties, PROPERTY_XSD_MAX_INCLUSIVE_DATE_TIME, MAYBEVOID );
229                 addDateTimePropertyDescription( aProperties, PROPERTY_XSD_MAX_EXCLUSIVE_DATE_TIME, MAYBEVOID );
230                 addDateTimePropertyDescription( aProperties, PROPERTY_XSD_MIN_INCLUSIVE_DATE_TIME, MAYBEVOID );
231                 addDateTimePropertyDescription( aProperties, PROPERTY_XSD_MIN_EXCLUSIVE_DATE_TIME, MAYBEVOID );
232             }
233         }
234 
235         if ( aProperties.empty() )
236             return Sequence< Property >();
237         return Sequence< Property >( &(*aProperties.begin()), aProperties.size() );
238     }
239 
240     //--------------------------------------------------------------------
241     Sequence< ::rtl::OUString > SAL_CALL XSDValidationPropertyHandler::getSupersededProperties( ) throw (RuntimeException)
242     {
243         ::osl::MutexGuard aGuard( m_aMutex );
244 
245         ::std::vector< ::rtl::OUString > aSuperfluous;
246         if ( m_pHelper.get() )
247         {
248             aSuperfluous.push_back( PROPERTY_CONTROLSOURCE );
249             aSuperfluous.push_back( PROPERTY_EMPTY_IS_NULL );
250             aSuperfluous.push_back( PROPERTY_FILTERPROPOSAL );
251             aSuperfluous.push_back( PROPERTY_LISTSOURCETYPE );
252             aSuperfluous.push_back( PROPERTY_LISTSOURCE );
253             aSuperfluous.push_back( PROPERTY_BOUNDCOLUMN );
254 
255             bool bAllowBinding = m_pHelper->canBindToAnyDataType();
256 
257             if ( bAllowBinding )
258             {
259                 aSuperfluous.push_back( PROPERTY_MAXTEXTLEN );
260                 aSuperfluous.push_back( PROPERTY_VALUEMIN );
261                 aSuperfluous.push_back( PROPERTY_VALUEMAX );
262                 aSuperfluous.push_back( PROPERTY_DECIMAL_ACCURACY );
263                 aSuperfluous.push_back( PROPERTY_TIMEMIN );
264                 aSuperfluous.push_back( PROPERTY_TIMEMAX );
265                 aSuperfluous.push_back( PROPERTY_DATEMIN );
266                 aSuperfluous.push_back( PROPERTY_DATEMAX );
267                 aSuperfluous.push_back( PROPERTY_EFFECTIVE_MIN );
268                 aSuperfluous.push_back( PROPERTY_EFFECTIVE_MAX );
269             }
270         }
271 
272         if ( aSuperfluous.empty() )
273             return Sequence< ::rtl::OUString >();
274         return Sequence< ::rtl::OUString >( &(*aSuperfluous.begin()), aSuperfluous.size() );
275     }
276 
277     //--------------------------------------------------------------------
278     Sequence< ::rtl::OUString > SAL_CALL XSDValidationPropertyHandler::getActuatingProperties( ) throw (RuntimeException)
279     {
280         ::osl::MutexGuard aGuard( m_aMutex );
281         ::std::vector< ::rtl::OUString > aInterestedInActuations( 2 );
282         if ( m_pHelper.get() )
283         {
284             aInterestedInActuations.push_back( PROPERTY_XSD_DATA_TYPE );
285             aInterestedInActuations.push_back( PROPERTY_XML_DATA_MODEL );
286         }
287         if ( aInterestedInActuations.empty() )
288             return Sequence< ::rtl::OUString >();
289         return Sequence< ::rtl::OUString >( &(*aInterestedInActuations.begin()), aInterestedInActuations.size() );
290     }
291 
292     //--------------------------------------------------------------------
293     namespace
294     {
295         void showPropertyUI( const Reference< XObjectInspectorUI >& _rxInspectorUI, const ::rtl::OUString& _rPropertyName, bool _bShow )
296         {
297             if ( _bShow )
298                 _rxInspectorUI->showPropertyUI( _rPropertyName );
299             else
300                 _rxInspectorUI->hidePropertyUI( _rPropertyName );
301         }
302     }
303 
304     //--------------------------------------------------------------------
305     LineDescriptor SAL_CALL XSDValidationPropertyHandler::describePropertyLine( const ::rtl::OUString& _rPropertyName,
306         const Reference< XPropertyControlFactory >& _rxControlFactory )
307         throw (UnknownPropertyException, NullPointerException, RuntimeException)
308     {
309         ::osl::MutexGuard aGuard( m_aMutex );
310         if ( !_rxControlFactory.is() )
311             throw NullPointerException();
312         if ( !m_pHelper.get() )
313             throw RuntimeException();
314 
315         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
316 
317         LineDescriptor aDescriptor;
318         if ( nPropId != PROPERTY_ID_XSD_DATA_TYPE )
319             aDescriptor.IndentLevel = 1;
320 
321         // collect some information about the to-be-created control
322         sal_Int16 nControlType = PropertyControlType::TextField;
323         ::std::vector< ::rtl::OUString > aListEntries;
324         Optional< double > aMinValue( sal_False, 0 );
325         Optional< double > aMaxValue( sal_False, 0 );
326 
327         switch ( nPropId )
328         {
329         case PROPERTY_ID_XSD_DATA_TYPE:
330             nControlType = PropertyControlType::ListBox;
331 
332             implGetAvailableDataTypeNames( aListEntries );
333 
334             aDescriptor.PrimaryButtonId = rtl::OUString::createFromAscii(UID_PROP_ADD_DATA_TYPE);
335             aDescriptor.SecondaryButtonId = rtl::OUString::createFromAscii(UID_PROP_REMOVE_DATA_TYPE);;
336             aDescriptor.HasPrimaryButton = aDescriptor.HasSecondaryButton = sal_True;
337             aDescriptor.PrimaryButtonImageURL = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:graphicrepository/extensions/res/buttonplus.png" ) );
338             aDescriptor.SecondaryButtonImageURL = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:graphicrepository/extensions/res/buttonminus.png" ) );
339             break;
340 
341         case PROPERTY_ID_XSD_WHITESPACES:
342         {
343             nControlType = PropertyControlType::ListBox;
344             aListEntries = m_pInfoService->getPropertyEnumRepresentations( PROPERTY_ID_XSD_WHITESPACES );
345         }
346         break;
347 
348         case PROPERTY_ID_XSD_PATTERN:
349             nControlType = PropertyControlType::TextField;
350             break;
351 
352         case PROPERTY_ID_XSD_LENGTH:
353         case PROPERTY_ID_XSD_MIN_LENGTH:
354         case PROPERTY_ID_XSD_MAX_LENGTH:
355             nControlType = PropertyControlType::NumericField;
356             break;
357 
358         case PROPERTY_ID_XSD_TOTAL_DIGITS:
359         case PROPERTY_ID_XSD_FRACTION_DIGITS:
360             nControlType = PropertyControlType::NumericField;
361             break;
362 
363         case PROPERTY_ID_XSD_MAX_INCLUSIVE_INT:
364         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_INT:
365         case PROPERTY_ID_XSD_MIN_INCLUSIVE_INT:
366         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_INT:
367         {
368             nControlType = PropertyControlType::NumericField;
369 
370             // handle limits for various 'INT' types according to
371             // their actual semantics (year, month, day)
372 
373             ::rtl::Reference< XSDDataType > xDataType( m_pHelper->getValidatingDataType() );
374             sal_Int16 nTypeClass = xDataType.is() ? xDataType->classify() : DataTypeClass::STRING;
375 
376             aMinValue.IsPresent = aMaxValue.IsPresent = sal_True;
377             aMinValue.Value = DataTypeClass::gYear == nTypeClass ? 0 : 1;
378             aMaxValue.Value = ::std::numeric_limits< sal_Int32 >::max();
379             if ( DataTypeClass::gMonth == nTypeClass )
380                 aMaxValue.Value = 12;
381             else if ( DataTypeClass::gDay == nTypeClass )
382                 aMaxValue.Value = 31;
383         }
384         break;
385 
386         case PROPERTY_ID_XSD_MAX_INCLUSIVE_DOUBLE:
387         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DOUBLE:
388         case PROPERTY_ID_XSD_MIN_INCLUSIVE_DOUBLE:
389         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DOUBLE:
390             nControlType = PropertyControlType::NumericField;
391             // TODO/eForms: do we have "auto-digits"?
392             break;
393 
394         case PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE:
395         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE:
396         case PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE:
397         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE:
398             nControlType = PropertyControlType::DateField;
399             break;
400 
401         case PROPERTY_ID_XSD_MAX_INCLUSIVE_TIME:
402         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_TIME:
403         case PROPERTY_ID_XSD_MIN_INCLUSIVE_TIME:
404         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_TIME:
405             nControlType = PropertyControlType::TimeField;
406             break;
407 
408         case PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE_TIME:
409         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE_TIME:
410         case PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE_TIME:
411         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE_TIME:
412             nControlType = PropertyControlType::DateTimeField;
413             break;
414 
415         default:
416             DBG_ERROR( "XSDValidationPropertyHandler::describePropertyLine: cannot handle this property!" );
417             break;
418         }
419 
420         switch ( nControlType )
421         {
422         case PropertyControlType::ListBox:
423             aDescriptor.Control = PropertyHandlerHelper::createListBoxControl( _rxControlFactory, aListEntries, sal_False, sal_False );
424             break;
425         case PropertyControlType::NumericField:
426             aDescriptor.Control = PropertyHandlerHelper::createNumericControl( _rxControlFactory, 0, aMinValue, aMaxValue, sal_False );
427             break;
428         default:
429             aDescriptor.Control = _rxControlFactory->createPropertyControl( nControlType, sal_False );
430             break;
431         }
432 
433         aDescriptor.Category = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Data" ) );
434         aDescriptor.DisplayName = m_pInfoService->getPropertyTranslation( nPropId );
435         aDescriptor.HelpURL = HelpIdUrl::getHelpURL( m_pInfoService->getPropertyHelpId( nPropId ) );
436 
437         return aDescriptor;
438     }
439 
440     //--------------------------------------------------------------------
441     InteractiveSelectionResult SAL_CALL XSDValidationPropertyHandler::onInteractivePropertySelection( const ::rtl::OUString& _rPropertyName, sal_Bool _bPrimary, Any& /*_rData*/, const Reference< XObjectInspectorUI >& _rxInspectorUI ) throw (UnknownPropertyException, NullPointerException, RuntimeException)
442     {
443         if ( !_rxInspectorUI.is() )
444             throw NullPointerException();
445 
446         ::osl::MutexGuard aGuard( m_aMutex );
447         OSL_ENSURE( m_pHelper.get(), "XSDValidationPropertyHandler::onInteractivePropertySelection: we don't have any SupportedProperties!" );
448         if ( !m_pHelper.get() )
449             return InteractiveSelectionResult_Cancelled;
450 
451         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
452 
453         switch ( nPropId )
454         {
455         case PROPERTY_ID_XSD_DATA_TYPE:
456         {
457             if ( _bPrimary )
458             {
459                 ::rtl::OUString sNewDataTypeName;
460                 if ( implPrepareCloneDataCurrentType( sNewDataTypeName ) )
461                 {
462                     implDoCloneCurrentDataType( sNewDataTypeName );
463                     return InteractiveSelectionResult_Success;
464                 }
465             }
466             else
467                 return implPrepareRemoveCurrentDataType() && implDoRemoveCurrentDataType() ? InteractiveSelectionResult_Success : InteractiveSelectionResult_Cancelled;
468         }
469         break;
470 
471         default:
472             DBG_ERROR( "XSDValidationPropertyHandler::onInteractivePropertySelection: unexpected property to build a dedicated UI!" );
473             break;
474         }
475         return InteractiveSelectionResult_Cancelled;
476     }
477 
478     //--------------------------------------------------------------------
479     void SAL_CALL XSDValidationPropertyHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
480     {
481         ::osl::MutexGuard aGuard( m_aMutex );
482         XSDValidationPropertyHandler_Base::addPropertyChangeListener( _rxListener );
483         if ( m_pHelper.get() )
484             m_pHelper->registerBindingListener( _rxListener );
485     }
486 
487     //--------------------------------------------------------------------
488     void SAL_CALL XSDValidationPropertyHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener ) throw (RuntimeException)
489     {
490         ::osl::MutexGuard aGuard( m_aMutex );
491         if ( m_pHelper.get() )
492             m_pHelper->revokeBindingListener( _rxListener );
493         XSDValidationPropertyHandler_Base::removePropertyChangeListener( _rxListener );
494     }
495 
496     //--------------------------------------------------------------------
497     bool XSDValidationPropertyHandler::implPrepareCloneDataCurrentType( ::rtl::OUString& _rNewName ) SAL_THROW(())
498     {
499         OSL_PRECOND( m_pHelper.get(), "XSDValidationPropertyHandler::implPrepareCloneDataCurrentType: this will crash!" );
500 
501         ::rtl::Reference< XSDDataType > pType = m_pHelper->getValidatingDataType();
502         if ( !pType.is() )
503         {
504             DBG_ERROR( "XSDValidationPropertyHandler::implPrepareCloneDataCurrentType: invalid current data type!" );
505             return false;
506         }
507 
508         ::std::vector< ::rtl::OUString > aExistentNames;
509         m_pHelper->getAvailableDataTypeNames( aExistentNames );
510 
511         NewDataTypeDialog aDialog( NULL, pType->getName(), aExistentNames );  // TODO/eForms: proper parent
512         if ( aDialog.Execute() != RET_OK )
513             return false;
514 
515         _rNewName = aDialog.GetName();
516         return true;
517     }
518 
519     //--------------------------------------------------------------------
520     bool XSDValidationPropertyHandler::implDoCloneCurrentDataType( const ::rtl::OUString& _rNewName ) SAL_THROW(())
521     {
522         OSL_PRECOND( m_pHelper.get(), "XSDValidationPropertyHandler::implDoCloneCurrentDataType: this will crash!" );
523 
524         ::rtl::Reference< XSDDataType > pType = m_pHelper->getValidatingDataType();
525         if ( !pType.is() )
526             return false;
527 
528         if ( !m_pHelper->cloneDataType( pType, _rNewName ) )
529             return false;
530 
531         m_pHelper->setValidatingDataTypeByName( _rNewName );
532         return true;
533     }
534 
535     //--------------------------------------------------------------------
536     bool XSDValidationPropertyHandler::implPrepareRemoveCurrentDataType() SAL_THROW(())
537     {
538         OSL_PRECOND( m_pHelper.get(), "XSDValidationPropertyHandler::implPrepareRemoveCurrentDataType: this will crash!" );
539 
540         ::rtl::Reference< XSDDataType > pType = m_pHelper->getValidatingDataType();
541         if ( !pType.is() )
542         {
543             DBG_ERROR( "XSDValidationPropertyHandler::implPrepareRemoveCurrentDataType: invalid current data type!" );
544             return false;
545         }
546 
547         // confirmation message
548         String sConfirmation( PcrRes( RID_STR_CONFIRM_DELETE_DATA_TYPE ) );
549         sConfirmation.SearchAndReplaceAscii( "#type#", pType->getName() );
550         QueryBox aQuery( NULL, WB_YES_NO, sConfirmation ); // TODO/eForms: proper parent
551         if ( aQuery.Execute() != RET_YES )
552             return false;
553 
554         return true;
555     }
556 
557     //--------------------------------------------------------------------
558     bool XSDValidationPropertyHandler::implDoRemoveCurrentDataType() SAL_THROW(())
559     {
560         OSL_PRECOND( m_pHelper.get(), "XSDValidationPropertyHandler::implDoRemoveCurrentDataType: this will crash!" );
561 
562         ::rtl::Reference< XSDDataType > pType = m_pHelper->getValidatingDataType();
563         if ( !pType.is() )
564             return false;
565 
566         // set a new data type at the binding, which is the "basic" type for the one
567         // we are going to delete
568         // (do this before the actual deletion, so the old type is still valid for property change
569         // notifications)
570         m_pHelper->setValidatingDataTypeByName( m_pHelper->getBasicTypeNameForClass( pType->classify() ) );
571         // now remove the type
572         m_pHelper->removeDataTypeFromRepository( pType->getName() );
573 
574         return true;
575     }
576 
577     //--------------------------------------------------------------------
578     void SAL_CALL XSDValidationPropertyHandler::actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& _rOldValue, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit ) throw (NullPointerException, RuntimeException)
579     {
580         if ( !_rxInspectorUI.is() )
581             throw NullPointerException();
582 
583         ::osl::MutexGuard aGuard( m_aMutex );
584         PropertyId nActuatingPropId( impl_getPropertyId_throw( _rActuatingPropertyName ) );
585         if ( !m_pHelper.get() )
586             throw RuntimeException();
587             // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
588 
589         switch ( nActuatingPropId )
590         {
591         case PROPERTY_ID_XSD_DATA_TYPE:
592         {
593             ::rtl::Reference< XSDDataType > xDataType( m_pHelper->getValidatingDataType() );
594 
595             // is removal of this type possible?
596             sal_Bool bIsBasicType = xDataType.is() && xDataType->isBasicType();
597             _rxInspectorUI->enablePropertyUIElements( PROPERTY_XSD_DATA_TYPE, PropertyLineElement::PrimaryButton, xDataType.is() );
598             _rxInspectorUI->enablePropertyUIElements( PROPERTY_XSD_DATA_TYPE, PropertyLineElement::SecondaryButton, xDataType.is() && !bIsBasicType );
599 
600             //------------------------------------------------------------
601             // show the facets which are available at the data type
602             ::rtl::OUString aFacets[] = {
603                 PROPERTY_XSD_WHITESPACES, PROPERTY_XSD_PATTERN,
604                 PROPERTY_XSD_LENGTH, PROPERTY_XSD_MIN_LENGTH, PROPERTY_XSD_MAX_LENGTH, PROPERTY_XSD_TOTAL_DIGITS,
605                 PROPERTY_XSD_FRACTION_DIGITS,
606                 PROPERTY_XSD_MAX_INCLUSIVE_INT,
607                 PROPERTY_XSD_MAX_EXCLUSIVE_INT,
608                 PROPERTY_XSD_MIN_INCLUSIVE_INT,
609                 PROPERTY_XSD_MIN_EXCLUSIVE_INT,
610                 PROPERTY_XSD_MAX_INCLUSIVE_DOUBLE,
611                 PROPERTY_XSD_MAX_EXCLUSIVE_DOUBLE,
612                 PROPERTY_XSD_MIN_INCLUSIVE_DOUBLE,
613                 PROPERTY_XSD_MIN_EXCLUSIVE_DOUBLE,
614                 PROPERTY_XSD_MAX_INCLUSIVE_DATE,
615                 PROPERTY_XSD_MAX_EXCLUSIVE_DATE,
616                 PROPERTY_XSD_MIN_INCLUSIVE_DATE,
617                 PROPERTY_XSD_MIN_EXCLUSIVE_DATE,
618                 PROPERTY_XSD_MAX_INCLUSIVE_TIME,
619                 PROPERTY_XSD_MAX_EXCLUSIVE_TIME,
620                 PROPERTY_XSD_MIN_INCLUSIVE_TIME,
621                 PROPERTY_XSD_MIN_EXCLUSIVE_TIME,
622                 PROPERTY_XSD_MAX_INCLUSIVE_DATE_TIME,
623                 PROPERTY_XSD_MAX_EXCLUSIVE_DATE_TIME,
624                 PROPERTY_XSD_MIN_INCLUSIVE_DATE_TIME,
625                 PROPERTY_XSD_MIN_EXCLUSIVE_DATE_TIME
626             };
627 
628             size_t i=0;
629             const ::rtl::OUString* pLoop = NULL;
630             for ( i = 0, pLoop = aFacets;
631                   i < sizeof( aFacets ) / sizeof( aFacets[0] );
632                   ++i, ++pLoop
633                 )
634             {
635                 showPropertyUI( _rxInspectorUI, *pLoop, xDataType.is() && xDataType->hasFacet( *pLoop ) );
636                 _rxInspectorUI->enablePropertyUI( *pLoop, !bIsBasicType );
637             }
638         }
639         break;
640 
641         case PROPERTY_ID_XML_DATA_MODEL:
642         {
643             // The data type which the current binding works with may not be present in the
644             // new model. Thus, transfer it.
645             ::rtl::OUString sOldModelName; _rOldValue >>= sOldModelName;
646             ::rtl::OUString sNewModelName; _rNewValue >>= sNewModelName;
647             ::rtl::OUString sDataType = m_pHelper->getValidatingDataTypeName();
648             m_pHelper->copyDataType( sOldModelName, sNewModelName, sDataType );
649 
650             // the list of available data types depends on the chosen model, so update this
651             if ( !_bFirstTimeInit )
652                 _rxInspectorUI->rebuildPropertyUI( PROPERTY_XSD_DATA_TYPE );
653         }
654         break;
655 
656         default:
657             DBG_ERROR( "XSDValidationPropertyHandler::actuatingPropertyChanged: cannot handle this property!" );
658             return;
659         }
660 
661         // in both cases, we need to care for the current value of the XSD_DATA_TYPE property,
662         // and update the FormatKey of the formatted field we're inspecting (if any)
663         if ( !_bFirstTimeInit && m_pHelper->isInspectingFormattedField() )
664             m_pHelper->findDefaultFormatForIntrospectee();
665     }
666 
667     //--------------------------------------------------------------------
668     void XSDValidationPropertyHandler::implGetAvailableDataTypeNames( ::std::vector< ::rtl::OUString >& /* [out] */ _rNames ) const SAL_THROW(())
669     {
670         OSL_PRECOND( m_pHelper.get(), "XSDValidationPropertyHandler::implGetAvailableDataTypeNames: this will crash!" );
671         // start with *all* types which are available at the model
672         ::std::vector< ::rtl::OUString > aAllTypes;
673         m_pHelper->getAvailableDataTypeNames( aAllTypes );
674         _rNames.clear();
675         _rNames.reserve( aAllTypes.size() );
676 
677         // then allow only those which are "compatible" with our control
678         for ( ::std::vector< ::rtl::OUString >::const_iterator dataType = aAllTypes.begin();
679               dataType != aAllTypes.end();
680               ++dataType
681             )
682         {
683             ::rtl::Reference< XSDDataType > pType = m_pHelper->getDataTypeByName( *dataType );
684             if ( pType.is() && m_pHelper->canBindToDataType( pType->classify() ) )
685                 _rNames.push_back( *dataType );
686         }
687     }
688 
689 //........................................................................
690 } // namespace pcr
691 //........................................................................
692 
693