Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / extensions / source / propctrlr / formcomponenthandler.cxx
blob1ca87af6e2fb0420fc4f029753035cb588e35ee7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "controltype.hxx"
22 #include "modulepcr.hxx"
23 #include <propctrlr.h>
24 #include <helpids.h>
25 #include "fontdialog.hxx"
26 #include "formcomponenthandler.hxx"
27 #include "formlinkdialog.hxx"
28 #include "formmetadata.hxx"
29 #include <strings.hrc>
30 #include <showhide.hrc>
31 #include <yesno.hrc>
32 #include "formstrings.hxx"
33 #include "handlerhelper.hxx"
34 #include "listselectiondlg.hxx"
35 #include "pcrcommon.hxx"
36 #include "selectlabeldialog.hxx"
37 #include "standardcontrol.hxx"
38 #include "taborder.hxx"
39 #include "usercontrol.hxx"
41 #include <com/sun/star/lang/NullPointerException.hpp>
42 #include <com/sun/star/lang/XServiceInfo.hpp>
43 #include <com/sun/star/form/FormComponentType.hpp>
44 #include <com/sun/star/beans/PropertyAttribute.hpp>
45 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
46 #include <com/sun/star/container/XNameAccess.hpp>
47 #include <com/sun/star/form/XForm.hpp>
48 #include <com/sun/star/container/XChild.hpp>
49 #include <com/sun/star/sdb/OrderDialog.hpp>
50 #include <com/sun/star/sdb/FilterDialog.hpp>
51 #include <com/sun/star/sdbc/XConnection.hpp>
52 #include <com/sun/star/sdb/CommandType.hpp>
53 #include <com/sun/star/sdb/DatabaseContext.hpp>
54 #include <com/sun/star/form/XGridColumnFactory.hpp>
55 #include <com/sun/star/sdb/SQLContext.hpp>
56 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
57 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
58 #include <com/sun/star/form/ListSourceType.hpp>
59 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
60 #include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
61 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
62 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
63 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
64 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
65 #include <com/sun/star/awt/XTabControllerModel.hpp>
66 #include <com/sun/star/form/FormSubmitEncoding.hpp>
67 #include <com/sun/star/awt/VisualEffect.hpp>
68 #include <com/sun/star/form/FormButtonType.hpp>
69 #include <com/sun/star/inspection/PropertyControlType.hpp>
70 #include <com/sun/star/util/MeasureUnit.hpp>
71 #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
72 #include <com/sun/star/inspection/PropertyLineElement.hpp>
73 #include <com/sun/star/resource/XStringResourceManager.hpp>
74 #include <com/sun/star/resource/MissingResourceException.hpp>
75 #include <com/sun/star/report/XReportDefinition.hpp>
76 #include <com/sun/star/graphic/GraphicObject.hpp>
77 #include <com/sun/star/text/WritingMode2.hpp>
79 #include <comphelper/extract.hxx>
80 #include <comphelper/types.hxx>
81 #include <connectivity/dbconversion.hxx>
82 #include <connectivity/dbexception.hxx>
83 #include <cppuhelper/exc_hlp.hxx>
84 #include <sfx2/app.hxx>
85 #include <sfx2/basedlgs.hxx>
86 #include <sfx2/docfilt.hxx>
87 #include <sfx2/filedlghelper.hxx>
88 #include <svl/ctloptions.hxx>
89 #include <svtools/colrdlg.hxx>
90 #include <svl/filenotation.hxx>
91 #include <svl/intitem.hxx>
92 #include <svl/itemset.hxx>
93 #include <svl/numformat.hxx>
94 #include <unotools/moduleoptions.hxx>
95 #include <svl/numuno.hxx>
96 #include <svl/urihelper.hxx>
97 #include <svx/dialogs.hrc>
98 #include <svx/numinf.hxx>
99 #include <svx/svxdlg.hxx>
100 #include <svx/svxids.hrc>
101 #include <vcl/graph.hxx>
102 #include <vcl/unohelp.hxx>
103 #include <comphelper/diagnose_ex.hxx>
104 #include <sal/macros.h>
105 #include <sal/log.hxx>
107 #include <limits>
108 #include <memory>
109 #include <string_view>
111 namespace pcr
115 using namespace ::com::sun::star;
116 using namespace uno;
117 using namespace lang;
118 using namespace beans;
119 using namespace frame;
120 using namespace script;
121 using namespace form;
122 using namespace util;
123 using namespace awt;
124 using namespace sdb;
125 using namespace sdbc;
126 using namespace sdbcx;
127 using namespace report;
128 using namespace container;
129 using namespace ui::dialogs;
130 using namespace inspection;
131 using namespace ::dbtools;
133 namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
136 //= FormComponentPropertyHandler
138 #define PROPERTY_ID_ROWSET 1
140 FormComponentPropertyHandler::FormComponentPropertyHandler( const Reference< XComponentContext >& _rxContext )
141 :PropertyHandlerComponent( _rxContext )
142 ,::comphelper::OPropertyContainer(PropertyHandlerComponent::rBHelper)
143 ,m_sDefaultValueString( PcrRes(RID_STR_STANDARD) )
144 ,m_eComponentClass( eUnknown )
145 ,m_bComponentIsSubForm( false )
146 ,m_bHaveListSource( false )
147 ,m_bHaveCommand( false )
148 ,m_nClassId( 0 )
150 registerProperty(PROPERTY_ROWSET,PROPERTY_ID_ROWSET,0,&m_xRowSet,cppu::UnoType<decltype(m_xRowSet)>::get());
154 FormComponentPropertyHandler::~FormComponentPropertyHandler()
158 IMPLEMENT_FORWARD_XINTERFACE2(FormComponentPropertyHandler,PropertyHandlerComponent,::comphelper::OPropertyContainer)
160 OUString FormComponentPropertyHandler::getImplementationName( )
162 return "com.sun.star.comp.extensions.FormComponentPropertyHandler";
166 Sequence< OUString > FormComponentPropertyHandler::getSupportedServiceNames( )
168 return { "com.sun.star.form.inspection.FormComponentPropertyHandler" };
171 namespace {
173 // TODO: -> export from toolkit
174 struct LanguageDependentProp
176 const char* pPropName;
177 sal_Int32 nPropNameLength;
182 const LanguageDependentProp aLanguageDependentProp[] =
184 { "Text", 4 },
185 { "Label", 5 },
186 { "Title", 5 },
187 { "HelpText", 8 },
188 { "CurrencySymbol", 14 },
189 { "StringItemList", 14 },
190 { nullptr, 0 }
193 namespace
195 bool lcl_isLanguageDependentProperty( std::u16string_view aName )
197 bool bRet = false;
199 const LanguageDependentProp* pLangDepProp = aLanguageDependentProp;
200 while( pLangDepProp->pPropName != nullptr )
202 if( o3tl::equalsAscii( aName, std::string_view(pLangDepProp->pPropName, pLangDepProp->nPropNameLength) ))
204 bRet = true;
205 break;
207 pLangDepProp++;
209 return bRet;
212 Reference< resource::XStringResourceResolver > lcl_getStringResourceResolverForProperty
213 ( const Reference< XPropertySet >& _xComponent, std::u16string_view _rPropertyName,
214 const Any& _rPropertyValue )
216 Reference< resource::XStringResourceResolver > xRet;
217 const TypeClass eType = _rPropertyValue.getValueType().getTypeClass();
218 if ( (eType == TypeClass_STRING || eType == TypeClass_SEQUENCE) &&
219 lcl_isLanguageDependentProperty( _rPropertyName ) )
221 Reference< resource::XStringResourceResolver > xStringResourceResolver;
224 xStringResourceResolver.set( _xComponent->getPropertyValue( "ResourceResolver" ),UNO_QUERY);
225 if( xStringResourceResolver.is() &&
226 xStringResourceResolver->getLocales().hasElements() )
228 xRet = xStringResourceResolver;
231 catch(const UnknownPropertyException&)
233 // nii
237 return xRet;
242 Any FormComponentPropertyHandler::impl_getPropertyValue_throw( const OUString& _rPropertyName ) const
244 const PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
246 // tdf#117159 crash with chart in database report
247 if (!m_xComponent)
248 return Any();
250 Any aPropertyValue( m_xComponent->getPropertyValue( _rPropertyName ) );
252 Reference< resource::XStringResourceResolver > xStringResourceResolver
253 = lcl_getStringResourceResolverForProperty( m_xComponent, _rPropertyName, aPropertyValue );
254 if( xStringResourceResolver.is() )
256 TypeClass eType = aPropertyValue.getValueType().getTypeClass();
257 if( eType == TypeClass_STRING )
259 OUString aPropStr;
260 aPropertyValue >>= aPropStr;
261 if( aPropStr.getLength() > 1 )
263 OUString aPureIdStr = aPropStr.copy( 1 );
264 if( xStringResourceResolver->hasEntryForId( aPureIdStr ) )
266 OUString aResourceStr = xStringResourceResolver->resolveString( aPureIdStr );
267 aPropertyValue <<= aResourceStr;
271 // StringItemList?
272 else if( eType == TypeClass_SEQUENCE )
274 Sequence< OUString > aStrings;
275 aPropertyValue >>= aStrings;
277 std::vector< OUString > aResolvedStrings;
278 aResolvedStrings.reserve( aStrings.getLength() );
281 for ( const OUString& rIdStr : std::as_const(aStrings) )
283 OUString aPureIdStr = rIdStr.copy( 1 );
284 if( xStringResourceResolver->hasEntryForId( aPureIdStr ) )
285 aResolvedStrings.push_back(xStringResourceResolver->resolveString( aPureIdStr ));
286 else
287 aResolvedStrings.push_back(rIdStr);
290 catch( const resource::MissingResourceException & )
292 aPropertyValue <<= comphelper::containerToSequence(aResolvedStrings);
295 else
296 impl_normalizePropertyValue_nothrow( aPropertyValue, nPropId );
298 return aPropertyValue;
301 Any SAL_CALL FormComponentPropertyHandler::getPropertyValue( const OUString& _rPropertyName )
303 if( _rPropertyName == PROPERTY_ROWSET )
304 return ::comphelper::OPropertyContainer::getPropertyValue( _rPropertyName );
306 ::osl::MutexGuard aGuard( m_aMutex );
307 return impl_getPropertyValue_throw( _rPropertyName );
310 void SAL_CALL FormComponentPropertyHandler::setPropertyValue( const OUString& _rPropertyName, const Any& _rValue )
312 if( _rPropertyName == PROPERTY_ROWSET )
314 ::comphelper::OPropertyContainer::setPropertyValue( _rPropertyName, _rValue );
315 return;
318 ::osl::MutexGuard aGuard( m_aMutex );
319 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) ); // check if property is known by the handler
321 Reference< graphic::XGraphicObject > xGrfObj;
322 if ( PROPERTY_ID_IMAGE_URL == nPropId && ( _rValue >>= xGrfObj ) )
324 DBG_ASSERT( xGrfObj.is(), "FormComponentPropertyHandler::setPropertyValue() xGrfObj is invalid");
325 m_xComponent->setPropertyValue(PROPERTY_GRAPHIC, uno::Any(xGrfObj->getGraphic()));
327 else if ( PROPERTY_ID_FONT == nPropId )
329 // special handling, the value is a faked value we generated ourself in impl_executeFontDialog_nothrow
330 Sequence< NamedValue > aFontPropertyValues;
331 if( ! (_rValue >>= aFontPropertyValues) )
332 SAL_WARN("extensions.propctrlr", "setPropertyValue: unable to get property " << PROPERTY_ID_FONT);
334 for ( const NamedValue& fontPropertyValue : std::as_const(aFontPropertyValues) )
335 m_xComponent->setPropertyValue( fontPropertyValue.Name, fontPropertyValue.Value );
337 else
339 Any aValue = _rValue;
341 Reference< resource::XStringResourceResolver > xStringResourceResolver
342 = lcl_getStringResourceResolverForProperty( m_xComponent, _rPropertyName, _rValue );
343 if( xStringResourceResolver.is() )
345 Reference< resource::XStringResourceManager >
346 xStringResourceManager( xStringResourceResolver, UNO_QUERY );
347 if( xStringResourceManager.is() )
349 Any aPropertyValue( m_xComponent->getPropertyValue( _rPropertyName ) );
350 TypeClass eType = aPropertyValue.getValueType().getTypeClass();
351 if( eType == TypeClass_STRING )
353 OUString aPropStr;
354 aPropertyValue >>= aPropStr;
355 if( aPropStr.getLength() > 1 )
357 OUString aPureIdStr = aPropStr.copy( 1 );
358 OUString aValueStr;
359 _rValue >>= aValueStr;
360 xStringResourceManager->setString( aPureIdStr, aValueStr );
361 aValue = aPropertyValue; // set value to force modified
364 // StringItemList?
365 else if( eType == TypeClass_SEQUENCE )
367 static const char aDot[] = ".";
369 // Put strings into resource using new ids
370 Sequence< OUString > aNewStrings;
371 _rValue >>= aNewStrings;
373 const sal_Int32 nNewCount = aNewStrings.getLength();
375 // Create new Ids
376 std::unique_ptr<OUString[]> pNewPureIds(new OUString[nNewCount]);
377 Any aNameAny = m_xComponent->getPropertyValue(PROPERTY_NAME);
378 OUString sControlName;
379 aNameAny >>= sControlName;
380 OUString aIdStrBase = aDot
381 + sControlName
382 + aDot
383 + _rPropertyName;
384 sal_Int32 i;
385 for ( i = 0; i < nNewCount; ++i )
387 sal_Int32 nUniqueId = xStringResourceManager->getUniqueNumericId();
388 OUString aPureIdStr = OUString::number( nUniqueId ) + aIdStrBase;
389 pNewPureIds[i] = aPureIdStr;
390 // Force usage of next Unique Id
391 xStringResourceManager->setString( aPureIdStr, OUString() );
394 // Move strings to new Ids for all locales
395 const Sequence< Locale > aLocaleSeq = xStringResourceManager->getLocales();
396 Sequence< OUString > aOldIdStrings;
397 aPropertyValue >>= aOldIdStrings;
400 const OUString* pOldIdStrings = aOldIdStrings.getConstArray();
401 sal_Int32 nOldIdCount = aOldIdStrings.getLength();
402 for ( i = 0; i < nNewCount; ++i )
404 OUString aOldPureIdStr;
405 if( i < nOldIdCount )
407 OUString aOldIdStr = pOldIdStrings[i];
408 aOldPureIdStr = aOldIdStr.copy( 1 );
410 OUString aNewPureIdStr = pNewPureIds[i];
412 for ( const Locale& rLocale : aLocaleSeq )
414 OUString aResourceStr;
415 if( !aOldPureIdStr.isEmpty() )
417 if( xStringResourceManager->hasEntryForIdAndLocale( aOldPureIdStr, rLocale ) )
419 aResourceStr = xStringResourceManager->
420 resolveStringForLocale( aOldPureIdStr, rLocale );
423 xStringResourceManager->setStringForLocale( aNewPureIdStr, aResourceStr, rLocale );
427 catch( const resource::MissingResourceException & )
431 // Set new strings for current locale and create
432 // new Id sequence as new property value
433 Sequence< OUString > aNewIdStrings;
434 aNewIdStrings.realloc( nNewCount );
435 OUString* pNewIdStrings = aNewIdStrings.getArray();
436 for ( i = 0; i < nNewCount; ++i )
438 const OUString& aPureIdStr = pNewPureIds[i];
439 const OUString& aStr = aNewStrings[i];
440 xStringResourceManager->setString( aPureIdStr, aStr );
442 pNewIdStrings[i] = "&" + aPureIdStr;
444 aValue <<= aNewIdStrings;
446 // Remove old ids from resource for all locales
447 for( const OUString& rIdStr : std::as_const(aOldIdStrings) )
449 OUString aPureIdStr = rIdStr.copy( 1 );
450 for ( const Locale& rLocale : aLocaleSeq )
454 xStringResourceManager->removeIdForLocale( aPureIdStr, rLocale );
456 catch( const resource::MissingResourceException & )
464 m_xComponent->setPropertyValue( _rPropertyName, aValue );
468 Any SAL_CALL FormComponentPropertyHandler::convertToPropertyValue( const OUString& _rPropertyName, const Any& _rControlValue )
470 ::osl::MutexGuard aGuard( m_aMutex );
471 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
472 Property aProperty( impl_getPropertyFromId_throw( nPropId ) );
474 Any aPropertyValue( _rControlValue );
475 if ( !aPropertyValue.hasValue() )
477 if ( ( aProperty.Attributes & PropertyAttribute::MAYBEVOID ) == 0 )
478 // default construct an instance of the proper type
479 aPropertyValue = Any( nullptr, aProperty.Type );
480 // nothing to do
481 return aPropertyValue;
484 /// care for the special "default" string, translate it to VOID
485 if ( m_aPropertiesWithDefListEntry.find( _rPropertyName ) != m_aPropertiesWithDefListEntry.end() )
487 // it's a control with a string list
488 OUString sStringValue;
489 if ( _rControlValue >>= sStringValue )
490 { // note that ColorListBoxes might transfer values either as string or as css.util.Color,
491 // so this check here is important
492 if ( sStringValue == m_sDefaultValueString )
493 return Any();
497 switch ( nPropId )
499 case PROPERTY_ID_DATASOURCE:
501 OUString sControlValue;
502 if( ! (_rControlValue >>= sControlValue) )
503 SAL_WARN("extensions.propctrlr", "convertToPropertyValue: unable to get property " << PROPERTY_ID_DATASOURCE);
505 if ( !sControlValue.isEmpty() )
507 Reference< XDatabaseContext > xDatabaseContext = sdb::DatabaseContext::create( m_xContext );
508 if ( !xDatabaseContext->hasByName( sControlValue ) )
510 ::svt::OFileNotation aTransformer(sControlValue);
511 aPropertyValue <<= aTransformer.get( ::svt::OFileNotation::N_URL );
515 break; // case PROPERTY_ID_DATASOURCE
517 case PROPERTY_ID_SHOW_POSITION:
518 case PROPERTY_ID_SHOW_NAVIGATION:
519 case PROPERTY_ID_SHOW_RECORDACTIONS:
520 case PROPERTY_ID_SHOW_FILTERSORT:
522 OUString sControlValue;
523 if( ! (_rControlValue >>= sControlValue) )
524 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for Show/Hide");
526 static_assert(SAL_N_ELEMENTS(RID_RSC_ENUM_SHOWHIDE) == 2, "FormComponentPropertyHandler::convertToPropertyValue: broken resource for Show/Hide!");
527 bool bShow = sControlValue == PcrRes(RID_RSC_ENUM_SHOWHIDE[1]);
529 aPropertyValue <<= bShow;
531 break;
533 case PROPERTY_ID_TARGET_URL:
534 case PROPERTY_ID_IMAGE_URL:
536 OUString sControlValue;
537 if( ! (_rControlValue >>= sControlValue) )
538 SAL_WARN("extensions.propctrlr", "convertToPropertyValue: unable to get property for URLs");
539 // Don't convert a placeholder
540 if ( nPropId == PROPERTY_ID_IMAGE_URL && sControlValue == PcrRes(RID_EMBED_IMAGE_PLACEHOLDER) )
541 aPropertyValue <<= sControlValue;
542 else
544 INetURLObject aDocURL( impl_getDocumentURL_nothrow() );
545 aPropertyValue <<= URIHelper::SmartRel2Abs( aDocURL, sControlValue, Link<OUString *, bool>(), false, true );
548 break;
550 case PROPERTY_ID_DATEMIN:
551 case PROPERTY_ID_DATEMAX:
552 case PROPERTY_ID_DEFAULT_DATE:
553 case PROPERTY_ID_DATE:
555 util::Date aDate;
556 if( ! (_rControlValue >>= aDate) )
557 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for date");
558 aPropertyValue <<= aDate;
560 break;
562 case PROPERTY_ID_TIMEMIN:
563 case PROPERTY_ID_TIMEMAX:
564 case PROPERTY_ID_DEFAULT_TIME:
565 case PROPERTY_ID_TIME:
567 util::Time aTime;
568 if( ! (_rControlValue >>= aTime) )
569 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for time");
570 aPropertyValue <<= aTime;
572 break;
574 case PROPERTY_ID_WRITING_MODE:
576 aPropertyValue = PropertyHandlerComponent::convertToPropertyValue( _rPropertyName, _rControlValue );
578 sal_Int16 nNormalizedValue( 2 );
579 if( ! (aPropertyValue >>= nNormalizedValue) )
580 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for " << PROPERTY_ID_WRITING_MODE);
582 sal_Int16 nWritingMode = WritingMode2::CONTEXT;
583 switch ( nNormalizedValue )
585 case 0: nWritingMode = WritingMode2::LR_TB; break;
586 case 1: nWritingMode = WritingMode2::RL_TB; break;
587 case 2: nWritingMode = WritingMode2::CONTEXT; break;
588 default:
589 OSL_FAIL( "FormComponentPropertyHandler::convertToPropertyValue: unexpected 'normalized value' for WritingMode!" );
590 nWritingMode = WritingMode2::CONTEXT;
591 break;
594 aPropertyValue <<= nWritingMode;
596 break;
598 default:
599 aPropertyValue = PropertyHandlerComponent::convertToPropertyValue( _rPropertyName, _rControlValue );
600 break; // default
602 } // switch ( nPropId )
604 return aPropertyValue;
607 Any SAL_CALL FormComponentPropertyHandler::convertToControlValue( const OUString& _rPropertyName, const Any& _rPropertyValue, const Type& _rControlValueType )
609 ::osl::MutexGuard aGuard( m_aMutex );
610 sal_Int32 nPropId = m_pInfoService->getPropertyId( _rPropertyName );
611 DBG_ASSERT( nPropId != -1, "FormComponentPropertyHandler::convertToPropertyValue: not one of my properties!!" );
613 impl_getPropertyFromId_throw( nPropId );
615 Any aControlValue( _rPropertyValue );
616 if ( !aControlValue.hasValue() )
618 // if the property is represented with a list box or color list box, we need to
619 // translate this into the string "Default"
620 if ( m_aPropertiesWithDefListEntry.find( _rPropertyName ) != m_aPropertiesWithDefListEntry.end() )
621 aControlValue <<= m_sDefaultValueString;
623 return aControlValue;
626 switch ( nPropId )
629 case PROPERTY_ID_SHOW_POSITION:
630 case PROPERTY_ID_SHOW_NAVIGATION:
631 case PROPERTY_ID_SHOW_RECORDACTIONS:
632 case PROPERTY_ID_SHOW_FILTERSORT:
634 static_assert(SAL_N_ELEMENTS(RID_RSC_ENUM_SHOWHIDE) == 2, "FormComponentPropertyHandler::convertToPropertyValue: broken resource for Show/Hide!");
635 OUString sControlValue = ::comphelper::getBOOL(_rPropertyValue)
636 ? PcrRes(RID_RSC_ENUM_SHOWHIDE[1])
637 : PcrRes(RID_RSC_ENUM_SHOWHIDE[0]);
638 aControlValue <<= sControlValue;
640 break;
643 case PROPERTY_ID_DATASOURCE:
645 OSL_ENSURE( _rControlValueType.getTypeClass() == TypeClass_STRING,
646 "FormComponentPropertyHandler::convertToControlValue: wrong ControlValueType!" );
648 OUString sDataSource;
649 _rPropertyValue >>= sDataSource;
650 if ( !sDataSource.isEmpty() )
652 ::svt::OFileNotation aTransformer( sDataSource );
653 sDataSource = aTransformer.get( ::svt::OFileNotation::N_SYSTEM );
655 aControlValue <<= sDataSource;
657 break;
660 case PROPERTY_ID_CONTROLLABEL:
662 OUString sControlValue;
664 Reference< XPropertySet > xSet;
665 _rPropertyValue >>= xSet;
666 Reference< XPropertySetInfo > xPSI;
667 if ( xSet.is() )
668 xPSI = xSet->getPropertySetInfo();
669 if ( xPSI.is() && xPSI->hasPropertyByName( PROPERTY_LABEL ) )
671 OUString sLabel;
672 if( ! (xSet->getPropertyValue( PROPERTY_LABEL) >>= sLabel) )
673 SAL_WARN("extensions.propctrlr", "convertToPropertyValue: unable to get property " << PROPERTY_LABEL);
674 sControlValue = "<" + sLabel + ">";
677 aControlValue <<= sControlValue;
679 break;
682 case PROPERTY_ID_DATEMIN:
683 case PROPERTY_ID_DATEMAX:
684 case PROPERTY_ID_DEFAULT_DATE:
685 case PROPERTY_ID_DATE:
687 sal_Int32 nDate = 0;
688 if( ! (_rPropertyValue >>= nDate) )
689 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for dates");
690 aControlValue <<= DBTypeConversion::toDate( nDate );
692 break;
694 case PROPERTY_ID_TIMEMIN:
695 case PROPERTY_ID_TIMEMAX:
696 case PROPERTY_ID_DEFAULT_TIME:
697 case PROPERTY_ID_TIME:
699 sal_Int64 nTime = 0;
700 if( ! (_rPropertyValue >>= nTime) )
701 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for times");
702 aControlValue <<= DBTypeConversion::toTime( nTime );
704 break;
706 case PROPERTY_ID_WRITING_MODE:
708 sal_Int16 nWritingMode( WritingMode2::CONTEXT );
709 if( ! (_rPropertyValue >>= nWritingMode) )
710 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property " << PROPERTY_ID_WRITING_MODE);
712 sal_Int16 nNormalized = 2;
713 switch ( nWritingMode )
715 case WritingMode2::LR_TB: nNormalized = 0; break;
716 case WritingMode2::RL_TB: nNormalized = 1; break;
717 case WritingMode2::CONTEXT: nNormalized = 2; break;
718 default:
719 OSL_FAIL( "FormComponentPropertyHandler::convertToControlValue: unsupported API value for WritingMode!" );
720 nNormalized = 2;
721 break;
724 aControlValue = PropertyHandlerComponent::convertToControlValue( _rPropertyName, Any( nNormalized ), _rControlValueType );
726 break;
728 case PROPERTY_ID_FONT:
730 FontDescriptor aFont;
731 if( ! (_rPropertyValue >>= aFont) )
732 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property " << PROPERTY_ID_FONT);
734 OUStringBuffer displayName;
735 if ( aFont.Name.isEmpty() )
737 displayName.append( PcrRes(RID_STR_FONT_DEFAULT) );
739 else
741 // font name
742 displayName.append( aFont.Name + ", " );
744 // font style
745 ::FontWeight eWeight = vcl::unohelper::ConvertFontWeight( aFont.Weight );
746 TranslateId pStyleResID = RID_STR_FONTSTYLE_REGULAR;
747 if ( aFont.Slant == FontSlant_ITALIC )
749 if ( eWeight > WEIGHT_NORMAL )
750 pStyleResID = RID_STR_FONTSTYLE_BOLD_ITALIC;
751 else
752 pStyleResID = RID_STR_FONTSTYLE_ITALIC;
754 else
756 if ( eWeight > WEIGHT_NORMAL )
757 pStyleResID = RID_STR_FONTSTYLE_BOLD;
759 displayName.append(PcrRes(pStyleResID));
761 // font size
762 if ( aFont.Height )
764 displayName.append( ", " + OUString::number( sal_Int32( aFont.Height ) ) );
768 aControlValue <<= displayName.makeStringAndClear();
770 break;
772 default:
773 aControlValue = PropertyHandlerComponent::convertToControlValue( _rPropertyName, _rPropertyValue, _rControlValueType );
774 break;
776 } // switch ( nPropId )
778 return aControlValue;
781 PropertyState SAL_CALL FormComponentPropertyHandler::getPropertyState( const OUString& _rPropertyName )
783 ::osl::MutexGuard aGuard( m_aMutex );
784 if ( m_xPropertyState.is() )
785 return m_xPropertyState->getPropertyState( _rPropertyName );
786 return PropertyState_DIRECT_VALUE;
789 void SAL_CALL FormComponentPropertyHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener )
791 ::osl::MutexGuard aGuard( m_aMutex );
792 PropertyHandlerComponent::addPropertyChangeListener( _rxListener );
793 if ( m_xComponent.is() )
794 m_xComponent->addPropertyChangeListener( OUString(), _rxListener );
797 void SAL_CALL FormComponentPropertyHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener )
799 ::osl::MutexGuard aGuard( m_aMutex );
800 if ( m_xComponent.is() )
801 m_xComponent->removePropertyChangeListener( OUString(), _rxListener );
802 PropertyHandlerComponent::removePropertyChangeListener( _rxListener );
805 Sequence< Property > FormComponentPropertyHandler::doDescribeSupportedProperties() const
807 if ( !m_xComponentPropertyInfo.is() )
808 return Sequence< Property >();
810 std::vector< Property > aProperties;
812 Sequence< Property > aAllProperties( m_xComponentPropertyInfo->getProperties() );
813 aProperties.reserve( aAllProperties.getLength() );
815 // filter the properties
816 PropertyId nPropId( 0 );
817 OUString sDisplayName;
819 for ( Property & rProperty : asNonConstRange(aAllProperties) )
821 nPropId = m_pInfoService->getPropertyId( rProperty.Name );
822 if ( nPropId == -1 )
823 continue;
824 rProperty.Handle = nPropId;
826 sDisplayName = m_pInfoService->getPropertyTranslation( nPropId );
827 if ( sDisplayName.isEmpty() )
828 continue;
830 sal_uInt32 nPropertyUIFlags = m_pInfoService->getPropertyUIFlags( nPropId );
831 bool bIsVisibleForForms = ( nPropertyUIFlags & PROP_FLAG_FORM_VISIBLE ) != 0;
832 bool bIsVisibleForDialogs = ( nPropertyUIFlags & PROP_FLAG_DIALOG_VISIBLE ) != 0;
834 // depending on whether we're working for a form or a UNO dialog, some
835 // properties are not displayed
836 if ( ( m_eComponentClass == eFormControl && !bIsVisibleForForms )
837 || ( m_eComponentClass == eDialogControl && !bIsVisibleForDialogs )
839 continue;
841 // some generic sanity checks
842 if ( impl_shouldExcludeProperty_nothrow( rProperty ) )
843 continue;
845 switch ( nPropId )
847 case PROPERTY_ID_BORDER:
848 case PROPERTY_ID_TABSTOP:
849 // BORDER and TABSTOP are normalized (see impl_normalizePropertyValue_nothrow)
850 // to not allow VOID values
851 rProperty.Attributes &= ~PropertyAttribute::MAYBEVOID;
852 break;
854 case PROPERTY_ID_LISTSOURCE:
855 // no cursor source if no Base is installed.
856 if ( SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
857 const_cast< FormComponentPropertyHandler* >( this )->m_bHaveListSource = true;
858 break;
860 case PROPERTY_ID_COMMAND:
861 // no cursor source if no Base is installed.
862 if ( SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
863 const_cast< FormComponentPropertyHandler* >( this )->m_bHaveCommand = true;
864 break;
865 } // switch ( nPropId )
867 aProperties.push_back( rProperty );
870 if ( aProperties.empty() )
871 return Sequence< Property >();
872 return comphelper::containerToSequence(aProperties);
875 Sequence< OUString > SAL_CALL FormComponentPropertyHandler::getSupersededProperties( )
877 return Sequence< OUString >( );
880 Sequence< OUString > SAL_CALL FormComponentPropertyHandler::getActuatingProperties( )
882 return
884 PROPERTY_DATASOURCE,
885 PROPERTY_COMMAND,
886 PROPERTY_COMMANDTYPE,
887 PROPERTY_LISTSOURCE,
888 PROPERTY_LISTSOURCETYPE,
889 PROPERTY_SUBMIT_ENCODING,
890 PROPERTY_REPEAT,
891 PROPERTY_TABSTOP,
892 PROPERTY_BORDER,
893 PROPERTY_CONTROLSOURCE,
894 PROPERTY_DROPDOWN,
895 PROPERTY_IMAGE_URL,
896 PROPERTY_TARGET_URL,
897 PROPERTY_STRINGITEMLIST,
898 PROPERTY_BUTTONTYPE,
899 PROPERTY_ESCAPE_PROCESSING,
900 PROPERTY_TRISTATE,
901 PROPERTY_DECIMAL_ACCURACY,
902 PROPERTY_SHOWTHOUSANDSEP,
903 PROPERTY_FORMATKEY,
904 PROPERTY_EMPTY_IS_NULL,
905 PROPERTY_TOGGLE
909 LineDescriptor SAL_CALL FormComponentPropertyHandler::describePropertyLine( const OUString& _rPropertyName,
910 const Reference< XPropertyControlFactory >& _rxControlFactory )
912 if ( !_rxControlFactory.is() )
913 throw NullPointerException();
915 ::osl::MutexGuard aGuard( m_aMutex );
916 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
917 Property aProperty( impl_getPropertyFromId_throw( nPropId ) );
920 // for the MultiLine property, we have different UI translations depending on the control
921 // type
922 if ( nPropId == PROPERTY_ID_MULTILINE )
924 if ( ( m_nClassId == FormComponentType::FIXEDTEXT )
925 || ( m_nClassId == FormComponentType::COMMANDBUTTON )
926 || ( m_nClassId == FormComponentType::RADIOBUTTON )
927 || ( m_nClassId == FormComponentType::CHECKBOX )
929 nPropId = PROPERTY_ID_WORDBREAK;
932 OUString sDisplayName = m_pInfoService->getPropertyTranslation( nPropId );
933 if ( sDisplayName.isEmpty() )
935 OSL_FAIL( "FormComponentPropertyHandler::describePropertyLine: did getSupportedProperties not work properly?" );
936 throw UnknownPropertyException();
940 LineDescriptor aDescriptor;
941 aDescriptor.HelpURL = HelpIdUrl::getHelpURL( m_pInfoService->getPropertyHelpId( nPropId ) );
942 aDescriptor.DisplayName = sDisplayName;
944 // for the moment, assume a text field
945 sal_Int16 nControlType = PropertyControlType::TextField;
946 bool bReadOnly = false;
947 aDescriptor.Control.clear();
950 bool bNeedDefaultStringIfVoidAllowed = false;
952 TypeClass eType = aProperty.Type.getTypeClass();
954 switch ( nPropId )
956 case PROPERTY_ID_DEFAULT_SELECT_SEQ:
957 case PROPERTY_ID_SELECTEDITEMS:
958 aDescriptor.PrimaryButtonId = UID_PROP_DLG_SELECTION;
959 break;
961 case PROPERTY_ID_FILTER:
962 aDescriptor.PrimaryButtonId = UID_PROP_DLG_FILTER;
963 break;
965 case PROPERTY_ID_SORT:
966 aDescriptor.PrimaryButtonId = UID_PROP_DLG_ORDER;
967 break;
969 case PROPERTY_ID_MASTERFIELDS:
970 case PROPERTY_ID_DETAILFIELDS:
971 nControlType = PropertyControlType::StringListField;
972 aDescriptor.PrimaryButtonId = UID_PROP_DLG_FORMLINKFIELDS;
973 break;
975 case PROPERTY_ID_COMMAND:
976 aDescriptor.PrimaryButtonId = UID_PROP_DLG_SQLCOMMAND;
977 break;
979 case PROPERTY_ID_TABINDEX:
981 Reference< XControlContainer > xControlContext( impl_getContextControlContainer_nothrow() );
982 if ( xControlContext.is() )
983 aDescriptor.PrimaryButtonId = UID_PROP_DLG_TABINDEX;
984 nControlType = PropertyControlType::NumericField;
986 break;
988 case PROPERTY_ID_FONT:
989 bReadOnly = true;
990 aDescriptor.PrimaryButtonId = UID_PROP_DLG_FONT_TYPE;
991 break;
993 case PROPERTY_ID_TARGET_URL:
994 case PROPERTY_ID_IMAGE_URL:
996 std::unique_ptr<weld::Builder> xBuilder(PropertyHandlerHelper::makeBuilder("modules/spropctrlr/ui/urlcontrol.ui", m_xContext));
997 auto pURLBox = std::make_unique<SvtURLBox>(xBuilder->weld_combo_box("urlcontrol"));
998 rtl::Reference<OFileUrlControl> pControl = new OFileUrlControl(std::move(pURLBox), std::move(xBuilder), false);
999 pControl->SetModifyHandler();
1000 aDescriptor.Control = pControl;
1002 aDescriptor.PrimaryButtonId = PROPERTY_ID_TARGET_URL == nPropId
1003 ? OUString(UID_PROP_DLG_ATTR_TARGET_URL)
1004 : OUString(UID_PROP_DLG_IMAGE_URL);
1005 break;
1008 case PROPERTY_ID_ECHO_CHAR:
1009 nControlType = PropertyControlType::CharacterField;
1010 break;
1012 case PROPERTY_ID_BACKGROUNDCOLOR:
1013 case PROPERTY_ID_FILLCOLOR:
1014 case PROPERTY_ID_SYMBOLCOLOR:
1015 case PROPERTY_ID_BORDERCOLOR:
1016 case PROPERTY_ID_GRIDLINECOLOR:
1017 case PROPERTY_ID_HEADERBACKGROUNDCOLOR:
1018 case PROPERTY_ID_HEADERTEXTCOLOR:
1019 case PROPERTY_ID_ACTIVESELECTIONBACKGROUNDCOLOR:
1020 case PROPERTY_ID_ACTIVESELECTIONTEXTCOLOR:
1021 case PROPERTY_ID_INACTIVESELECTIONBACKGROUNDCOLOR:
1022 case PROPERTY_ID_INACTIVESELECTIONTEXTCOLOR:
1023 nControlType = PropertyControlType::ColorListBox;
1025 switch( nPropId )
1027 case PROPERTY_ID_BACKGROUNDCOLOR:
1028 aDescriptor.PrimaryButtonId = UID_PROP_DLG_BACKGROUNDCOLOR; break;
1029 case PROPERTY_ID_FILLCOLOR:
1030 aDescriptor.PrimaryButtonId = UID_PROP_DLG_FILLCOLOR; break;
1031 case PROPERTY_ID_SYMBOLCOLOR:
1032 aDescriptor.PrimaryButtonId = UID_PROP_DLG_SYMBOLCOLOR; break;
1033 case PROPERTY_ID_BORDERCOLOR:
1034 aDescriptor.PrimaryButtonId = UID_PROP_DLG_BORDERCOLOR; break;
1035 case PROPERTY_ID_GRIDLINECOLOR:
1036 aDescriptor.PrimaryButtonId = HID_PROP_GRIDLINECOLOR; break;
1037 case PROPERTY_ID_HEADERBACKGROUNDCOLOR:
1038 aDescriptor.PrimaryButtonId = HID_PROP_HEADERBACKGROUNDCOLOR; break;
1039 case PROPERTY_ID_HEADERTEXTCOLOR:
1040 aDescriptor.PrimaryButtonId = HID_PROP_HEADERTEXTCOLOR; break;
1041 case PROPERTY_ID_ACTIVESELECTIONBACKGROUNDCOLOR:
1042 aDescriptor.PrimaryButtonId = HID_PROP_ACTIVESELECTIONBACKGROUNDCOLOR; break;
1043 case PROPERTY_ID_ACTIVESELECTIONTEXTCOLOR:
1044 aDescriptor.PrimaryButtonId = HID_PROP_ACTIVESELECTIONTEXTCOLOR; break;
1045 case PROPERTY_ID_INACTIVESELECTIONBACKGROUNDCOLOR:
1046 aDescriptor.PrimaryButtonId = HID_PROP_INACTIVESELECTIONBACKGROUNDCOLOR; break;
1047 case PROPERTY_ID_INACTIVESELECTIONTEXTCOLOR:
1048 aDescriptor.PrimaryButtonId = HID_PROP_INACTIVESELECTIONTEXTCOLOR; break;
1050 break;
1052 case PROPERTY_ID_LABEL:
1053 case PROPERTY_ID_URL:
1054 nControlType = PropertyControlType::MultiLineTextField;
1055 break;
1057 case PROPERTY_ID_DEFAULT_TEXT:
1059 if (FormComponentType::FILECONTROL == m_nClassId)
1060 nControlType = PropertyControlType::TextField;
1061 else
1062 nControlType = PropertyControlType::MultiLineTextField;
1064 break;
1066 case PROPERTY_ID_TEXT:
1067 if ( impl_componentHasProperty_throw( PROPERTY_MULTILINE ) )
1068 nControlType = PropertyControlType::MultiLineTextField;
1069 break;
1071 case PROPERTY_ID_CONTROLLABEL:
1072 bReadOnly = true;
1073 aDescriptor.PrimaryButtonId = UID_PROP_DLG_CONTROLLABEL;
1074 break;
1076 case PROPERTY_ID_FORMATKEY:
1077 case PROPERTY_ID_EFFECTIVE_MIN:
1078 case PROPERTY_ID_EFFECTIVE_MAX:
1079 case PROPERTY_ID_EFFECTIVE_DEFAULT:
1080 case PROPERTY_ID_EFFECTIVE_VALUE:
1082 // and the supplier is really available
1083 Reference< XNumberFormatsSupplier > xSupplier;
1084 m_xComponent->getPropertyValue( PROPERTY_FORMATSSUPPLIER ) >>= xSupplier;
1085 if (xSupplier.is())
1087 Reference< XUnoTunnel > xTunnel(xSupplier,UNO_QUERY);
1088 DBG_ASSERT(xTunnel.is(), "FormComponentPropertyHandler::describePropertyLine : xTunnel is invalid!");
1089 if (auto pSupplier = comphelper::getFromUnoTunnel<SvNumberFormatsSupplierObj>(xTunnel))
1091 bool bIsFormatKey = (PROPERTY_ID_FORMATKEY == nPropId);
1093 bReadOnly = bIsFormatKey;
1095 if ( bIsFormatKey )
1097 std::unique_ptr<weld::Builder> xBuilder(PropertyHandlerHelper::makeBuilder("modules/spropctrlr/ui/formattedsample.ui", m_xContext));
1098 auto pContainer = xBuilder->weld_container("formattedsample");
1099 rtl::Reference<OFormatSampleControl> pControl = new OFormatSampleControl(std::move(pContainer), std::move(xBuilder), false);
1100 pControl->SetModifyHandler();
1102 pControl->SetFormatSupplier(pSupplier);
1104 aDescriptor.Control = pControl;
1106 aDescriptor.PrimaryButtonId = UID_PROP_DLG_NUMBER_FORMAT;
1108 else
1110 std::unique_ptr<weld::Builder> xBuilder(PropertyHandlerHelper::makeBuilder("modules/spropctrlr/ui/formattedcontrol.ui", m_xContext));
1111 auto pSpinButton = xBuilder->weld_formatted_spin_button("formattedcontrol");
1112 rtl::Reference<OFormattedNumericControl> pControl = new OFormattedNumericControl(std::move(pSpinButton), std::move(xBuilder), false);
1113 pControl->SetModifyHandler();
1115 FormatDescription aDesc;
1116 aDesc.pSupplier = pSupplier;
1117 Any aFormatKeyValue = m_xComponent->getPropertyValue(PROPERTY_FORMATKEY);
1118 if ( !( aFormatKeyValue >>= aDesc.nKey ) )
1119 aDesc.nKey = 0;
1121 pControl->SetFormatDescription( aDesc );
1123 aDescriptor.Control = pControl;
1128 break;
1130 case PROPERTY_ID_DATEMIN:
1131 case PROPERTY_ID_DATEMAX:
1132 case PROPERTY_ID_DEFAULT_DATE:
1133 case PROPERTY_ID_DATE:
1134 nControlType = PropertyControlType::DateField;
1135 break;
1137 case PROPERTY_ID_TIMEMIN:
1138 case PROPERTY_ID_TIMEMAX:
1139 case PROPERTY_ID_DEFAULT_TIME:
1140 case PROPERTY_ID_TIME:
1141 nControlType = PropertyControlType::TimeField;
1142 break;
1144 case PROPERTY_ID_VALUEMIN:
1145 case PROPERTY_ID_VALUEMAX:
1146 case PROPERTY_ID_DEFAULT_VALUE:
1147 case PROPERTY_ID_VALUE:
1149 std::unique_ptr<weld::Builder> xBuilder(PropertyHandlerHelper::makeBuilder("modules/spropctrlr/ui/formattedcontrol.ui", m_xContext));
1150 auto pSpinButton = xBuilder->weld_formatted_spin_button("formattedcontrol");
1151 rtl::Reference<OFormattedNumericControl> pControl = new OFormattedNumericControl(std::move(pSpinButton), std::move(xBuilder), false);
1152 pControl->SetModifyHandler();
1153 aDescriptor.Control = pControl;
1155 // we don't set a formatter so the control uses a default (which uses the application
1156 // language and a default numeric format)
1157 // but we set the decimal digits
1158 pControl->SetDecimalDigits(
1159 ::comphelper::getINT16( m_xComponent->getPropertyValue( PROPERTY_DECIMAL_ACCURACY ) )
1162 // and the default value for the property
1165 if (m_xPropertyState.is() && ((PROPERTY_ID_VALUEMIN == nPropId) || (PROPERTY_ID_VALUEMAX == nPropId)))
1167 double nDefault = 0;
1168 if ( m_xPropertyState->getPropertyDefault( aProperty.Name ) >>= nDefault )
1169 pControl->SetDefaultValue(nDefault);
1172 catch (const Exception&)
1174 // just ignore it
1177 break;
1180 default:
1181 if ( TypeClass_BYTE <= eType && eType <= TypeClass_DOUBLE )
1183 sal_Int16 nDigits = 0;
1184 sal_Int16 nValueUnit = -1;
1185 sal_Int16 nDisplayUnit = -1;
1186 if ( m_eComponentClass == eFormControl )
1188 if ( ( nPropId == PROPERTY_ID_WIDTH )
1189 || ( nPropId == PROPERTY_ID_ROWHEIGHT )
1190 || ( nPropId == PROPERTY_ID_HEIGHT )
1193 nValueUnit = MeasureUnit::MM_10TH;
1194 nDisplayUnit = impl_getDocumentMeasurementUnit_throw();
1195 nDigits = 2;
1199 Optional< double > aValueNotPresent( false, 0 );
1200 aDescriptor.Control = PropertyHandlerHelper::createNumericControl(
1201 _rxControlFactory, nDigits, aValueNotPresent, aValueNotPresent );
1203 Reference< XNumericControl > xNumericControl( aDescriptor.Control, UNO_QUERY_THROW );
1204 if ( nValueUnit != -1 )
1205 xNumericControl->setValueUnit( nValueUnit );
1206 if ( nDisplayUnit != -1 )
1207 xNumericControl->setDisplayUnit( nDisplayUnit );
1209 break;
1212 if ( eType == TypeClass_SEQUENCE )
1213 nControlType = PropertyControlType::StringListField;
1215 // boolean values
1216 if ( eType == TypeClass_BOOLEAN )
1218 if ( ( nPropId == PROPERTY_ID_SHOW_POSITION )
1219 || ( nPropId == PROPERTY_ID_SHOW_NAVIGATION )
1220 || ( nPropId == PROPERTY_ID_SHOW_RECORDACTIONS )
1221 || ( nPropId == PROPERTY_ID_SHOW_FILTERSORT )
1224 aDescriptor.Control = PropertyHandlerHelper::createListBoxControl(_rxControlFactory, RID_RSC_ENUM_SHOWHIDE, SAL_N_ELEMENTS(RID_RSC_ENUM_SHOWHIDE), false);
1226 else
1227 aDescriptor.Control = PropertyHandlerHelper::createListBoxControl(_rxControlFactory, RID_RSC_ENUM_YESNO, SAL_N_ELEMENTS(RID_RSC_ENUM_YESNO), false);
1228 bNeedDefaultStringIfVoidAllowed = true;
1232 // enum properties
1233 sal_uInt32 nPropertyUIFlags = m_pInfoService->getPropertyUIFlags( nPropId );
1234 bool bIsEnumProperty = ( nPropertyUIFlags & PROP_FLAG_ENUM ) != 0;
1235 if ( bIsEnumProperty || ( PROPERTY_ID_TARGET_FRAME == nPropId ) )
1237 std::vector< OUString > aEnumValues = m_pInfoService->getPropertyEnumRepresentations( nPropId );
1238 std::vector< OUString >::const_iterator pStart = aEnumValues.begin();
1239 std::vector< OUString >::const_iterator pEnd = aEnumValues.end();
1241 // for a checkbox: if "ambiguous" is not allowed, remove this from the sequence
1242 if ( ( PROPERTY_ID_DEFAULT_STATE == nPropId )
1243 || ( PROPERTY_ID_STATE == nPropId )
1246 if ( impl_componentHasProperty_throw( PROPERTY_TRISTATE ) )
1248 if ( !::comphelper::getBOOL( m_xComponent->getPropertyValue( PROPERTY_TRISTATE ) ) )
1249 { // remove the last sequence element
1250 if ( pEnd > pStart )
1251 --pEnd;
1254 else
1255 --pEnd;
1258 if ( PROPERTY_ID_LISTSOURCETYPE == nPropId )
1259 if ( FormComponentType::COMBOBOX == m_nClassId )
1260 // remove the first sequence element -> value list not possible for combo boxes
1261 ++pStart;
1263 // copy the sequence
1264 std::vector< OUString > aListEntries( pEnd - pStart );
1265 std::copy( pStart, pEnd, aListEntries.begin() );
1267 // create the control
1268 if ( PROPERTY_ID_TARGET_FRAME == nPropId )
1269 aDescriptor.Control = PropertyHandlerHelper::createComboBoxControl( _rxControlFactory, std::move(aListEntries), false );
1270 else
1272 aDescriptor.Control = PropertyHandlerHelper::createListBoxControl( _rxControlFactory, std::move(aListEntries), false, false );
1273 bNeedDefaultStringIfVoidAllowed = true;
1278 switch( nPropId )
1280 case PROPERTY_ID_REPEAT_DELAY:
1282 std::unique_ptr<weld::Builder> xBuilder(PropertyHandlerHelper::makeBuilder("modules/spropctrlr/ui/numericfield.ui", m_xContext));
1283 auto pSpinButton = xBuilder->weld_metric_spin_button("numericfield", FieldUnit::MILLISECOND);
1284 rtl::Reference<ONumericControl> pControl = new ONumericControl(std::move(pSpinButton), std::move(xBuilder), bReadOnly);
1285 pControl->SetModifyHandler();
1286 pControl->setMinValue( Optional< double >( true, 0 ) );
1287 pControl->setMaxValue( Optional< double >( true, std::numeric_limits< double >::max() ) );
1288 aDescriptor.Control = pControl;
1290 break;
1292 case PROPERTY_ID_TABINDEX:
1293 case PROPERTY_ID_BOUNDCOLUMN:
1294 case PROPERTY_ID_VISIBLESIZE:
1295 case PROPERTY_ID_MAXTEXTLEN:
1296 case PROPERTY_ID_LINEINCREMENT:
1297 case PROPERTY_ID_BLOCKINCREMENT:
1298 case PROPERTY_ID_SPININCREMENT:
1300 Optional< double > aMinValue( true, 0 );
1301 Optional< double > aMaxValue( true, 0x7FFFFFFF );
1303 if ( nPropId == PROPERTY_ID_MAXTEXTLEN || nPropId == PROPERTY_ID_BOUNDCOLUMN )
1304 aMinValue.Value = -1;
1305 else if ( nPropId == PROPERTY_ID_VISIBLESIZE )
1306 aMinValue.Value = 1;
1307 else
1308 aMinValue.Value = 0;
1310 aDescriptor.Control = PropertyHandlerHelper::createNumericControl(
1311 _rxControlFactory, 0, aMinValue, aMaxValue );
1313 break;
1315 case PROPERTY_ID_DECIMAL_ACCURACY:
1317 Optional< double > aMinValue( true, 0 );
1318 Optional< double > aMaxValue( true, 20 );
1320 aDescriptor.Control = PropertyHandlerHelper::createNumericControl(
1321 _rxControlFactory, 0, aMinValue, aMaxValue );
1323 break;
1326 // DataSource
1327 case PROPERTY_ID_DATASOURCE:
1329 aDescriptor.PrimaryButtonId = UID_PROP_DLG_ATTR_DATASOURCE;
1331 std::vector< OUString > aListEntries;
1333 Reference< XDatabaseContext > xDatabaseContext = sdb::DatabaseContext::create( m_xContext );
1334 const Sequence< OUString > aDatasources = xDatabaseContext->getElementNames();
1335 aListEntries.resize( aDatasources.getLength() );
1336 std::copy( aDatasources.begin(), aDatasources.end(), aListEntries.begin() );
1337 aDescriptor.Control = PropertyHandlerHelper::createComboBoxControl(
1338 _rxControlFactory, std::move(aListEntries), true );
1340 break;
1342 case PROPERTY_ID_CONTROLSOURCE:
1344 std::vector< OUString > aFieldNames;
1345 impl_initFieldList_nothrow( aFieldNames );
1346 aDescriptor.Control = PropertyHandlerHelper::createComboBoxControl(
1347 _rxControlFactory, std::move(aFieldNames), false );
1349 break;
1351 case PROPERTY_ID_COMMAND:
1352 impl_describeCursorSource_nothrow( aDescriptor, _rxControlFactory );
1353 break;
1355 case PROPERTY_ID_LISTSOURCE:
1356 impl_describeListSourceUI_throw( aDescriptor, _rxControlFactory );
1357 break;
1360 if ( !aDescriptor.Control.is() )
1361 aDescriptor.Control = _rxControlFactory->createPropertyControl( nControlType, bReadOnly );
1363 if ( ( aProperty.Attributes & PropertyAttribute::MAYBEVOID ) != 0 )
1365 // insert the string "Default" string, if necessary
1366 if (bNeedDefaultStringIfVoidAllowed)
1368 Reference< XStringListControl > xStringList( aDescriptor.Control, UNO_QUERY_THROW );
1369 xStringList->prependListEntry( m_sDefaultValueString );
1370 m_aPropertiesWithDefListEntry.insert( _rPropertyName );
1374 if ( !aDescriptor.PrimaryButtonId.isEmpty() )
1375 aDescriptor.HasPrimaryButton = true;
1376 if ( !aDescriptor.SecondaryButtonId.isEmpty() )
1377 aDescriptor.HasSecondaryButton = true;
1379 bool bIsDataProperty = ( nPropertyUIFlags & PROP_FLAG_DATA_PROPERTY ) != 0;
1380 aDescriptor.Category = bIsDataProperty ? std::u16string_view(u"Data") : std::u16string_view(u"General");
1381 return aDescriptor;
1384 InteractiveSelectionResult SAL_CALL FormComponentPropertyHandler::onInteractivePropertySelection( const OUString& _rPropertyName, sal_Bool /*_bPrimary*/, Any& _rData, const Reference< XObjectInspectorUI >& _rxInspectorUI )
1386 if ( !_rxInspectorUI.is() )
1387 throw NullPointerException();
1389 ::osl::ClearableMutexGuard aGuard( m_aMutex );
1390 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
1392 InteractiveSelectionResult eResult = InteractiveSelectionResult_Cancelled;
1393 switch ( nPropId )
1395 case PROPERTY_ID_DEFAULT_SELECT_SEQ:
1396 case PROPERTY_ID_SELECTEDITEMS:
1397 if ( impl_dialogListSelection_nothrow( _rPropertyName, aGuard ) )
1398 eResult = InteractiveSelectionResult_Success;
1399 break;
1401 case PROPERTY_ID_FILTER:
1402 case PROPERTY_ID_SORT:
1404 OUString sClause;
1405 if ( impl_dialogFilterOrSort_nothrow( PROPERTY_ID_FILTER == nPropId, sClause, aGuard ) )
1407 _rData <<= sClause;
1408 eResult = InteractiveSelectionResult_ObtainedValue;
1411 break;
1413 case PROPERTY_ID_MASTERFIELDS:
1414 case PROPERTY_ID_DETAILFIELDS:
1415 if ( impl_dialogLinkedFormFields_nothrow( aGuard ) )
1416 eResult = InteractiveSelectionResult_Success;
1417 break;
1419 case PROPERTY_ID_FORMATKEY:
1420 if ( impl_dialogFormatting_nothrow( _rData, aGuard ) )
1421 eResult = InteractiveSelectionResult_ObtainedValue;
1422 break;
1424 case PROPERTY_ID_IMAGE_URL:
1425 if ( impl_browseForImage_nothrow( _rData, aGuard ) )
1426 eResult = InteractiveSelectionResult_ObtainedValue;
1427 break;
1429 case PROPERTY_ID_TARGET_URL:
1430 if ( impl_browseForTargetURL_nothrow( _rData, aGuard ) )
1431 eResult = InteractiveSelectionResult_ObtainedValue;
1432 break;
1434 case PROPERTY_ID_FONT:
1435 if ( impl_executeFontDialog_nothrow( _rData, aGuard ) )
1436 eResult = InteractiveSelectionResult_ObtainedValue;
1437 break;
1439 case PROPERTY_ID_DATASOURCE:
1440 if ( impl_browseForDatabaseDocument_throw( _rData, aGuard ) )
1441 eResult = InteractiveSelectionResult_ObtainedValue;
1442 break;
1444 case PROPERTY_ID_BACKGROUNDCOLOR:
1445 case PROPERTY_ID_FILLCOLOR:
1446 case PROPERTY_ID_SYMBOLCOLOR:
1447 case PROPERTY_ID_BORDERCOLOR:
1448 case PROPERTY_ID_GRIDLINECOLOR:
1449 case PROPERTY_ID_HEADERBACKGROUNDCOLOR:
1450 case PROPERTY_ID_HEADERTEXTCOLOR:
1451 case PROPERTY_ID_ACTIVESELECTIONBACKGROUNDCOLOR:
1452 case PROPERTY_ID_ACTIVESELECTIONTEXTCOLOR:
1453 case PROPERTY_ID_INACTIVESELECTIONBACKGROUNDCOLOR:
1454 case PROPERTY_ID_INACTIVESELECTIONTEXTCOLOR:
1455 if ( impl_dialogColorChooser_throw( nPropId, _rData, aGuard ) )
1456 eResult = InteractiveSelectionResult_ObtainedValue;
1457 break;
1459 case PROPERTY_ID_CONTROLLABEL:
1460 if ( impl_dialogChooseLabelControl_nothrow( _rData, aGuard ) )
1461 eResult = InteractiveSelectionResult_ObtainedValue;
1462 break;
1464 case PROPERTY_ID_TABINDEX:
1465 if ( impl_dialogChangeTabOrder_nothrow( aGuard ) )
1466 eResult = InteractiveSelectionResult_Success;
1467 break;
1469 case PROPERTY_ID_COMMAND:
1470 case PROPERTY_ID_LISTSOURCE:
1471 if ( impl_doDesignSQLCommand_nothrow( _rxInspectorUI, nPropId ) )
1472 eResult = InteractiveSelectionResult_Pending;
1473 break;
1474 default:
1475 OSL_FAIL( "FormComponentPropertyHandler::onInteractivePropertySelection: request for a property which does not have dedicated UI!" );
1476 break;
1478 return eResult;
1481 namespace
1483 void lcl_rebuildAndResetCommand( const Reference< XObjectInspectorUI >& _rxInspectorUI, const Reference< XPropertyHandler >& _rxHandler )
1485 OSL_PRECOND( _rxInspectorUI.is(), "lcl_rebuildAndResetCommand: invalid BrowserUI!" );
1486 OSL_PRECOND( _rxHandler.is(), "lcl_rebuildAndResetCommand: invalid handler!" );
1487 _rxInspectorUI->rebuildPropertyUI( PROPERTY_COMMAND );
1488 _rxHandler->setPropertyValue( PROPERTY_COMMAND, Any( OUString() ) );
1492 void SAL_CALL FormComponentPropertyHandler::actuatingPropertyChanged( const OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit )
1494 if ( !_rxInspectorUI.is() )
1495 throw NullPointerException();
1497 ::osl::MutexGuard aGuard( m_aMutex );
1498 PropertyId nActuatingPropId( impl_getPropertyId_nothrow( _rActuatingPropertyName ) );
1500 std::vector< PropertyId > aDependentProperties;
1502 switch ( nActuatingPropId )
1504 // ----- EscapeProcessing -----
1505 case PROPERTY_ID_ESCAPE_PROCESSING:
1506 aDependentProperties.push_back( PROPERTY_ID_FILTER );
1507 aDependentProperties.push_back( PROPERTY_ID_SORT );
1508 break; // case PROPERTY_ID_ESCAPE_PROCESSING
1510 // ----- CommandType -----
1511 case PROPERTY_ID_COMMANDTYPE:
1512 // available commands (tables or queries) might have changed
1513 if ( !_bFirstTimeInit && m_bHaveCommand )
1514 lcl_rebuildAndResetCommand( _rxInspectorUI, this );
1515 aDependentProperties.push_back( PROPERTY_ID_COMMAND );
1516 break; // case PROPERTY_ID_COMMANDTYPE
1518 // ----- DataSourceName -----
1519 case PROPERTY_ID_DATASOURCE:
1520 // reset the connection, now that we have a new data source
1521 m_xRowSetConnection.clear();
1523 // available list source values (tables or queries) might have changed
1524 if ( !_bFirstTimeInit && m_bHaveListSource )
1525 _rxInspectorUI->rebuildPropertyUI( PROPERTY_LISTSOURCE );
1527 // available commands (tables or queries) might have changed
1528 if ( !_bFirstTimeInit && m_bHaveCommand )
1529 lcl_rebuildAndResetCommand( _rxInspectorUI, this );
1531 // Command also depends on DataSource
1532 aDependentProperties.push_back( PROPERTY_ID_COMMAND );
1533 [[fallthrough]];
1535 // ----- Command -----
1536 case PROPERTY_ID_COMMAND:
1537 aDependentProperties.push_back( PROPERTY_ID_FILTER );
1538 aDependentProperties.push_back( PROPERTY_ID_SORT );
1539 if ( m_bComponentIsSubForm )
1540 aDependentProperties.push_back( PROPERTY_ID_DETAILFIELDS );
1541 break;
1543 // ----- ListSourceType -----
1544 case PROPERTY_ID_LISTSOURCETYPE:
1545 if ( !_bFirstTimeInit && m_bHaveListSource )
1546 // available list source values (tables or queries) might have changed
1547 _rxInspectorUI->rebuildPropertyUI( PROPERTY_LISTSOURCE );
1548 aDependentProperties.push_back( PROPERTY_ID_STRINGITEMLIST );
1549 aDependentProperties.push_back( PROPERTY_ID_TYPEDITEMLIST );
1550 aDependentProperties.push_back( PROPERTY_ID_BOUNDCOLUMN );
1551 [[fallthrough]];
1553 // ----- StringItemList -----
1554 case PROPERTY_ID_STRINGITEMLIST:
1555 aDependentProperties.push_back( PROPERTY_ID_TYPEDITEMLIST );
1556 aDependentProperties.push_back( PROPERTY_ID_SELECTEDITEMS );
1557 aDependentProperties.push_back( PROPERTY_ID_DEFAULT_SELECT_SEQ );
1558 break;
1560 // ----- ListSource -----
1561 case PROPERTY_ID_LISTSOURCE:
1562 aDependentProperties.push_back( PROPERTY_ID_STRINGITEMLIST );
1563 aDependentProperties.push_back( PROPERTY_ID_TYPEDITEMLIST );
1564 break;
1566 // ----- DataField -----
1567 case PROPERTY_ID_CONTROLSOURCE:
1569 OUString sControlSource;
1570 _rNewValue >>= sControlSource;
1571 if ( impl_componentHasProperty_throw( PROPERTY_FILTERPROPOSAL ) )
1572 _rxInspectorUI->enablePropertyUI( PROPERTY_FILTERPROPOSAL, !sControlSource.isEmpty() );
1573 if ( impl_componentHasProperty_throw( PROPERTY_EMPTY_IS_NULL ) )
1574 _rxInspectorUI->enablePropertyUI( PROPERTY_EMPTY_IS_NULL, !sControlSource.isEmpty() );
1576 aDependentProperties.push_back( PROPERTY_ID_BOUNDCOLUMN );
1577 aDependentProperties.push_back( PROPERTY_ID_SCALEIMAGE );
1578 aDependentProperties.push_back( PROPERTY_ID_SCALE_MODE );
1579 aDependentProperties.push_back( PROPERTY_ID_INPUT_REQUIRED );
1581 break;
1583 case PROPERTY_ID_EMPTY_IS_NULL:
1584 aDependentProperties.push_back( PROPERTY_ID_INPUT_REQUIRED );
1585 break;
1587 // ----- SubmitEncoding -----
1588 case PROPERTY_ID_SUBMIT_ENCODING:
1590 FormSubmitEncoding eEncoding = FormSubmitEncoding_URL;
1591 if( ! (_rNewValue >>= eEncoding) )
1592 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_SUBMIT_ENCODING);
1593 _rxInspectorUI->enablePropertyUI( PROPERTY_SUBMIT_METHOD, eEncoding == FormSubmitEncoding_URL );
1595 break;
1597 // ----- Repeat -----
1598 case PROPERTY_ID_REPEAT:
1600 bool bIsRepeating = false;
1601 if( ! (_rNewValue >>= bIsRepeating) )
1602 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_REPEAT);
1603 _rxInspectorUI->enablePropertyUI( PROPERTY_REPEAT_DELAY, bIsRepeating );
1605 break;
1607 // ----- TabStop -----
1608 case PROPERTY_ID_TABSTOP:
1610 if ( !impl_componentHasProperty_throw( PROPERTY_TABINDEX ) )
1611 break;
1612 bool bHasTabStop = false;
1613 _rNewValue >>= bHasTabStop;
1614 _rxInspectorUI->enablePropertyUI( PROPERTY_TABINDEX, bHasTabStop );
1616 break;
1618 // ----- Border -----
1619 case PROPERTY_ID_BORDER:
1621 sal_Int16 nBordeType = VisualEffect::NONE;
1622 if( ! (_rNewValue >>= nBordeType) )
1623 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_BORDER);
1624 _rxInspectorUI->enablePropertyUI( PROPERTY_BORDERCOLOR, nBordeType == VisualEffect::FLAT );
1626 break;
1628 // ----- DropDown -----
1629 case PROPERTY_ID_DROPDOWN:
1631 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_LINECOUNT ) )
1633 bool bDropDown = true;
1634 _rNewValue >>= bDropDown;
1635 _rxInspectorUI->enablePropertyUI( PROPERTY_LINECOUNT, bDropDown );
1638 break;
1640 // ----- ImageURL -----
1641 case PROPERTY_ID_IMAGE_URL:
1643 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_IMAGEPOSITION ) )
1645 OUString sImageURL;
1646 if( ! (_rNewValue >>= sImageURL) )
1647 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_IMAGE_URL);
1648 _rxInspectorUI->enablePropertyUI( PROPERTY_IMAGEPOSITION, !sImageURL.isEmpty() );
1651 aDependentProperties.push_back( PROPERTY_ID_SCALEIMAGE );
1652 aDependentProperties.push_back( PROPERTY_ID_SCALE_MODE );
1654 break;
1656 // ----- ButtonType -----
1657 case PROPERTY_ID_BUTTONTYPE:
1659 FormButtonType eButtonType( FormButtonType_PUSH );
1660 if( ! (_rNewValue >>= eButtonType) )
1661 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_BUTTONTYPE);
1662 _rxInspectorUI->enablePropertyUI( PROPERTY_TARGET_URL, FormButtonType_URL == eButtonType );
1663 [[fallthrough]];
1666 // ----- TargetURL -----
1667 case PROPERTY_ID_TARGET_URL:
1668 aDependentProperties.push_back( PROPERTY_ID_TARGET_FRAME );
1669 break; // case PROPERTY_ID_TARGET_URL
1671 // ----- TriState -----
1672 case PROPERTY_ID_TRISTATE:
1673 if ( !_bFirstTimeInit )
1674 _rxInspectorUI->rebuildPropertyUI( m_eComponentClass == eFormControl ? OUString(PROPERTY_DEFAULT_STATE) : OUString(PROPERTY_STATE) );
1675 break; // case PROPERTY_ID_TRISTATE
1677 // ----- DecimalAccuracy -----
1678 case PROPERTY_ID_DECIMAL_ACCURACY:
1679 // ----- ShowThousandsSeparator -----
1680 case PROPERTY_ID_SHOWTHOUSANDSEP:
1682 bool bAccuracy = (PROPERTY_ID_DECIMAL_ACCURACY == nActuatingPropId);
1683 sal_uInt16 nNewDigits = 0;
1684 if ( bAccuracy )
1686 if( ! (_rNewValue >>= nNewDigits) )
1687 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_DECIMAL_ACCURACY);
1689 else
1691 bool bUseSep = false;
1692 if( ! (_rNewValue >>= bUseSep) )
1693 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_SHOWTHOUSANDSEP);
1696 // propagate the changes to the min/max/default fields
1697 OUString aAffectedProps[] = { OUString(PROPERTY_VALUE), OUString(PROPERTY_DEFAULT_VALUE), OUString(PROPERTY_VALUEMIN), OUString(PROPERTY_VALUEMAX) };
1698 for (const OUString & aAffectedProp : aAffectedProps)
1700 Reference< XPropertyControl > xControl;
1703 xControl = _rxInspectorUI->getPropertyControl( aAffectedProp );
1705 catch( const UnknownPropertyException& ) {}
1706 if ( xControl.is() )
1708 OFormattedNumericControl* pControl = dynamic_cast< OFormattedNumericControl* >( xControl.get() );
1709 DBG_ASSERT( pControl, "FormComponentPropertyHandler::actuatingPropertyChanged: invalid control!" );
1710 if (pControl)
1712 if ( bAccuracy )
1713 pControl->SetDecimalDigits( nNewDigits );
1718 break;
1720 // ----- FormatKey -----
1721 case PROPERTY_ID_FORMATKEY:
1723 FormatDescription aNewDesc;
1725 Reference< XNumberFormatsSupplier > xSupplier;
1726 if( ! (m_xComponent->getPropertyValue( PROPERTY_FORMATSSUPPLIER ) >>= xSupplier) )
1727 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_FORMATKEY);
1729 Reference< XUnoTunnel > xTunnel( xSupplier, UNO_QUERY );
1730 DBG_ASSERT(xTunnel.is(), "FormComponentPropertyHandler::actuatingPropertyChanged: xTunnel is invalid!");
1731 if ( xTunnel.is() )
1733 SvNumberFormatsSupplierObj* pSupplier = reinterpret_cast<SvNumberFormatsSupplierObj*>(xTunnel->getSomething(SvNumberFormatsSupplierObj::getUnoTunnelId()));
1734 // the same again
1736 aNewDesc.pSupplier = pSupplier;
1737 if ( !( _rNewValue >>= aNewDesc.nKey ) )
1738 aNewDesc.nKey = 0;
1740 // give each control which has to know this an own copy of the description
1741 OUString aFormattedPropertyControls[] = {
1742 OUString(PROPERTY_EFFECTIVE_MIN), OUString(PROPERTY_EFFECTIVE_MAX), OUString(PROPERTY_EFFECTIVE_DEFAULT), OUString(PROPERTY_EFFECTIVE_VALUE)
1744 for (const OUString & aFormattedPropertyControl : aFormattedPropertyControls)
1746 Reference< XPropertyControl > xControl;
1749 xControl = _rxInspectorUI->getPropertyControl( aFormattedPropertyControl );
1751 catch( const UnknownPropertyException& ) {}
1752 if ( xControl.is() )
1754 OFormattedNumericControl* pControl = dynamic_cast< OFormattedNumericControl* >( xControl.get() );
1755 DBG_ASSERT( pControl, "FormComponentPropertyHandler::actuatingPropertyChanged: invalid control!" );
1756 if ( pControl )
1757 pControl->SetFormatDescription( aNewDesc );
1762 break;
1764 case PROPERTY_ID_TOGGLE:
1766 bool bIsToggleButton = false;
1767 if( ! (_rNewValue >>= bIsToggleButton) )
1768 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_TOGGLE);
1769 _rxInspectorUI->enablePropertyUI( PROPERTY_DEFAULT_STATE, bIsToggleButton );
1771 break;
1772 case -1:
1773 throw RuntimeException();
1774 break;
1775 default:
1776 OSL_FAIL( "FormComponentPropertyHandler::actuatingPropertyChanged: did not register for this property!" );
1777 break;
1779 } // switch ( nActuatingPropId )
1781 for (auto const& dependentProperty : aDependentProperties)
1783 if ( impl_isSupportedProperty_nothrow(dependentProperty) )
1784 impl_updateDependentProperty_nothrow(dependentProperty, _rxInspectorUI);
1788 void FormComponentPropertyHandler::impl_updateDependentProperty_nothrow( PropertyId _nPropId, const Reference< XObjectInspectorUI >& _rxInspectorUI ) const
1792 switch ( _nPropId )
1794 // ----- StringItemList -----
1795 case PROPERTY_ID_STRINGITEMLIST:
1797 ListSourceType eLSType = ListSourceType_VALUELIST;
1798 if( ! (impl_getPropertyValue_throw( PROPERTY_LISTSOURCETYPE ) >>= eLSType) )
1799 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " << PROPERTY_LISTSOURCETYPE);
1801 OUString sListSource;
1803 Sequence< OUString > aListSource;
1804 Any aListSourceValue( impl_getPropertyValue_throw( PROPERTY_LISTSOURCE ) );
1805 if ( aListSourceValue >>= aListSource )
1807 if ( aListSource.hasElements() )
1808 sListSource = aListSource[0];
1810 else
1811 if( ! (aListSourceValue >>= sListSource) )
1812 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " << PROPERTY_LISTSOURCE);
1815 bool bIsEnabled = ( ( eLSType == ListSourceType_VALUELIST )
1816 || ( sListSource.isEmpty() )
1818 _rxInspectorUI->enablePropertyUI( PROPERTY_STRINGITEMLIST, bIsEnabled );
1820 break; // case PROPERTY_ID_STRINGITEMLIST
1822 // ----- TypedItemList -----
1823 case PROPERTY_ID_TYPEDITEMLIST:
1825 /* TODO: anything? */
1827 break; // case PROPERTY_ID_TYPEDITEMLIST
1829 // ----- BoundColumn -----
1830 case PROPERTY_ID_BOUNDCOLUMN:
1832 ListSourceType eLSType = ListSourceType_VALUELIST;
1833 if( ! (impl_getPropertyValue_throw( PROPERTY_LISTSOURCETYPE ) >>= eLSType) )
1834 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " << PROPERTY_LISTSOURCETYPE);
1836 _rxInspectorUI->enablePropertyUI( PROPERTY_BOUNDCOLUMN,
1837 ( eLSType != ListSourceType_VALUELIST )
1840 break; // case PROPERTY_ID_BOUNDCOLUMN
1842 // ----- ScaleImage, ScaleMode -----
1843 case PROPERTY_ID_SCALEIMAGE:
1844 case PROPERTY_ID_SCALE_MODE:
1846 OUString sControlSource;
1847 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_CONTROLSOURCE ) )
1848 impl_getPropertyValue_throw( PROPERTY_CONTROLSOURCE ) >>= sControlSource;
1850 OUString sImageURL;
1851 impl_getPropertyValue_throw( PROPERTY_IMAGE_URL ) >>= sImageURL;
1853 _rxInspectorUI->enablePropertyUI( impl_getPropertyNameFromId_nothrow( _nPropId ),
1854 ( !sControlSource.isEmpty() ) || ( !sImageURL.isEmpty() )
1857 break; // case PROPERTY_ID_SCALEIMAGE, PROPERTY_ID_SCALE_MODE
1859 // ----- InputRequired -----
1860 case PROPERTY_ID_INPUT_REQUIRED:
1862 OUString sControlSource;
1863 if( ! (impl_getPropertyValue_throw( PROPERTY_CONTROLSOURCE ) >>= sControlSource) )
1864 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " << PROPERTY_CONTROLSOURCE);
1866 bool bEmptyIsNULL = false;
1867 bool bHasEmptyIsNULL = impl_componentHasProperty_throw( PROPERTY_EMPTY_IS_NULL );
1868 if ( bHasEmptyIsNULL )
1869 if( ! (impl_getPropertyValue_throw( PROPERTY_EMPTY_IS_NULL ) >>= bEmptyIsNULL) )
1870 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " << PROPERTY_EMPTY_IS_NULL);
1872 // if the control is not bound to a DB field, there is no sense in having the "Input required"
1873 // property
1874 // Also, if an empty input of this control are *not* written as NULL, but as empty strings,
1875 // then "Input required" does not make sense, too (since there's always an input, even if the control
1876 // is empty).
1877 _rxInspectorUI->enablePropertyUI( PROPERTY_INPUT_REQUIRED,
1878 ( !sControlSource.isEmpty() ) && ( !bHasEmptyIsNULL || bEmptyIsNULL )
1881 break;
1883 // ----- SelectedItems, DefaultSelection -----
1884 case PROPERTY_ID_SELECTEDITEMS:
1885 case PROPERTY_ID_DEFAULT_SELECT_SEQ:
1887 Sequence< OUString > aEntries;
1888 impl_getPropertyValue_throw( PROPERTY_STRINGITEMLIST ) >>= aEntries;
1889 bool isEnabled = aEntries.hasElements();
1891 if ( ( m_nClassId == FormComponentType::LISTBOX ) && ( m_eComponentClass == eFormControl ) )
1893 ListSourceType eLSType = ListSourceType_VALUELIST;
1894 impl_getPropertyValue_throw( PROPERTY_LISTSOURCETYPE ) >>= eLSType;
1895 isEnabled &= ( eLSType == ListSourceType_VALUELIST );
1897 _rxInspectorUI->enablePropertyUIElements( impl_getPropertyNameFromId_nothrow( _nPropId ),
1898 PropertyLineElement::PrimaryButton, isEnabled );
1900 break; // case PROPERTY_ID_DEFAULT_SELECT_SEQ
1902 // ----- TargetFrame ------
1903 case PROPERTY_ID_TARGET_FRAME:
1905 OUString sTargetURL;
1906 impl_getPropertyValue_throw( PROPERTY_TARGET_URL ) >>= sTargetURL;
1907 FormButtonType eButtonType( FormButtonType_URL );
1908 if ( 0 != m_nClassId )
1910 if( ! (impl_getPropertyValue_throw( PROPERTY_BUTTONTYPE ) >>= eButtonType) )
1911 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " << PROPERTY_BUTTONTYPE);
1913 // if m_nClassId is 0, then we're inspecting a form. In this case, eButtonType is always
1914 // FormButtonType_URL here
1915 _rxInspectorUI->enablePropertyUI( PROPERTY_TARGET_FRAME,
1916 ( eButtonType == FormButtonType_URL ) && ( !sTargetURL.isEmpty() )
1919 break;
1921 // ----- Order ------
1922 case PROPERTY_ID_SORT:
1923 // ----- Filter ------
1924 case PROPERTY_ID_FILTER:
1926 Reference< XConnection > xConnection;
1927 bool bAllowEmptyDS = ::dbtools::isEmbeddedInDatabase( m_xComponent, xConnection );
1929 // if there's no escape processing, we cannot enter any values for this property
1930 bool bDoEscapeProcessing( false );
1931 impl_getPropertyValue_throw( PROPERTY_ESCAPE_PROCESSING ) >>= bDoEscapeProcessing;
1932 _rxInspectorUI->enablePropertyUI(
1933 impl_getPropertyNameFromId_nothrow( _nPropId ),
1934 bDoEscapeProcessing
1937 // also care for the browse button - enabled if we have escape processing, and a valid
1938 // data source signature
1939 _rxInspectorUI->enablePropertyUIElements(
1940 impl_getPropertyNameFromId_nothrow( _nPropId ),
1941 PropertyLineElement::PrimaryButton,
1942 impl_hasValidDataSourceSignature_nothrow( m_xComponent, bAllowEmptyDS )
1943 && bDoEscapeProcessing
1946 break; // case PROPERTY_ID_FILTER:
1948 // ----- Command -----
1949 case PROPERTY_ID_COMMAND:
1951 sal_Int32 nCommandType( CommandType::COMMAND );
1952 if( ! (impl_getPropertyValue_throw( PROPERTY_COMMANDTYPE ) >>= nCommandType) )
1953 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " << PROPERTY_COMMANDTYPE);
1955 impl_ensureRowsetConnection_nothrow();
1956 Reference< XConnection > xConnection = m_xRowSetConnection.getTyped();
1957 bool bAllowEmptyDS = false;
1958 if ( !xConnection.is() )
1959 bAllowEmptyDS = ::dbtools::isEmbeddedInDatabase( m_xComponent, xConnection );
1961 bool doEnable = ( nCommandType == CommandType::COMMAND )
1962 && ( m_xRowSetConnection.is()
1963 || xConnection.is()
1964 || impl_hasValidDataSourceSignature_nothrow( m_xComponent, bAllowEmptyDS)
1967 _rxInspectorUI->enablePropertyUIElements(
1968 PROPERTY_COMMAND,
1969 PropertyLineElement::PrimaryButton,
1970 doEnable
1973 break; // case PROPERTY_ID_COMMAND
1975 // ----- DetailFields -----
1976 case PROPERTY_ID_DETAILFIELDS:
1978 Reference< XConnection > xConnection;
1979 bool bAllowEmptyDS = ::dbtools::isEmbeddedInDatabase( m_xComponent, xConnection );
1981 // both our current form, and its parent form, need to have a valid
1982 // data source signature
1983 bool bDoEnableMasterDetailFields =
1984 impl_hasValidDataSourceSignature_nothrow( m_xComponent, bAllowEmptyDS )
1985 && impl_hasValidDataSourceSignature_nothrow( Reference< XPropertySet >( m_xObjectParent, UNO_QUERY ), bAllowEmptyDS );
1987 // in opposite to the other properties, here in real *two* properties are
1988 // affected
1989 _rxInspectorUI->enablePropertyUIElements( PROPERTY_DETAILFIELDS, PropertyLineElement::PrimaryButton, bDoEnableMasterDetailFields );
1990 _rxInspectorUI->enablePropertyUIElements( PROPERTY_MASTERFIELDS, PropertyLineElement::PrimaryButton, bDoEnableMasterDetailFields );
1992 break;
1994 default:
1995 OSL_FAIL( "FormComponentPropertyHandler::impl_updateDependentProperty_nothrow: unexpected property to update!" );
1996 break;
1998 } // switch
2000 catch( const Exception& )
2002 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "FormComponentPropertyHandler::impl_updateDependentProperty_nothrow" );
2006 void SAL_CALL FormComponentPropertyHandler::disposing()
2008 PropertyHandlerComponent::disposing();
2009 if ( m_xCommandDesigner.is() && m_xCommandDesigner->isActive() )
2010 m_xCommandDesigner->dispose();
2013 sal_Bool SAL_CALL FormComponentPropertyHandler::suspend( sal_Bool _bSuspend )
2015 ::osl::MutexGuard aGuard( m_aMutex );
2016 if ( _bSuspend )
2017 if ( m_xCommandDesigner.is() && m_xCommandDesigner->isActive() )
2018 return m_xCommandDesigner->suspend();
2019 return true;
2022 void FormComponentPropertyHandler::onNewComponent()
2024 PropertyHandlerComponent::onNewComponent();
2025 if ( !m_xComponentPropertyInfo.is() && m_xComponent.is() )
2026 throw NullPointerException();
2028 m_xPropertyState.set( m_xComponent, UNO_QUERY );
2029 m_eComponentClass = eUnknown;
2030 m_bComponentIsSubForm = m_bHaveListSource = m_bHaveCommand = false;
2031 m_nClassId = 0;
2035 // component class
2036 m_eComponentClass = eUnknown;
2038 if ( impl_componentHasProperty_throw( PROPERTY_WIDTH )
2039 && impl_componentHasProperty_throw( PROPERTY_HEIGHT )
2040 && impl_componentHasProperty_throw( PROPERTY_POSITIONX )
2041 && impl_componentHasProperty_throw( PROPERTY_POSITIONY )
2042 && impl_componentHasProperty_throw( PROPERTY_STEP )
2043 && impl_componentHasProperty_throw( PROPERTY_TABINDEX )
2046 m_eComponentClass = eDialogControl;
2048 else
2050 m_eComponentClass = eFormControl;
2054 // (database) sub form?
2055 Reference< XForm > xAsForm( m_xComponent, UNO_QUERY );
2056 if ( xAsForm.is() )
2058 Reference< XForm > xFormsParent( xAsForm->getParent(), css::uno::UNO_QUERY );
2059 m_bComponentIsSubForm = xFormsParent.is();
2063 // ClassId
2064 Reference< XChild > xCompAsChild( m_xComponent, UNO_QUERY );
2065 if ( xCompAsChild.is() )
2066 m_xObjectParent = xCompAsChild->getParent();
2069 // ClassId
2070 impl_classifyControlModel_throw();
2072 catch( const RuntimeException& )
2074 throw;
2076 catch( const Exception& )
2078 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "FormComponentPropertyHandler::onNewComponent" );
2082 void FormComponentPropertyHandler::impl_classifyControlModel_throw( )
2084 if ( impl_componentHasProperty_throw( PROPERTY_CLASSID ) )
2086 if( ! (m_xComponent->getPropertyValue( PROPERTY_CLASSID ) >>= m_nClassId) )
2087 SAL_WARN("extensions.propctrlr", "impl_classifyControlModel_throw: unable to get property " << PROPERTY_CLASSID);
2089 else if ( eDialogControl == m_eComponentClass )
2091 Reference< XServiceInfo > xServiceInfo( m_xComponent, UNO_QUERY );
2092 if ( xServiceInfo.is() )
2094 // it's a control model, and can tell about it's supported services
2095 m_nClassId = FormComponentType::CONTROL;
2097 const char* aControlModelServiceNames[] =
2099 "UnoControlButtonModel",
2100 "UnoControlCheckBoxModel",
2101 "UnoControlComboBoxModel",
2102 "UnoControlCurrencyFieldModel",
2103 "UnoControlDateFieldModel",
2104 "UnoControlEditModel",
2105 "UnoControlFileControlModel",
2106 "UnoControlFixedTextModel",
2107 "UnoControlGroupBoxModel",
2108 "UnoControlImageControlModel",
2109 "UnoControlListBoxModel",
2110 "UnoControlNumericFieldModel",
2111 "UnoControlPatternFieldModel",
2112 "UnoControlRadioButtonModel",
2113 "UnoControlScrollBarModel",
2114 "UnoControlSpinButtonModel",
2115 "UnoControlTimeFieldModel",
2117 "UnoControlFixedLineModel",
2118 "UnoControlFormattedFieldModel",
2119 "UnoControlProgressBarModel"
2121 const sal_Int16 nClassIDs[] =
2123 FormComponentType::COMMANDBUTTON,
2124 FormComponentType::CHECKBOX,
2125 FormComponentType::COMBOBOX,
2126 FormComponentType::CURRENCYFIELD,
2127 FormComponentType::DATEFIELD,
2128 FormComponentType::TEXTFIELD,
2129 FormComponentType::FILECONTROL,
2130 FormComponentType::FIXEDTEXT,
2131 FormComponentType::GROUPBOX,
2132 FormComponentType::IMAGECONTROL,
2133 FormComponentType::LISTBOX,
2134 FormComponentType::NUMERICFIELD,
2135 FormComponentType::PATTERNFIELD,
2136 FormComponentType::RADIOBUTTON,
2137 FormComponentType::SCROLLBAR,
2138 FormComponentType::SPINBUTTON,
2139 FormComponentType::TIMEFIELD,
2141 ControlType::FIXEDLINE,
2142 ControlType::FORMATTEDFIELD,
2143 ControlType::PROGRESSBAR
2146 sal_Int32 nKnownControlTypes = SAL_N_ELEMENTS( aControlModelServiceNames );
2147 OSL_ENSURE( nKnownControlTypes == SAL_N_ELEMENTS( nClassIDs ),
2148 "FormComponentPropertyHandler::impl_classifyControlModel_throw: inconsistence" );
2150 for ( sal_Int32 i = 0; i < nKnownControlTypes; ++i )
2152 OUString sServiceName = "com.sun.star.awt." +
2153 OUString::createFromAscii( aControlModelServiceNames[ i ] );
2155 if ( xServiceInfo->supportsService( sServiceName ) )
2157 m_nClassId = nClassIDs[ i ];
2158 break;
2165 void FormComponentPropertyHandler::impl_normalizePropertyValue_nothrow( Any& _rValue, PropertyId _nPropId ) const
2167 switch ( _nPropId )
2169 case PROPERTY_ID_TABSTOP:
2170 if ( !_rValue.hasValue() )
2172 switch ( m_nClassId )
2174 case FormComponentType::COMMANDBUTTON:
2175 case FormComponentType::RADIOBUTTON:
2176 case FormComponentType::CHECKBOX:
2177 case FormComponentType::TEXTFIELD:
2178 case FormComponentType::LISTBOX:
2179 case FormComponentType::COMBOBOX:
2180 case FormComponentType::FILECONTROL:
2181 case FormComponentType::DATEFIELD:
2182 case FormComponentType::TIMEFIELD:
2183 case FormComponentType::NUMERICFIELD:
2184 case ControlType::FORMATTEDFIELD:
2185 case FormComponentType::CURRENCYFIELD:
2186 case FormComponentType::PATTERNFIELD:
2187 _rValue <<= true;
2188 break;
2189 default:
2190 _rValue <<= false;
2191 break;
2194 break;
2198 bool FormComponentPropertyHandler::isReportModel() const
2200 Reference<XModel> xModel(impl_getContextDocument_nothrow());
2201 Reference<XReportDefinition> xReportDef(xModel, css::uno::UNO_QUERY);
2202 return xReportDef.is();
2205 bool FormComponentPropertyHandler::impl_shouldExcludeProperty_nothrow( const Property& _rProperty ) const
2207 OSL_ENSURE( _rProperty.Handle == m_pInfoService->getPropertyId( _rProperty.Name ),
2208 "FormComponentPropertyHandler::impl_shouldExcludeProperty_nothrow: inconsistency in the property!" );
2210 if ( _rProperty.Handle == PROPERTY_ID_CONTROLLABEL )
2211 // prevent that this is caught below
2212 return false;
2214 if ( ( _rProperty.Type.getTypeClass() == TypeClass_INTERFACE )
2215 || ( _rProperty.Type.getTypeClass() == TypeClass_UNKNOWN )
2217 return true;
2219 if ( ( _rProperty.Attributes & PropertyAttribute::TRANSIENT ) && ( m_eComponentClass != eDialogControl ) )
2220 // strange enough, dialog controls declare a lot of their properties as transient
2221 return true;
2223 if ( _rProperty.Attributes & PropertyAttribute::READONLY )
2224 return true;
2226 switch ( _rProperty.Handle )
2228 case PROPERTY_ID_MASTERFIELDS:
2229 case PROPERTY_ID_DETAILFIELDS:
2230 if ( !m_bComponentIsSubForm )
2231 // no master and detail fields for forms which are no sub forms
2232 return true;
2233 break;
2235 case PROPERTY_ID_DATASOURCE:
2237 // don't show DataSource if the component is part of an embedded form document
2238 Reference< XConnection > xConn;
2239 if ( isEmbeddedInDatabase( m_xComponent, xConn ) )
2240 return true;
2242 break;
2244 case PROPERTY_ID_TEXT:
2245 // don't show the "Text" property of formatted fields
2246 if ( ControlType::FORMATTEDFIELD == m_nClassId )
2247 return true;
2248 break;
2250 case PROPERTY_ID_FORMATKEY:
2251 case PROPERTY_ID_EFFECTIVE_MIN:
2252 case PROPERTY_ID_EFFECTIVE_MAX:
2253 case PROPERTY_ID_EFFECTIVE_DEFAULT:
2254 case PROPERTY_ID_EFFECTIVE_VALUE:
2255 // only if the set has a formats supplier, too
2256 if ( !impl_componentHasProperty_throw( PROPERTY_FORMATSSUPPLIER ) )
2257 return true;
2258 // (form) date and time fields also have a formats supplier, but the format itself
2259 // is reflected in another property
2260 if ( ( FormComponentType::DATEFIELD == m_nClassId )
2261 || ( FormComponentType::TIMEFIELD == m_nClassId )
2263 return true;
2264 break;
2266 case PROPERTY_ID_SCALEIMAGE:
2267 if ( impl_componentHasProperty_throw( PROPERTY_SCALE_MODE ) )
2268 // ScaleImage is superseded by ScaleMode
2269 return true;
2270 break;
2272 case PROPERTY_ID_WRITING_MODE:
2273 if ( !SvtCTLOptions::IsCTLFontEnabled() )
2274 return true;
2275 break;
2278 sal_uInt32 nPropertyUIFlags = m_pInfoService->getPropertyUIFlags( _rProperty.Handle );
2280 // don't show experimental properties unless allowed to do so
2281 if ( ( nPropertyUIFlags & PROP_FLAG_EXPERIMENTAL ) != 0 )
2282 return true;
2284 // no data properties if no Base is installed.
2285 if ( ( nPropertyUIFlags & PROP_FLAG_DATA_PROPERTY ) != 0 )
2286 if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
2287 return true;
2289 if ((nPropertyUIFlags & PROP_FLAG_REPORT_INVISIBLE) != 0 && isReportModel())
2290 return true;
2292 return false;
2295 Reference< XRowSet > FormComponentPropertyHandler::impl_getRowSet_throw( ) const
2297 Reference< XRowSet > xRowSet = m_xRowSet;
2298 if ( !xRowSet.is() )
2300 xRowSet.set( m_xComponent, UNO_QUERY );
2301 if ( !xRowSet.is() )
2303 xRowSet.set( m_xObjectParent, UNO_QUERY );
2304 if ( !xRowSet.is() )
2306 // are we inspecting a grid column?
2307 if (Reference< XGridColumnFactory >( m_xObjectParent, UNO_QUERY) .is())
2308 { // yes
2309 Reference< XChild > xParentAsChild( m_xObjectParent, UNO_QUERY );
2310 if ( xParentAsChild.is() )
2311 xRowSet.set( xParentAsChild->getParent(), UNO_QUERY );
2314 if ( !xRowSet.is() )
2315 xRowSet = m_xRowSet;
2317 DBG_ASSERT( xRowSet.is(), "FormComponentPropertyHandler::impl_getRowSet_throw: could not obtain the rowset for the introspectee!" );
2319 return xRowSet;
2323 Reference< XRowSet > FormComponentPropertyHandler::impl_getRowSet_nothrow( ) const
2325 Reference< XRowSet > xReturn;
2328 xReturn = impl_getRowSet_throw();
2330 catch( const Exception& )
2332 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "FormComponentPropertyHandler::impl_getRowSet_nothrow" );
2334 return xReturn;
2338 void FormComponentPropertyHandler::impl_initFieldList_nothrow( std::vector< OUString >& _rFieldNames ) const
2340 clearContainer( _rFieldNames );
2343 weld::WaitObject aWaitCursor(impl_getDefaultDialogFrame_nothrow());
2345 // get the form of the control we're inspecting
2346 Reference< XPropertySet > xFormSet( impl_getRowSet_throw(), UNO_QUERY );
2347 if ( !xFormSet.is() )
2348 return;
2350 OUString sObjectName;
2351 if( ! (xFormSet->getPropertyValue( PROPERTY_COMMAND ) >>= sObjectName) )
2352 SAL_WARN("extensions.propctrlr", "impl_initFieldList_nothrow: unable to get property " << PROPERTY_COMMAND);
2353 // when there is no command we don't need to ask for columns
2354 if ( !sObjectName.isEmpty() && impl_ensureRowsetConnection_nothrow() )
2356 OUString aDatabaseName;
2357 if( ! (xFormSet->getPropertyValue( PROPERTY_DATASOURCE ) >>= aDatabaseName) )
2358 SAL_WARN("extensions.propctrlr", "impl_initFieldList_nothrow: unable to get property " << PROPERTY_DATASOURCE);
2359 sal_Int32 nObjectType = CommandType::COMMAND;
2360 if( ! (xFormSet->getPropertyValue( PROPERTY_COMMANDTYPE ) >>= nObjectType) )
2361 SAL_WARN("extensions.propctrlr", "impl_initFieldList_nothrow: unable to get property " << PROPERTY_COMMANDTYPE);
2363 const Sequence<OUString> aNames = ::dbtools::getFieldNamesByCommandDescriptor( m_xRowSetConnection, nObjectType, sObjectName );
2364 _rFieldNames.insert( _rFieldNames.end(), aNames.begin(), aNames.end() );
2367 catch (const Exception&)
2369 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "FormComponentPropertyHandler::impl_initFieldList_nothrow" );
2373 void FormComponentPropertyHandler::impl_displaySQLError_nothrow( const ::dbtools::SQLExceptionInfo& _rErrorDescriptor ) const
2375 auto pTopLevel = impl_getDefaultDialogFrame_nothrow();
2376 ::dbtools::showError(_rErrorDescriptor, pTopLevel ? pTopLevel->GetXWindow() : nullptr, m_xContext);
2379 bool FormComponentPropertyHandler::impl_ensureRowsetConnection_nothrow() const
2381 if ( !m_xRowSetConnection.is() )
2383 uno::Reference<sdbc::XConnection> xConnection;
2384 Any any = m_xContext->getValueByName( "ActiveConnection" );
2385 any >>= xConnection;
2386 m_xRowSetConnection.reset(xConnection,::dbtools::SharedConnection::NoTakeOwnership);
2388 if ( m_xRowSetConnection.is() )
2389 return true;
2391 Reference< XRowSet > xRowSet( impl_getRowSet_throw() );
2392 Reference< XPropertySet > xRowSetProps( xRowSet, UNO_QUERY );
2394 // connect the row set - this is delegated to elsewhere - while observing errors
2395 SQLExceptionInfo aError;
2398 if ( xRowSetProps.is() )
2400 weld::WaitObject aWaitCursor(impl_getDefaultDialogFrame_nothrow());
2401 m_xRowSetConnection = ::dbtools::ensureRowSetConnection( xRowSet, m_xContext, nullptr );
2404 catch ( const SQLException& ) { aError = SQLExceptionInfo( ::cppu::getCaughtException() ); }
2405 catch ( const WrappedTargetException& e ) { aError = SQLExceptionInfo( e.TargetException ); }
2406 catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION("extensions.propctrlr"); }
2408 // report errors, if necessary
2409 if ( aError.isValid() )
2411 OUString sDataSourceName;
2414 xRowSetProps->getPropertyValue( PROPERTY_DATASOURCE ) >>= sDataSourceName;
2416 catch( const Exception& )
2418 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "FormComponentPropertyHandler::impl_ensureRowsetConnection_nothrow: caught an exception during error handling!" );
2420 // additional info about what happened
2421 INetURLObject aParser( sDataSourceName );
2422 if ( aParser.GetProtocol() != INetProtocol::NotValid )
2423 sDataSourceName = aParser.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
2424 OUString sInfo(PcrRes(RID_STR_UNABLETOCONNECT).replaceAll("$name$", sDataSourceName));
2425 SQLContext aContext;
2426 aContext.Message = sInfo;
2427 aContext.NextException = aError.get();
2428 impl_displaySQLError_nothrow( aContext );
2431 return m_xRowSetConnection.is();
2435 void FormComponentPropertyHandler::impl_describeCursorSource_nothrow( LineDescriptor& _out_rProperty, const Reference< XPropertyControlFactory >& _rxControlFactory ) const
2439 weld::WaitObject aWaitCursor(impl_getDefaultDialogFrame_nothrow());
2442 // Set the UI data
2443 _out_rProperty.DisplayName = m_pInfoService->getPropertyTranslation( PROPERTY_ID_COMMAND );
2445 _out_rProperty.HelpURL = HelpIdUrl::getHelpURL( m_pInfoService->getPropertyHelpId( PROPERTY_ID_COMMAND ) );
2446 _out_rProperty.PrimaryButtonId = UID_PROP_DLG_SQLCOMMAND;
2449 sal_Int32 nCommandType = CommandType::COMMAND;
2450 impl_getPropertyValue_throw( PROPERTY_COMMANDTYPE ) >>= nCommandType;
2452 switch ( nCommandType )
2454 case CommandType::TABLE:
2455 case CommandType::QUERY:
2457 std::vector< OUString > aNames;
2458 if ( impl_ensureRowsetConnection_nothrow() )
2460 if ( nCommandType == CommandType::TABLE )
2461 impl_fillTableNames_throw( aNames );
2462 else
2463 impl_fillQueryNames_throw( aNames );
2465 _out_rProperty.Control = PropertyHandlerHelper::createComboBoxControl( _rxControlFactory, std::move(aNames), true );
2467 break;
2469 default:
2470 _out_rProperty.Control = _rxControlFactory->createPropertyControl( PropertyControlType::MultiLineTextField, false );
2471 break;
2474 catch (const Exception&)
2476 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "FormComponentPropertyHandler::impl_describeCursorSource_nothrow");
2481 void FormComponentPropertyHandler::impl_fillTableNames_throw( std::vector< OUString >& _out_rNames ) const
2483 OSL_PRECOND( m_xRowSetConnection.is(), "FormComponentPropertyHandler::impl_fillTableNames_throw: need a connection!" );
2484 _out_rNames.resize( 0 );
2486 Reference< XTablesSupplier > xSupplyTables( m_xRowSetConnection, UNO_QUERY );
2487 Reference< XNameAccess > xTableNames;
2488 if ( xSupplyTables.is() )
2489 xTableNames = xSupplyTables->getTables();
2490 DBG_ASSERT( xTableNames.is(), "FormComponentPropertyHandler::impl_fillTableNames_throw: no way to obtain the tables of the connection!" );
2491 if ( !xTableNames.is() )
2492 return;
2494 const Sequence<OUString> aNames = xTableNames->getElementNames();
2495 _out_rNames.insert( _out_rNames.end(), aNames.begin(), aNames.end() );
2499 void FormComponentPropertyHandler::impl_fillQueryNames_throw( std::vector< OUString >& _out_rNames ) const
2501 OSL_PRECOND( m_xRowSetConnection.is(), "FormComponentPropertyHandler::impl_fillQueryNames_throw: need a connection!" );
2502 _out_rNames.resize( 0 );
2504 Reference< XQueriesSupplier > xSupplyQueries( m_xRowSetConnection, UNO_QUERY );
2505 Reference< XNameAccess > xQueryNames;
2506 if ( xSupplyQueries.is() )
2508 xQueryNames = xSupplyQueries->getQueries();
2509 impl_fillQueryNames_throw(xQueryNames,_out_rNames);
2513 void FormComponentPropertyHandler::impl_fillQueryNames_throw( const Reference< XNameAccess >& _xQueryNames,std::vector< OUString >& _out_rNames,std::u16string_view _sName ) const
2515 DBG_ASSERT( _xQueryNames.is(), "FormComponentPropertyHandler::impl_fillQueryNames_throw: no way to obtain the queries of the connection!" );
2516 if ( !_xQueryNames.is() )
2517 return;
2519 bool bAdd = !_sName.empty();
2521 const Sequence<OUString> aQueryNames =_xQueryNames->getElementNames();
2522 for ( const OUString& rQueryName : aQueryNames )
2524 OUStringBuffer sTemp;
2525 if ( bAdd )
2527 sTemp.append(OUString::Concat(_sName) + "/");
2529 sTemp.append(rQueryName);
2530 Reference< XNameAccess > xSubQueries(_xQueryNames->getByName(rQueryName),UNO_QUERY);
2531 if ( xSubQueries.is() )
2532 impl_fillQueryNames_throw(xSubQueries,_out_rNames,sTemp);
2533 else
2534 _out_rNames.push_back( sTemp.makeStringAndClear() );
2539 void FormComponentPropertyHandler::impl_describeListSourceUI_throw( LineDescriptor& _out_rDescriptor, const Reference< XPropertyControlFactory >& _rxControlFactory ) const
2541 OSL_PRECOND( m_xComponent.is(), "FormComponentPropertyHandler::impl_describeListSourceUI_throw: no component!" );
2544 // read out ListSourceTypes
2545 Any aListSourceType( m_xComponent->getPropertyValue( PROPERTY_LISTSOURCETYPE ) );
2547 sal_Int32 nListSourceType = sal_Int32(ListSourceType_VALUELIST);
2548 ::cppu::enum2int( nListSourceType, aListSourceType );
2549 ListSourceType eListSourceType = static_cast<ListSourceType>(nListSourceType);
2551 _out_rDescriptor.DisplayName = m_pInfoService->getPropertyTranslation( PROPERTY_ID_LISTSOURCE );
2552 _out_rDescriptor.HelpURL = HelpIdUrl::getHelpURL( m_pInfoService->getPropertyHelpId( PROPERTY_ID_LISTSOURCE ) );
2555 // set enums
2556 switch( eListSourceType )
2558 case ListSourceType_VALUELIST:
2559 _out_rDescriptor.Control = _rxControlFactory->createPropertyControl( PropertyControlType::StringListField, false );
2560 break;
2562 case ListSourceType_TABLEFIELDS:
2563 case ListSourceType_TABLE:
2564 case ListSourceType_QUERY:
2566 std::vector< OUString > aListEntries;
2567 if ( impl_ensureRowsetConnection_nothrow() )
2569 if ( eListSourceType == ListSourceType_QUERY )
2570 impl_fillQueryNames_throw( aListEntries );
2571 else
2572 impl_fillTableNames_throw( aListEntries );
2574 _out_rDescriptor.Control = PropertyHandlerHelper::createComboBoxControl( _rxControlFactory, std::move(aListEntries), false );
2576 break;
2577 case ListSourceType_SQL:
2578 case ListSourceType_SQLPASSTHROUGH:
2579 impl_ensureRowsetConnection_nothrow();
2580 _out_rDescriptor.HasPrimaryButton = m_xRowSetConnection.is();
2581 break;
2582 default: break;
2586 bool FormComponentPropertyHandler::impl_dialogListSelection_nothrow( const OUString& _rProperty, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2588 OSL_PRECOND(m_pInfoService, "FormComponentPropertyHandler::impl_dialogListSelection_"
2589 "nothrow: no property meta data!");
2591 OUString sPropertyUIName( m_pInfoService->getPropertyTranslation( m_pInfoService->getPropertyId( _rProperty ) ) );
2592 ListSelectionDialog aDialog(impl_getDefaultDialogFrame_nothrow(), m_xComponent, _rProperty, sPropertyUIName);
2593 _rClearBeforeDialog.clear();
2594 return ( RET_OK == aDialog.run() );
2597 bool FormComponentPropertyHandler::impl_dialogFilterOrSort_nothrow( bool _bFilter, OUString& _out_rSelectedClause, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2599 OSL_PRECOND( Reference< XRowSet >( m_xComponent, UNO_QUERY ).is(),
2600 "FormComponentPropertyHandler::impl_dialogFilterOrSort_nothrow: to be called for forms only!" );
2602 _out_rSelectedClause.clear();
2603 bool bSuccess = false;
2604 SQLExceptionInfo aErrorInfo;
2607 if ( !impl_ensureRowsetConnection_nothrow() )
2608 return false;
2610 // get a composer for the statement which the form is currently based on
2611 Reference< XSingleSelectQueryComposer > xComposer( ::dbtools::getCurrentSettingsComposer( m_xComponent, m_xContext, nullptr ) );
2612 OSL_ENSURE( xComposer.is(), "FormComponentPropertyHandler::impl_dialogFilterOrSort_nothrow: could not obtain a composer!" );
2613 if ( !xComposer.is() )
2614 return false;
2616 OUString sPropertyUIName( m_pInfoService->getPropertyTranslation( _bFilter ? PROPERTY_ID_FILTER : PROPERTY_ID_SORT ) );
2618 // create the dialog
2619 Reference< XExecutableDialog > xDialog;
2620 if ( _bFilter)
2622 xDialog.set( sdb::FilterDialog::createDefault(m_xContext) );
2624 else
2626 xDialog.set( sdb::OrderDialog::createDefault(m_xContext) );
2630 // initialize the dialog
2631 Reference< XPropertySet > xDialogProps( xDialog, UNO_QUERY_THROW );
2632 xDialogProps->setPropertyValue("QueryComposer", Any( xComposer ) );
2633 xDialogProps->setPropertyValue("RowSet", Any( m_xComponent ) );
2634 if (auto pTopLevel = impl_getDefaultDialogFrame_nothrow())
2635 xDialogProps->setPropertyValue("ParentWindow", Any(pTopLevel->GetXWindow()));
2636 xDialogProps->setPropertyValue("Title", Any( sPropertyUIName ) );
2638 _rClearBeforeDialog.clear();
2639 bSuccess = ( xDialog->execute() != 0 );
2640 if ( bSuccess )
2641 _out_rSelectedClause = _bFilter ? xComposer->getFilter() : xComposer->getOrder();
2643 catch (const SQLContext& e) { aErrorInfo = e; }
2644 catch (const SQLWarning& e) { aErrorInfo = e; }
2645 catch (const SQLException& e) { aErrorInfo = e; }
2646 catch( const Exception& )
2648 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "FormComponentPropertyHandler::impl_dialogFilterOrSort_nothrow" );
2651 if ( aErrorInfo.isValid() )
2652 impl_displaySQLError_nothrow( aErrorInfo );
2654 return bSuccess;
2658 bool FormComponentPropertyHandler::impl_dialogLinkedFormFields_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2660 Reference< XForm > xDetailForm( m_xComponent, UNO_QUERY );
2661 Reference< XForm > xMasterForm( m_xObjectParent, UNO_QUERY );
2662 uno::Reference<beans::XPropertySet> xMasterProp(m_xObjectParent,uno::UNO_QUERY);
2663 OSL_PRECOND( xDetailForm.is() && xMasterForm.is(), "FormComponentPropertyHandler::impl_dialogLinkedFormFields_nothrow: no forms!" );
2664 if ( !xDetailForm.is() || !xMasterForm.is() )
2665 return false;
2667 FormLinkDialog aDialog(impl_getDefaultDialogFrame_nothrow(), m_xComponent, xMasterProp, m_xContext);
2668 _rClearBeforeDialog.clear();
2669 return ( RET_OK == aDialog.run() );
2672 bool FormComponentPropertyHandler::impl_dialogFormatting_nothrow( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2674 bool bChanged = false;
2677 // create the itemset for the dialog
2678 SfxItemSet aCoreSet(
2679 SfxGetpApp()->GetPool(),
2680 svl::Items<
2681 SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO>);
2682 // ripped this somewhere ... don't understand it :(
2684 // get the number formats supplier
2685 Reference< XNumberFormatsSupplier > xSupplier;
2686 m_xComponent->getPropertyValue( PROPERTY_FORMATSSUPPLIER ) >>= xSupplier;
2688 DBG_ASSERT(xSupplier.is(), "FormComponentPropertyHandler::impl_dialogFormatting_nothrow: invalid call !" );
2689 Reference< XUnoTunnel > xTunnel( xSupplier, UNO_QUERY_THROW );
2690 SvNumberFormatsSupplierObj* pSupplier =
2691 reinterpret_cast< SvNumberFormatsSupplierObj* >( xTunnel->getSomething( SvNumberFormatsSupplierObj::getUnoTunnelId() ) );
2692 DBG_ASSERT( pSupplier != nullptr, "FormComponentPropertyHandler::impl_dialogFormatting_nothrow: invalid call !" );
2694 sal_Int32 nFormatKey = 0;
2695 impl_getPropertyValue_throw( PROPERTY_FORMATKEY ) >>= nFormatKey;
2696 aCoreSet.Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE, nFormatKey ) );
2698 SvNumberFormatter* pFormatter = pSupplier->GetNumberFormatter();
2699 double dPreviewVal = OFormatSampleControl::getPreviewValue(pFormatter,nFormatKey);
2700 SvxNumberInfoItem aFormatter( pFormatter, dPreviewVal, PcrRes(RID_STR_TEXT_FORMAT), SID_ATTR_NUMBERFORMAT_INFO );
2701 aCoreSet.Put( aFormatter );
2703 // a tab dialog with a single page
2704 SfxSingleTabDialogController aDialog(impl_getDefaultDialogFrame_nothrow(), &aCoreSet,
2705 "cui/ui/formatnumberdialog.ui", "FormatNumberDialog");
2706 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
2707 ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SVXPAGE_NUMBERFORMAT );
2708 if ( !fnCreatePage )
2709 throw RuntimeException(); // caught below
2711 aDialog.SetTabPage((*fnCreatePage)(aDialog.get_content_area(), &aDialog, &aCoreSet));
2713 _rClearBeforeDialog.clear();
2714 if ( RET_OK == aDialog.run() )
2716 const SfxItemSet* pResult = aDialog.GetOutputItemSet();
2718 if (const SvxNumberInfoItem* pInfoItem = pResult->GetItem( SID_ATTR_NUMBERFORMAT_INFO ))
2720 for (sal_uInt32 key : pInfoItem->GetDelFormats())
2721 pFormatter->DeleteEntry(key);
2724 if ( const SfxUInt32Item* pItem = pResult->GetItemIfSet( SID_ATTR_NUMBERFORMAT_VALUE, false ) )
2726 _out_rNewValue <<= static_cast<sal_Int32>( pItem->GetValue() );
2727 bChanged = true;
2731 catch( const Exception& )
2733 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "FormComponentPropertyHandler::impl_dialogFormatting_nothrow" );
2735 return bChanged;
2738 bool FormComponentPropertyHandler::impl_browseForImage_nothrow( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2740 bool bIsLink = true;// reflect the legacy behavior
2741 OUString aStrTrans = m_pInfoService->getPropertyTranslation( PROPERTY_ID_IMAGE_URL );
2743 weld::Window* pWin = impl_getDefaultDialogFrame_nothrow();
2744 ::sfx2::FileDialogHelper aFileDlg(
2745 ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW,
2746 FileDialogFlags::Graphic, pWin);
2747 aFileDlg.SetContext(sfx2::FileDialogHelper::FormsInsertImage);
2748 aFileDlg.SetTitle(aStrTrans);
2749 // non-linked images ( e.g. those located in the document
2750 // stream ) only if document is available
2751 bool bHandleNonLink;
2753 Reference< XModel > xModel( impl_getContextDocument_nothrow() );
2754 bHandleNonLink = xModel.is();
2755 // Not implemented in reports
2756 if (bHandleNonLink)
2758 Reference< XReportDefinition > xReportDef( xModel, css::uno::UNO_QUERY );
2759 bHandleNonLink = !xReportDef.is();
2763 Reference< XFilePickerControlAccess > xController(aFileDlg.GetFilePicker(), UNO_QUERY);
2764 DBG_ASSERT(xController.is(), "FormComponentPropertyHandler::impl_browseForImage_nothrow: missing the controller interface on the file picker!");
2765 if (xController.is())
2767 // do a preview by default
2768 xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0, css::uno::Any(true));
2770 xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, css::uno::Any(bIsLink));
2771 xController->enableControl(ExtendedFilePickerElementIds::CHECKBOX_LINK, bHandleNonLink );
2775 OUString sCurValue;
2776 if( ! (impl_getPropertyValue_throw( PROPERTY_IMAGE_URL ) >>= sCurValue) )
2777 SAL_WARN("extensions.propctrlr", "impl_browseForImage_nothrow: unable to get property " << PROPERTY_IMAGE_URL);
2778 if (!sCurValue.isEmpty())
2780 aFileDlg.SetDisplayDirectory( sCurValue );
2781 // TODO: need to set the display directory _and_ the default name
2784 _rClearBeforeDialog.clear();
2785 bool bSuccess = ( ERRCODE_NONE == aFileDlg.Execute() );
2786 if ( bSuccess )
2788 if ( bHandleNonLink && xController.is() )
2790 xController->getValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0) >>= bIsLink;
2792 if ( !bIsLink )
2794 Graphic aGraphic;
2795 aFileDlg.GetGraphic(aGraphic);
2797 Reference< graphic::XGraphicObject > xGrfObj = graphic::GraphicObject::create( m_xContext );
2798 xGrfObj->setGraphic( aGraphic.GetXGraphic() );
2800 _out_rNewValue <<= xGrfObj;
2803 else
2804 _out_rNewValue <<= aFileDlg.GetPath();
2806 return bSuccess;
2809 bool FormComponentPropertyHandler::impl_browseForTargetURL_nothrow( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2811 weld::Window* pWin = impl_getDefaultDialogFrame_nothrow();
2812 ::sfx2::FileDialogHelper aFileDlg(
2813 ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
2814 FileDialogFlags::NONE, pWin);
2816 OUString sURL;
2817 if( ! (impl_getPropertyValue_throw( PROPERTY_TARGET_URL ) >>= sURL) )
2818 SAL_WARN("extensions.propctrlr", "impl_browseForTargetURL_nothrow: unable to get property " << PROPERTY_TARGET_URL);
2819 INetURLObject aParser( sURL );
2820 if ( INetProtocol::File == aParser.GetProtocol() )
2821 // set the initial directory only for file-URLs. Everything else
2822 // is considered to be potentially expensive
2823 aFileDlg.SetDisplayDirectory( sURL );
2825 _rClearBeforeDialog.clear();
2826 bool bSuccess = ( ERRCODE_NONE == aFileDlg.Execute() );
2827 if ( bSuccess )
2828 _out_rNewValue <<= aFileDlg.GetPath();
2829 return bSuccess;
2832 bool FormComponentPropertyHandler::impl_executeFontDialog_nothrow( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2834 bool bSuccess = false;
2836 // create an item set for use with the dialog
2837 std::unique_ptr<SfxItemSet> pSet;
2838 rtl::Reference<SfxItemPool> pPool;
2839 std::vector<SfxPoolItem*>* pDefaults = nullptr;
2840 ControlCharacterDialog::createItemSet(pSet, pPool, pDefaults);
2841 ControlCharacterDialog::translatePropertiesToItems(m_xComponent, pSet.get());
2843 { // do this in an own block. The dialog needs to be destroyed before we call
2844 // destroyItemSet
2845 ControlCharacterDialog aDlg(impl_getDefaultDialogFrame_nothrow(), *pSet);
2846 _rClearBeforeDialog.clear();
2847 if (RET_OK == aDlg.run())
2849 const SfxItemSet* pOut = aDlg.GetOutputItemSet();
2850 if ( pOut )
2852 std::vector< NamedValue > aFontPropertyValues;
2853 ControlCharacterDialog::translateItemsToProperties( *pOut, aFontPropertyValues );
2854 _out_rNewValue <<= comphelper::containerToSequence(aFontPropertyValues);
2855 bSuccess = true;
2860 ControlCharacterDialog::destroyItemSet(pSet, pPool, pDefaults);
2861 return bSuccess;
2865 bool FormComponentPropertyHandler::impl_browseForDatabaseDocument_throw( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2867 weld::Window* pWin = impl_getDefaultDialogFrame_nothrow();
2868 ::sfx2::FileDialogHelper aFileDlg(
2869 ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION, FileDialogFlags::NONE,
2870 "sdatabase", SfxFilterFlags::NONE, SfxFilterFlags::NONE, pWin);
2872 OUString sDataSource;
2873 if( ! (impl_getPropertyValue_throw( PROPERTY_DATASOURCE ) >>= sDataSource) )
2874 SAL_WARN("extensions.propctrlr", "impl_browseForDatabaseDocument_throw: unable to get property " << PROPERTY_DATASOURCE);
2875 INetURLObject aParser( sDataSource );
2876 if ( INetProtocol::File == aParser.GetProtocol() )
2877 // set the initial directory only for file-URLs. Everything else
2878 // is considered to be potentially expensive
2879 aFileDlg.SetDisplayDirectory( sDataSource );
2881 std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetFilterByName("StarOffice XML (Base)");
2882 OSL_ENSURE(pFilter,"Filter: StarOffice XML (Base) could not be found!");
2883 if ( pFilter )
2885 aFileDlg.SetCurrentFilter(pFilter->GetUIName());
2886 //aFileDlg.AddFilter(pFilter->GetFilterName(),pFilter->GetDefaultExtension());
2889 _rClearBeforeDialog.clear();
2890 bool bSuccess = ( ERRCODE_NONE == aFileDlg.Execute() );
2891 if ( bSuccess )
2892 _out_rNewValue <<= aFileDlg.GetPath();
2893 return bSuccess;
2896 bool FormComponentPropertyHandler::impl_dialogColorChooser_throw( sal_Int32 _nColorPropertyId, Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2898 ::Color aColor;
2899 if( ! (impl_getPropertyValue_throw( impl_getPropertyNameFromId_nothrow( _nColorPropertyId )) >>= aColor) )
2900 SAL_WARN("extensions.propctrlr", "impl_dialogColorChooser_throw: unable to get property " << _nColorPropertyId);
2901 SvColorDialog aColorDlg;
2902 aColorDlg.SetColor( aColor );
2904 _rClearBeforeDialog.clear();
2905 weld::Window* pParent = impl_getDefaultDialogFrame_nothrow();
2906 if (!aColorDlg.Execute(pParent))
2907 return false;
2909 _out_rNewValue <<= aColorDlg.GetColor();
2910 return true;
2913 bool FormComponentPropertyHandler::impl_dialogChooseLabelControl_nothrow( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2915 weld::Window* pParent = impl_getDefaultDialogFrame_nothrow();
2916 OSelectLabelDialog dlgSelectLabel(pParent, m_xComponent);
2917 _rClearBeforeDialog.clear();
2918 bool bSuccess = (RET_OK == dlgSelectLabel.run());
2919 if ( bSuccess )
2920 _out_rNewValue <<= dlgSelectLabel.GetSelected();
2921 return bSuccess;
2925 Reference< XControlContainer > FormComponentPropertyHandler::impl_getContextControlContainer_nothrow() const
2927 Reference< XControlContainer > xControlContext;
2928 Any any = m_xContext->getValueByName( "ControlContext" );
2929 any >>= xControlContext;
2930 return xControlContext;
2934 bool FormComponentPropertyHandler::impl_dialogChangeTabOrder_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2936 OSL_PRECOND( impl_getContextControlContainer_nothrow().is(), "FormComponentPropertyHandler::impl_dialogChangeTabOrder_nothrow: invalid control context!" );
2938 Reference< XTabControllerModel > xTabControllerModel( impl_getRowSet_nothrow(), UNO_QUERY );
2939 TabOrderDialog aDialog(impl_getDefaultDialogFrame_nothrow(), xTabControllerModel,
2940 impl_getContextControlContainer_nothrow(), m_xContext);
2941 _rClearBeforeDialog.clear();
2942 return RET_OK == aDialog.run();
2945 namespace
2948 //- ISQLCommandPropertyUI
2950 class ISQLCommandPropertyUI : public ISQLCommandAdapter
2952 public:
2953 /** returns the empty-string-terminated list of names of properties
2954 whose UI is to be disabled while the SQL command property is
2955 being edited.
2957 virtual OUString* getPropertiesToDisable() = 0;
2961 //- SQLCommandPropertyUI
2963 class SQLCommandPropertyUI : public ISQLCommandPropertyUI
2965 protected:
2966 explicit SQLCommandPropertyUI( const Reference< XPropertySet >& _rxObject )
2967 : m_xObject(_rxObject)
2969 if ( !m_xObject.is() )
2970 throw NullPointerException();
2973 protected:
2974 Reference< XPropertySet > m_xObject;
2978 //- FormSQLCommandUI - declaration
2980 class FormSQLCommandUI : public SQLCommandPropertyUI
2982 public:
2983 explicit FormSQLCommandUI( const Reference< XPropertySet >& _rxForm );
2985 // ISQLCommandAdapter
2986 virtual OUString getSQLCommand() const override;
2987 virtual bool getEscapeProcessing() const override;
2988 virtual void setSQLCommand( const OUString& _rCommand ) const override;
2989 virtual void setEscapeProcessing( const bool _bEscapeProcessing ) const override;
2991 // ISQLCommandPropertyUI
2992 virtual OUString* getPropertiesToDisable() override;
2996 //- FormSQLCommandUI - implementation
2999 FormSQLCommandUI::FormSQLCommandUI( const Reference< XPropertySet >& _rxForm )
3000 :SQLCommandPropertyUI( _rxForm )
3005 OUString FormSQLCommandUI::getSQLCommand() const
3007 OUString sCommand;
3008 if( ! (m_xObject->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand) )
3009 SAL_WARN("extensions.propctrlr", "getSQLCommand: unable to get property " << PROPERTY_COMMAND);
3010 return sCommand;
3014 bool FormSQLCommandUI::getEscapeProcessing() const
3016 bool bEscapeProcessing( false );
3017 if( ! (m_xObject->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bEscapeProcessing) )
3018 SAL_WARN("extensions.propctrlr", "getSQLCommand: unable to get property " << PROPERTY_ESCAPE_PROCESSING);
3019 return bEscapeProcessing;
3023 void FormSQLCommandUI::setSQLCommand( const OUString& _rCommand ) const
3025 m_xObject->setPropertyValue( PROPERTY_COMMAND, Any( _rCommand ) );
3029 void FormSQLCommandUI::setEscapeProcessing( const bool _bEscapeProcessing ) const
3031 m_xObject->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, Any( _bEscapeProcessing ) );
3035 OUString* FormSQLCommandUI::getPropertiesToDisable()
3037 static OUString s_aCommandProps[] = {
3038 OUString(PROPERTY_DATASOURCE),
3039 OUString(PROPERTY_COMMAND),
3040 OUString(PROPERTY_COMMANDTYPE),
3041 OUString(PROPERTY_ESCAPE_PROCESSING),
3042 OUString()
3044 return s_aCommandProps;
3047 //- ValueListCommandUI - declaration
3049 class ValueListCommandUI : public SQLCommandPropertyUI
3051 public:
3052 explicit ValueListCommandUI( const Reference< XPropertySet >& _rxListOrCombo );
3054 // ISQLCommandAdapter
3055 virtual OUString getSQLCommand() const override;
3056 virtual bool getEscapeProcessing() const override;
3057 virtual void setSQLCommand( const OUString& _rCommand ) const override;
3058 virtual void setEscapeProcessing( const bool _bEscapeProcessing ) const override;
3060 // ISQLCommandPropertyUI
3061 virtual OUString* getPropertiesToDisable() override;
3062 private:
3063 mutable bool m_bPropertyValueIsList;
3067 //- ValueListCommandUI - implementation
3070 ValueListCommandUI::ValueListCommandUI( const Reference< XPropertySet >& _rxListOrCombo )
3071 :SQLCommandPropertyUI( _rxListOrCombo )
3072 ,m_bPropertyValueIsList( false )
3077 OUString ValueListCommandUI::getSQLCommand() const
3079 OUString sValue;
3080 m_bPropertyValueIsList = false;
3082 // for combo boxes, the property is a mere string
3083 Any aValue( m_xObject->getPropertyValue( PROPERTY_LISTSOURCE ) );
3084 if ( aValue >>= sValue )
3085 return sValue;
3087 Sequence< OUString > aValueList;
3088 if ( aValue >>= aValueList )
3090 m_bPropertyValueIsList = true;
3091 if ( aValueList.hasElements() )
3092 sValue = aValueList[0];
3093 return sValue;
3096 OSL_FAIL( "ValueListCommandUI::getSQLCommand: unexpected property type!" );
3097 return sValue;
3101 bool ValueListCommandUI::getEscapeProcessing() const
3103 ListSourceType eType = ListSourceType_SQL;
3104 if( ! (m_xObject->getPropertyValue( PROPERTY_LISTSOURCETYPE ) >>= eType) )
3105 SAL_WARN("extensions.propctrlr", "getEscapeProcessing: unable to get property " << PROPERTY_LISTSOURCETYPE);
3106 OSL_ENSURE( ( eType == ListSourceType_SQL ) || ( eType == ListSourceType_SQLPASSTHROUGH ),
3107 "ValueListCommandUI::getEscapeProcessing: unexpected list source type!" );
3108 return ( eType == ListSourceType_SQL );
3112 void ValueListCommandUI::setSQLCommand( const OUString& _rCommand ) const
3114 Any aValue;
3115 if ( m_bPropertyValueIsList )
3116 aValue <<= Sequence< OUString >( &_rCommand, 1 );
3117 else
3118 aValue <<= _rCommand;
3119 m_xObject->setPropertyValue( PROPERTY_LISTSOURCE, aValue );
3123 void ValueListCommandUI::setEscapeProcessing( const bool _bEscapeProcessing ) const
3125 m_xObject->setPropertyValue( PROPERTY_LISTSOURCETYPE, Any(
3126 _bEscapeProcessing ? ListSourceType_SQL : ListSourceType_SQLPASSTHROUGH ) );
3130 OUString* ValueListCommandUI::getPropertiesToDisable()
3132 static OUString s_aListSourceProps[] = {
3133 OUString(PROPERTY_LISTSOURCETYPE),
3134 OUString(PROPERTY_LISTSOURCE),
3135 OUString()
3137 return s_aListSourceProps;
3142 bool FormComponentPropertyHandler::impl_doDesignSQLCommand_nothrow( const Reference< XObjectInspectorUI >& _rxInspectorUI, PropertyId _nDesignForProperty )
3146 if ( m_xCommandDesigner.is() )
3148 if ( m_xCommandDesigner->isActive() )
3150 m_xCommandDesigner->raise();
3151 return true;
3153 m_xCommandDesigner->dispose();
3154 m_xCommandDesigner.set( nullptr );
3157 if ( !impl_ensureRowsetConnection_nothrow() )
3158 return false;
3160 Reference< XPropertySet > xComponentProperties( m_xComponent, UNO_SET_THROW );
3162 ::rtl::Reference< ISQLCommandPropertyUI > xCommandUI;
3163 switch ( _nDesignForProperty )
3165 case PROPERTY_ID_COMMAND:
3166 xCommandUI = new FormSQLCommandUI( xComponentProperties );
3167 break;
3168 case PROPERTY_ID_LISTSOURCE:
3169 xCommandUI = new ValueListCommandUI( xComponentProperties );
3170 break;
3171 default:
3172 OSL_FAIL( "FormComponentPropertyHandler::OnDesignerClosed: invalid property id!" );
3173 return false;
3176 m_xCommandDesigner.set( new SQLCommandDesigner( m_xContext, xCommandUI, m_xRowSetConnection, LINK( this, FormComponentPropertyHandler, OnDesignerClosed ) ) );
3178 DBG_ASSERT( _rxInspectorUI.is(), "FormComponentPropertyHandler::OnDesignerClosed: no access to the property browser ui!" );
3179 if ( m_xCommandDesigner->isActive() && _rxInspectorUI.is() )
3181 m_xBrowserUI = _rxInspectorUI;
3182 // disable everything which would affect this property
3183 const OUString* pToDisable = xCommandUI->getPropertiesToDisable();
3184 while ( !pToDisable->isEmpty() )
3186 m_xBrowserUI->enablePropertyUIElements( *pToDisable++, PropertyLineElement::All, false );
3189 // but enable the browse button for the property itself - so it can be used to raise the query designer
3190 OUString sPropertyName( impl_getPropertyNameFromId_nothrow( _nDesignForProperty ) );
3191 m_xBrowserUI->enablePropertyUIElements( sPropertyName, PropertyLineElement::PrimaryButton, true );
3194 catch( const Exception& )
3196 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
3198 return m_xCommandDesigner.is();
3202 IMPL_LINK_NOARG( FormComponentPropertyHandler, OnDesignerClosed, SQLCommandDesigner&, void )
3204 OSL_ENSURE( m_xBrowserUI.is() && m_xCommandDesigner.is(), "FormComponentPropertyHandler::OnDesignerClosed: too many NULLs!" );
3205 if ( !(m_xBrowserUI.is() && m_xCommandDesigner.is()) )
3206 return;
3210 ::rtl::Reference< ISQLCommandPropertyUI > xCommandUI(
3211 dynamic_cast< ISQLCommandPropertyUI* >( m_xCommandDesigner->getPropertyAdapter().get() ) );
3212 if ( !xCommandUI.is() )
3213 throw NullPointerException();
3215 const OUString* pToEnable = xCommandUI->getPropertiesToDisable();
3216 while ( !pToEnable->isEmpty() )
3218 m_xBrowserUI->enablePropertyUIElements( *pToEnable++, PropertyLineElement::All, true );
3221 catch( const Exception& )
3223 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
3228 bool FormComponentPropertyHandler::impl_hasValidDataSourceSignature_nothrow( const Reference< XPropertySet >& _xFormProperties, bool _bAllowEmptyDataSourceName )
3230 bool bHas = false;
3231 if ( _xFormProperties.is() )
3235 OUString sPropertyValue;
3236 // first, we need the name of an existent data source
3237 if ( _xFormProperties->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATASOURCE) )
3238 _xFormProperties->getPropertyValue( PROPERTY_DATASOURCE ) >>= sPropertyValue;
3239 bHas = ( !sPropertyValue.isEmpty() ) || _bAllowEmptyDataSourceName;
3241 // then, the command should not be empty
3242 if ( bHas )
3244 if ( _xFormProperties->getPropertySetInfo()->hasPropertyByName(PROPERTY_COMMAND) )
3245 _xFormProperties->getPropertyValue( PROPERTY_COMMAND ) >>= sPropertyValue;
3246 bHas = !sPropertyValue.isEmpty();
3249 catch( const Exception& )
3251 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "FormComponentPropertyHandler::impl_hasValidDataSourceSignature_nothrow" );
3254 return bHas;
3257 OUString FormComponentPropertyHandler::impl_getDocumentURL_nothrow() const
3259 OUString sURL;
3262 Reference< XModel > xDocument( impl_getContextDocument_nothrow() );
3263 if ( xDocument.is() )
3264 sURL = xDocument->getURL();
3266 catch( const Exception& )
3268 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
3270 return sURL;
3273 ::cppu::IPropertyArrayHelper* FormComponentPropertyHandler::createArrayHelper( ) const
3275 uno::Sequence< beans::Property > aProps;
3276 describeProperties(aProps);
3277 return new ::cppu::OPropertyArrayHelper(aProps);
3281 ::cppu::IPropertyArrayHelper & FormComponentPropertyHandler::getInfoHelper()
3283 return *getArrayHelper();
3286 uno::Reference< beans::XPropertySetInfo > SAL_CALL FormComponentPropertyHandler::getPropertySetInfo( )
3288 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
3292 } // namespace pcr
3294 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
3295 extensions_propctrlr_FormComponentPropertyHandler_get_implementation(
3296 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
3298 return cppu::acquire(new pcr::FormComponentPropertyHandler(context));
3301 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */