xref: /trunk/main/extensions/source/propctrlr/xsdvalidationpropertyhandler.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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(  )
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(  )
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 )
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 )
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( )
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( )
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     {
304         ::osl::MutexGuard aGuard( m_aMutex );
305         if ( !_rxControlFactory.is() )
306             throw NullPointerException();
307         if ( !m_pHelper.get() )
308             throw RuntimeException();
309 
310         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
311 
312         LineDescriptor aDescriptor;
313         if ( nPropId != PROPERTY_ID_XSD_DATA_TYPE )
314             aDescriptor.IndentLevel = 1;
315 
316         // collect some information about the to-be-created control
317         sal_Int16 nControlType = PropertyControlType::TextField;
318         ::std::vector< ::rtl::OUString > aListEntries;
319         Optional< double > aMinValue( sal_False, 0 );
320         Optional< double > aMaxValue( sal_False, 0 );
321 
322         switch ( nPropId )
323         {
324         case PROPERTY_ID_XSD_DATA_TYPE:
325             nControlType = PropertyControlType::ListBox;
326 
327             implGetAvailableDataTypeNames( aListEntries );
328 
329             aDescriptor.PrimaryButtonId = rtl::OUString::createFromAscii(UID_PROP_ADD_DATA_TYPE);
330             aDescriptor.SecondaryButtonId = rtl::OUString::createFromAscii(UID_PROP_REMOVE_DATA_TYPE);
331             aDescriptor.HasPrimaryButton = aDescriptor.HasSecondaryButton = sal_True;
332             aDescriptor.PrimaryButtonImageURL = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:graphicrepository/extensions/res/buttonplus.png" ) );
333             aDescriptor.SecondaryButtonImageURL = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:graphicrepository/extensions/res/buttonminus.png" ) );
334             break;
335 
336         case PROPERTY_ID_XSD_WHITESPACES:
337         {
338             nControlType = PropertyControlType::ListBox;
339             aListEntries = m_pInfoService->getPropertyEnumRepresentations( PROPERTY_ID_XSD_WHITESPACES );
340         }
341         break;
342 
343         case PROPERTY_ID_XSD_PATTERN:
344             nControlType = PropertyControlType::TextField;
345             break;
346 
347         case PROPERTY_ID_XSD_LENGTH:
348         case PROPERTY_ID_XSD_MIN_LENGTH:
349         case PROPERTY_ID_XSD_MAX_LENGTH:
350             nControlType = PropertyControlType::NumericField;
351             break;
352 
353         case PROPERTY_ID_XSD_TOTAL_DIGITS:
354         case PROPERTY_ID_XSD_FRACTION_DIGITS:
355             nControlType = PropertyControlType::NumericField;
356             break;
357 
358         case PROPERTY_ID_XSD_MAX_INCLUSIVE_INT:
359         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_INT:
360         case PROPERTY_ID_XSD_MIN_INCLUSIVE_INT:
361         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_INT:
362         {
363             nControlType = PropertyControlType::NumericField;
364 
365             // handle limits for various 'INT' types according to
366             // their actual semantics (year, month, day)
367 
368             ::rtl::Reference< XSDDataType > xDataType( m_pHelper->getValidatingDataType() );
369             sal_Int16 nTypeClass = xDataType.is() ? xDataType->classify() : DataTypeClass::STRING;
370 
371             aMinValue.IsPresent = aMaxValue.IsPresent = sal_True;
372             aMinValue.Value = DataTypeClass::gYear == nTypeClass ? 0 : 1;
373             aMaxValue.Value = ::std::numeric_limits< sal_Int32 >::max();
374             if ( DataTypeClass::gMonth == nTypeClass )
375                 aMaxValue.Value = 12;
376             else if ( DataTypeClass::gDay == nTypeClass )
377                 aMaxValue.Value = 31;
378         }
379         break;
380 
381         case PROPERTY_ID_XSD_MAX_INCLUSIVE_DOUBLE:
382         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DOUBLE:
383         case PROPERTY_ID_XSD_MIN_INCLUSIVE_DOUBLE:
384         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DOUBLE:
385             nControlType = PropertyControlType::NumericField;
386             // TODO/eForms: do we have "auto-digits"?
387             break;
388 
389         case PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE:
390         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE:
391         case PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE:
392         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE:
393             nControlType = PropertyControlType::DateField;
394             break;
395 
396         case PROPERTY_ID_XSD_MAX_INCLUSIVE_TIME:
397         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_TIME:
398         case PROPERTY_ID_XSD_MIN_INCLUSIVE_TIME:
399         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_TIME:
400             nControlType = PropertyControlType::TimeField;
401             break;
402 
403         case PROPERTY_ID_XSD_MAX_INCLUSIVE_DATE_TIME:
404         case PROPERTY_ID_XSD_MAX_EXCLUSIVE_DATE_TIME:
405         case PROPERTY_ID_XSD_MIN_INCLUSIVE_DATE_TIME:
406         case PROPERTY_ID_XSD_MIN_EXCLUSIVE_DATE_TIME:
407             nControlType = PropertyControlType::DateTimeField;
408             break;
409 
410         default:
411             DBG_ERROR( "XSDValidationPropertyHandler::describePropertyLine: cannot handle this property!" );
412             break;
413         }
414 
415         switch ( nControlType )
416         {
417         case PropertyControlType::ListBox:
418             aDescriptor.Control = PropertyHandlerHelper::createListBoxControl( _rxControlFactory, aListEntries, sal_False, sal_False );
419             break;
420         case PropertyControlType::NumericField:
421             aDescriptor.Control = PropertyHandlerHelper::createNumericControl( _rxControlFactory, 0, aMinValue, aMaxValue, sal_False );
422             break;
423         default:
424             aDescriptor.Control = _rxControlFactory->createPropertyControl( nControlType, sal_False );
425             break;
426         }
427 
428         aDescriptor.Category = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Data" ) );
429         aDescriptor.DisplayName = m_pInfoService->getPropertyTranslation( nPropId );
430         aDescriptor.HelpURL = HelpIdUrl::getHelpURL( m_pInfoService->getPropertyHelpId( nPropId ) );
431 
432         return aDescriptor;
433     }
434 
435     //--------------------------------------------------------------------
onInteractivePropertySelection(const::rtl::OUString & _rPropertyName,sal_Bool _bPrimary,Any &,const Reference<XObjectInspectorUI> & _rxInspectorUI)436     InteractiveSelectionResult SAL_CALL XSDValidationPropertyHandler::onInteractivePropertySelection( const ::rtl::OUString& _rPropertyName, sal_Bool _bPrimary, Any& /*_rData*/, const Reference< XObjectInspectorUI >& _rxInspectorUI )
437     {
438         if ( !_rxInspectorUI.is() )
439             throw NullPointerException();
440 
441         ::osl::MutexGuard aGuard( m_aMutex );
442         OSL_ENSURE( m_pHelper.get(), "XSDValidationPropertyHandler::onInteractivePropertySelection: we don't have any SupportedProperties!" );
443         if ( !m_pHelper.get() )
444             return InteractiveSelectionResult_Cancelled;
445 
446         PropertyId nPropId( impl_getPropertyId_throw( _rPropertyName ) );
447 
448         switch ( nPropId )
449         {
450         case PROPERTY_ID_XSD_DATA_TYPE:
451         {
452             if ( _bPrimary )
453             {
454                 ::rtl::OUString sNewDataTypeName;
455                 if ( implPrepareCloneDataCurrentType( sNewDataTypeName ) )
456                 {
457                     implDoCloneCurrentDataType( sNewDataTypeName );
458                     return InteractiveSelectionResult_Success;
459                 }
460             }
461             else
462                 return implPrepareRemoveCurrentDataType() && implDoRemoveCurrentDataType() ? InteractiveSelectionResult_Success : InteractiveSelectionResult_Cancelled;
463         }
464         break;
465 
466         default:
467             DBG_ERROR( "XSDValidationPropertyHandler::onInteractivePropertySelection: unexpected property to build a dedicated UI!" );
468             break;
469         }
470         return InteractiveSelectionResult_Cancelled;
471     }
472 
473     //--------------------------------------------------------------------
addPropertyChangeListener(const Reference<XPropertyChangeListener> & _rxListener)474     void SAL_CALL XSDValidationPropertyHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener )
475     {
476         ::osl::MutexGuard aGuard( m_aMutex );
477         XSDValidationPropertyHandler_Base::addPropertyChangeListener( _rxListener );
478         if ( m_pHelper.get() )
479             m_pHelper->registerBindingListener( _rxListener );
480     }
481 
482     //--------------------------------------------------------------------
removePropertyChangeListener(const Reference<XPropertyChangeListener> & _rxListener)483     void SAL_CALL XSDValidationPropertyHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener )
484     {
485         ::osl::MutexGuard aGuard( m_aMutex );
486         if ( m_pHelper.get() )
487             m_pHelper->revokeBindingListener( _rxListener );
488         XSDValidationPropertyHandler_Base::removePropertyChangeListener( _rxListener );
489     }
490 
491     //--------------------------------------------------------------------
implPrepareCloneDataCurrentType(::rtl::OUString & _rNewName)492     bool XSDValidationPropertyHandler::implPrepareCloneDataCurrentType( ::rtl::OUString& _rNewName ) SAL_THROW(())
493     {
494         OSL_PRECOND( m_pHelper.get(), "XSDValidationPropertyHandler::implPrepareCloneDataCurrentType: this will crash!" );
495 
496         ::rtl::Reference< XSDDataType > pType = m_pHelper->getValidatingDataType();
497         if ( !pType.is() )
498         {
499             DBG_ERROR( "XSDValidationPropertyHandler::implPrepareCloneDataCurrentType: invalid current data type!" );
500             return false;
501         }
502 
503         ::std::vector< ::rtl::OUString > aExistentNames;
504         m_pHelper->getAvailableDataTypeNames( aExistentNames );
505 
506         NewDataTypeDialog aDialog( NULL, pType->getName(), aExistentNames );  // TODO/eForms: proper parent
507         if ( aDialog.Execute() != RET_OK )
508             return false;
509 
510         _rNewName = aDialog.GetName();
511         return true;
512     }
513 
514     //--------------------------------------------------------------------
implDoCloneCurrentDataType(const::rtl::OUString & _rNewName)515     bool XSDValidationPropertyHandler::implDoCloneCurrentDataType( const ::rtl::OUString& _rNewName ) SAL_THROW(())
516     {
517         OSL_PRECOND( m_pHelper.get(), "XSDValidationPropertyHandler::implDoCloneCurrentDataType: this will crash!" );
518 
519         ::rtl::Reference< XSDDataType > pType = m_pHelper->getValidatingDataType();
520         if ( !pType.is() )
521             return false;
522 
523         if ( !m_pHelper->cloneDataType( pType, _rNewName ) )
524             return false;
525 
526         m_pHelper->setValidatingDataTypeByName( _rNewName );
527         return true;
528     }
529 
530     //--------------------------------------------------------------------
implPrepareRemoveCurrentDataType()531     bool XSDValidationPropertyHandler::implPrepareRemoveCurrentDataType() SAL_THROW(())
532     {
533         OSL_PRECOND( m_pHelper.get(), "XSDValidationPropertyHandler::implPrepareRemoveCurrentDataType: this will crash!" );
534 
535         ::rtl::Reference< XSDDataType > pType = m_pHelper->getValidatingDataType();
536         if ( !pType.is() )
537         {
538             DBG_ERROR( "XSDValidationPropertyHandler::implPrepareRemoveCurrentDataType: invalid current data type!" );
539             return false;
540         }
541 
542         // confirmation message
543         String sConfirmation( PcrRes( RID_STR_CONFIRM_DELETE_DATA_TYPE ) );
544         sConfirmation.SearchAndReplaceAscii( "#type#", pType->getName() );
545         QueryBox aQuery( NULL, WB_YES_NO, sConfirmation ); // TODO/eForms: proper parent
546         if ( aQuery.Execute() != RET_YES )
547             return false;
548 
549         return true;
550     }
551 
552     //--------------------------------------------------------------------
implDoRemoveCurrentDataType()553     bool XSDValidationPropertyHandler::implDoRemoveCurrentDataType() SAL_THROW(())
554     {
555         OSL_PRECOND( m_pHelper.get(), "XSDValidationPropertyHandler::implDoRemoveCurrentDataType: this will crash!" );
556 
557         ::rtl::Reference< XSDDataType > pType = m_pHelper->getValidatingDataType();
558         if ( !pType.is() )
559             return false;
560 
561         // set a new data type at the binding, which is the "basic" type for the one
562         // we are going to delete
563         // (do this before the actual deletion, so the old type is still valid for property change
564         // notifications)
565         m_pHelper->setValidatingDataTypeByName( m_pHelper->getBasicTypeNameForClass( pType->classify() ) );
566         // now remove the type
567         m_pHelper->removeDataTypeFromRepository( pType->getName() );
568 
569         return true;
570     }
571 
572     //--------------------------------------------------------------------
actuatingPropertyChanged(const::rtl::OUString & _rActuatingPropertyName,const Any & _rNewValue,const Any & _rOldValue,const Reference<XObjectInspectorUI> & _rxInspectorUI,sal_Bool _bFirstTimeInit)573     void SAL_CALL XSDValidationPropertyHandler::actuatingPropertyChanged( const ::rtl::OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& _rOldValue, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit )
574     {
575         if ( !_rxInspectorUI.is() )
576             throw NullPointerException();
577 
578         ::osl::MutexGuard aGuard( m_aMutex );
579         PropertyId nActuatingPropId( impl_getPropertyId_throw( _rActuatingPropertyName ) );
580         if ( !m_pHelper.get() )
581             throw RuntimeException();
582             // if we survived impl_getPropertyId_throw, we should have a helper, since no helper implies no properties
583 
584         switch ( nActuatingPropId )
585         {
586         case PROPERTY_ID_XSD_DATA_TYPE:
587         {
588             ::rtl::Reference< XSDDataType > xDataType( m_pHelper->getValidatingDataType() );
589 
590             // is removal of this type possible?
591             sal_Bool bIsBasicType = xDataType.is() && xDataType->isBasicType();
592             _rxInspectorUI->enablePropertyUIElements( PROPERTY_XSD_DATA_TYPE, PropertyLineElement::PrimaryButton, xDataType.is() );
593             _rxInspectorUI->enablePropertyUIElements( PROPERTY_XSD_DATA_TYPE, PropertyLineElement::SecondaryButton, xDataType.is() && !bIsBasicType );
594 
595             //------------------------------------------------------------
596             // show the facets which are available at the data type
597             ::rtl::OUString aFacets[] = {
598                 PROPERTY_XSD_WHITESPACES, PROPERTY_XSD_PATTERN,
599                 PROPERTY_XSD_LENGTH, PROPERTY_XSD_MIN_LENGTH, PROPERTY_XSD_MAX_LENGTH, PROPERTY_XSD_TOTAL_DIGITS,
600                 PROPERTY_XSD_FRACTION_DIGITS,
601                 PROPERTY_XSD_MAX_INCLUSIVE_INT,
602                 PROPERTY_XSD_MAX_EXCLUSIVE_INT,
603                 PROPERTY_XSD_MIN_INCLUSIVE_INT,
604                 PROPERTY_XSD_MIN_EXCLUSIVE_INT,
605                 PROPERTY_XSD_MAX_INCLUSIVE_DOUBLE,
606                 PROPERTY_XSD_MAX_EXCLUSIVE_DOUBLE,
607                 PROPERTY_XSD_MIN_INCLUSIVE_DOUBLE,
608                 PROPERTY_XSD_MIN_EXCLUSIVE_DOUBLE,
609                 PROPERTY_XSD_MAX_INCLUSIVE_DATE,
610                 PROPERTY_XSD_MAX_EXCLUSIVE_DATE,
611                 PROPERTY_XSD_MIN_INCLUSIVE_DATE,
612                 PROPERTY_XSD_MIN_EXCLUSIVE_DATE,
613                 PROPERTY_XSD_MAX_INCLUSIVE_TIME,
614                 PROPERTY_XSD_MAX_EXCLUSIVE_TIME,
615                 PROPERTY_XSD_MIN_INCLUSIVE_TIME,
616                 PROPERTY_XSD_MIN_EXCLUSIVE_TIME,
617                 PROPERTY_XSD_MAX_INCLUSIVE_DATE_TIME,
618                 PROPERTY_XSD_MAX_EXCLUSIVE_DATE_TIME,
619                 PROPERTY_XSD_MIN_INCLUSIVE_DATE_TIME,
620                 PROPERTY_XSD_MIN_EXCLUSIVE_DATE_TIME
621             };
622 
623             size_t i=0;
624             const ::rtl::OUString* pLoop = NULL;
625             for ( i = 0, pLoop = aFacets;
626                   i < sizeof( aFacets ) / sizeof( aFacets[0] );
627                   ++i, ++pLoop
628                 )
629             {
630                 showPropertyUI( _rxInspectorUI, *pLoop, xDataType.is() && xDataType->hasFacet( *pLoop ) );
631                 _rxInspectorUI->enablePropertyUI( *pLoop, !bIsBasicType );
632             }
633         }
634         break;
635 
636         case PROPERTY_ID_XML_DATA_MODEL:
637         {
638             // The data type which the current binding works with may not be present in the
639             // new model. Thus, transfer it.
640             ::rtl::OUString sOldModelName; _rOldValue >>= sOldModelName;
641             ::rtl::OUString sNewModelName; _rNewValue >>= sNewModelName;
642             ::rtl::OUString sDataType = m_pHelper->getValidatingDataTypeName();
643             m_pHelper->copyDataType( sOldModelName, sNewModelName, sDataType );
644 
645             // the list of available data types depends on the chosen model, so update this
646             if ( !_bFirstTimeInit )
647                 _rxInspectorUI->rebuildPropertyUI( PROPERTY_XSD_DATA_TYPE );
648         }
649         break;
650 
651         default:
652             DBG_ERROR( "XSDValidationPropertyHandler::actuatingPropertyChanged: cannot handle this property!" );
653             return;
654         }
655 
656         // in both cases, we need to care for the current value of the XSD_DATA_TYPE property,
657         // and update the FormatKey of the formatted field we're inspecting (if any)
658         if ( !_bFirstTimeInit && m_pHelper->isInspectingFormattedField() )
659             m_pHelper->findDefaultFormatForIntrospectee();
660     }
661 
662     //--------------------------------------------------------------------
implGetAvailableDataTypeNames(::std::vector<::rtl::OUString> & _rNames) const663     void XSDValidationPropertyHandler::implGetAvailableDataTypeNames( ::std::vector< ::rtl::OUString >& /* [out] */ _rNames ) const SAL_THROW(())
664     {
665         OSL_PRECOND( m_pHelper.get(), "XSDValidationPropertyHandler::implGetAvailableDataTypeNames: this will crash!" );
666         // start with *all* types which are available at the model
667         ::std::vector< ::rtl::OUString > aAllTypes;
668         m_pHelper->getAvailableDataTypeNames( aAllTypes );
669         _rNames.clear();
670         _rNames.reserve( aAllTypes.size() );
671 
672         // then allow only those which are "compatible" with our control
673         for ( ::std::vector< ::rtl::OUString >::const_iterator dataType = aAllTypes.begin();
674               dataType != aAllTypes.end();
675               ++dataType
676             )
677         {
678             ::rtl::Reference< XSDDataType > pType = m_pHelper->getDataTypeByName( *dataType );
679             if ( pType.is() && m_pHelper->canBindToDataType( pType->classify() ) )
680                 _rNames.push_back( *dataType );
681         }
682     }
683 
684 //........................................................................
685 } // namespace pcr
686 //........................................................................
687