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