Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / extensions / source / propctrlr / formcomponenthandler.cxx
blob7feca01b5a5589b43dc525eef1cd9931f4c725fc
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 "pcrservices.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 "taborder.hxx"
38 #include "usercontrol.hxx"
40 #include <com/sun/star/lang/NullPointerException.hpp>
41 #include <com/sun/star/awt/XControlModel.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/sdb/XSingleSelectQueryComposer.hpp>
61 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
62 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
63 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
64 #include <com/sun/star/awt/XTabControllerModel.hpp>
65 #include <com/sun/star/form/FormSubmitEncoding.hpp>
66 #include <com/sun/star/awt/VisualEffect.hpp>
67 #include <com/sun/star/form/FormButtonType.hpp>
68 #include <com/sun/star/inspection/PropertyControlType.hpp>
69 #include <com/sun/star/util/MeasureUnit.hpp>
70 #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
71 #include <com/sun/star/inspection/PropertyLineElement.hpp>
72 #include <com/sun/star/resource/XStringResourceManager.hpp>
73 #include <com/sun/star/resource/MissingResourceException.hpp>
74 #include <com/sun/star/report/XReportDefinition.hpp>
75 #include <com/sun/star/graphic/GraphicObject.hpp>
76 #include <com/sun/star/text/WritingMode2.hpp>
78 #include <comphelper/extract.hxx>
79 #include <comphelper/types.hxx>
80 #include <connectivity/dbconversion.hxx>
81 #include <connectivity/dbexception.hxx>
82 #include <cppuhelper/exc_hlp.hxx>
83 #include <sfx2/app.hxx>
84 #include <sfx2/basedlgs.hxx>
85 #include <sfx2/docfilt.hxx>
86 #include <sfx2/filedlghelper.hxx>
87 #include <svl/ctloptions.hxx>
88 #include <svtools/colrdlg.hxx>
89 #include <svl/filenotation.hxx>
90 #include <svl/intitem.hxx>
91 #include <svl/itemset.hxx>
92 #include <unotools/moduleoptions.hxx>
93 #include <svl/numuno.hxx>
94 #include <svl/urihelper.hxx>
95 #include <svx/dialogs.hrc>
96 #include <svx/numinf.hxx>
97 #include <svx/svxdlg.hxx>
98 #include <svx/svxids.hrc>
99 #include <vcl/graph.hxx>
100 #include <vcl/unohelp.hxx>
101 #include <tools/diagnose_ex.h>
102 #include <vcl/stdtext.hxx>
103 #include <sal/macros.h>
104 #include <sal/log.hxx>
106 #include <limits>
107 #include <memory>
109 extern "C" void createRegistryInfo_FormComponentPropertyHandler()
111 ::pcr::FormComponentPropertyHandler::registerImplementation();
115 namespace pcr
119 using namespace ::com::sun::star;
120 using namespace uno;
121 using namespace lang;
122 using namespace beans;
123 using namespace frame;
124 using namespace script;
125 using namespace form;
126 using namespace util;
127 using namespace awt;
128 using namespace sdb;
129 using namespace sdbc;
130 using namespace sdbcx;
131 using namespace report;
132 using namespace container;
133 using namespace ui::dialogs;
134 using namespace inspection;
135 using namespace ::dbtools;
137 namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
140 //= FormComponentPropertyHandler
142 #define PROPERTY_ID_ROWSET 1
144 FormComponentPropertyHandler::FormComponentPropertyHandler( const Reference< XComponentContext >& _rxContext )
145 :FormComponentPropertyHandler_Base( _rxContext )
146 ,::comphelper::OPropertyContainer(FormComponentPropertyHandler_Base::rBHelper)
147 ,m_sDefaultValueString( PcrRes(RID_STR_STANDARD) )
148 ,m_eComponentClass( eUnknown )
149 ,m_bComponentIsSubForm( false )
150 ,m_bHaveListSource( false )
151 ,m_bHaveCommand( false )
152 ,m_nClassId( 0 )
154 registerProperty(PROPERTY_ROWSET,PROPERTY_ID_ROWSET,0,&m_xRowSet,cppu::UnoType<decltype(m_xRowSet)>::get());
158 FormComponentPropertyHandler::~FormComponentPropertyHandler()
162 IMPLEMENT_FORWARD_XINTERFACE2(FormComponentPropertyHandler,FormComponentPropertyHandler_Base,::comphelper::OPropertyContainer)
164 OUString FormComponentPropertyHandler::getImplementationName_static( )
166 return "com.sun.star.comp.extensions.FormComponentPropertyHandler";
170 Sequence< OUString > FormComponentPropertyHandler::getSupportedServiceNames_static( )
172 Sequence<OUString> aSupported { "com.sun.star.form.inspection.FormComponentPropertyHandler" };
173 return aSupported;
177 // TODO: -> export from toolkit
178 struct LanguageDependentProp
180 const char* pPropName;
181 sal_Int32 nPropNameLength;
184 static const LanguageDependentProp aLanguageDependentProp[] =
186 { "Text", 4 },
187 { "Label", 5 },
188 { "Title", 5 },
189 { "HelpText", 8 },
190 { "CurrencySymbol", 14 },
191 { "StringItemList", 14 },
192 { nullptr, 0 }
195 namespace
197 bool lcl_isLanguageDependentProperty( const OUString& aName )
199 bool bRet = false;
201 const LanguageDependentProp* pLangDepProp = aLanguageDependentProp;
202 while( pLangDepProp->pPropName != nullptr )
204 if( aName.equalsAsciiL( pLangDepProp->pPropName, pLangDepProp->nPropNameLength ))
206 bRet = true;
207 break;
209 pLangDepProp++;
211 return bRet;
214 Reference< resource::XStringResourceResolver > lcl_getStringResourceResolverForProperty
215 ( const Reference< XPropertySet >& _xComponent, const OUString& _rPropertyName,
216 const Any& _rPropertyValue )
218 Reference< resource::XStringResourceResolver > xRet;
219 const TypeClass eType = _rPropertyValue.getValueType().getTypeClass();
220 if ( (eType == TypeClass_STRING || eType == TypeClass_SEQUENCE) &&
221 lcl_isLanguageDependentProperty( _rPropertyName ) )
223 Reference< resource::XStringResourceResolver > xStringResourceResolver;
226 xStringResourceResolver.set( _xComponent->getPropertyValue( "ResourceResolver" ),UNO_QUERY);
227 if( xStringResourceResolver.is() &&
228 xStringResourceResolver->getLocales().hasElements() )
230 xRet = xStringResourceResolver;
233 catch(const UnknownPropertyException&)
235 // nii
239 return xRet;
244 Any FormComponentPropertyHandler::impl_getPropertyValue_throw( const OUString& _rPropertyName ) const
246 const PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
248 Any aPropertyValue( m_xComponent->getPropertyValue( _rPropertyName ) );
250 Reference< resource::XStringResourceResolver > xStringResourceResolver
251 = lcl_getStringResourceResolverForProperty( m_xComponent, _rPropertyName, aPropertyValue );
252 if( xStringResourceResolver.is() )
254 TypeClass eType = aPropertyValue.getValueType().getTypeClass();
255 if( eType == TypeClass_STRING )
257 OUString aPropStr;
258 aPropertyValue >>= aPropStr;
259 if( aPropStr.getLength() > 1 )
261 OUString aPureIdStr = aPropStr.copy( 1 );
262 if( xStringResourceResolver->hasEntryForId( aPureIdStr ) )
264 OUString aResourceStr = xStringResourceResolver->resolveString( aPureIdStr );
265 aPropertyValue <<= aResourceStr;
269 // StringItemList?
270 else if( eType == TypeClass_SEQUENCE )
272 Sequence< OUString > aStrings;
273 aPropertyValue >>= aStrings;
275 std::vector< OUString > aResolvedStrings;
276 aResolvedStrings.reserve( aStrings.getLength() );
279 for ( const OUString& rIdStr : std::as_const(aStrings) )
281 OUString aPureIdStr = rIdStr.copy( 1 );
282 if( xStringResourceResolver->hasEntryForId( aPureIdStr ) )
283 aResolvedStrings.push_back(xStringResourceResolver->resolveString( aPureIdStr ));
284 else
285 aResolvedStrings.push_back(rIdStr);
288 catch( const resource::MissingResourceException & )
290 aPropertyValue <<= comphelper::containerToSequence(aResolvedStrings);
293 else
294 impl_normalizePropertyValue_nothrow( aPropertyValue, nPropId );
296 return aPropertyValue;
299 Any SAL_CALL FormComponentPropertyHandler::getPropertyValue( const OUString& _rPropertyName )
301 if( _rPropertyName == PROPERTY_ROWSET )
302 return ::comphelper::OPropertyContainer::getPropertyValue( _rPropertyName );
304 ::osl::MutexGuard aGuard( m_aMutex );
305 return impl_getPropertyValue_throw( _rPropertyName );
308 void SAL_CALL FormComponentPropertyHandler::setPropertyValue( const OUString& _rPropertyName, const Any& _rValue )
310 if( _rPropertyName == PROPERTY_ROWSET )
312 ::comphelper::OPropertyContainer::setPropertyValue( _rPropertyName, _rValue );
313 return;
316 ::osl::MutexGuard aGuard( m_aMutex );
317 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) ); // check if property is known by the handler
319 Reference< graphic::XGraphicObject > xGrfObj;
320 if ( PROPERTY_ID_IMAGE_URL == nPropId && ( _rValue >>= xGrfObj ) )
322 DBG_ASSERT( xGrfObj.is(), "FormComponentPropertyHandler::setPropertyValue() xGrfObj is invalid");
323 m_xComponent->setPropertyValue(PROPERTY_GRAPHIC, uno::makeAny(xGrfObj->getGraphic()));
325 else if ( PROPERTY_ID_FONT == nPropId )
327 // special handling, the value is a faked value we generated ourself in impl_executeFontDialog_nothrow
328 Sequence< NamedValue > aFontPropertyValues;
329 if( ! (_rValue >>= aFontPropertyValues) )
330 SAL_WARN("extensions.propctrlr", "setPropertyValue: unable to get property " << PROPERTY_ID_FONT);
332 for ( const NamedValue& fontPropertyValue : std::as_const(aFontPropertyValues) )
333 m_xComponent->setPropertyValue( fontPropertyValue.Name, fontPropertyValue.Value );
335 else
337 Any aValue = _rValue;
339 Reference< resource::XStringResourceResolver > xStringResourceResolver
340 = lcl_getStringResourceResolverForProperty( m_xComponent, _rPropertyName, _rValue );
341 if( xStringResourceResolver.is() )
343 Reference< resource::XStringResourceManager >
344 xStringResourceManager( xStringResourceResolver, UNO_QUERY );
345 if( xStringResourceManager.is() )
347 Any aPropertyValue( m_xComponent->getPropertyValue( _rPropertyName ) );
348 TypeClass eType = aPropertyValue.getValueType().getTypeClass();
349 if( eType == TypeClass_STRING )
351 OUString aPropStr;
352 aPropertyValue >>= aPropStr;
353 if( aPropStr.getLength() > 1 )
355 OUString aPureIdStr = aPropStr.copy( 1 );
356 OUString aValueStr;
357 _rValue >>= aValueStr;
358 xStringResourceManager->setString( aPureIdStr, aValueStr );
359 aValue = aPropertyValue; // set value to force modified
362 // StringItemList?
363 else if( eType == TypeClass_SEQUENCE )
365 static const char aDot[] = ".";
367 // Put strings into resource using new ids
368 Sequence< OUString > aNewStrings;
369 _rValue >>= aNewStrings;
371 const sal_Int32 nNewCount = aNewStrings.getLength();
373 // Create new Ids
374 std::unique_ptr<OUString[]> pNewPureIds(new OUString[nNewCount]);
375 Any aNameAny = m_xComponent->getPropertyValue(PROPERTY_NAME);
376 OUString sControlName;
377 aNameAny >>= sControlName;
378 OUString aIdStrBase = aDot
379 + sControlName
380 + aDot
381 + _rPropertyName;
382 sal_Int32 i;
383 for ( i = 0; i < nNewCount; ++i )
385 sal_Int32 nUniqueId = xStringResourceManager->getUniqueNumericId();
386 OUString aPureIdStr = OUString::number( nUniqueId ) + aIdStrBase;
387 pNewPureIds[i] = aPureIdStr;
388 // Force usage of next Unique Id
389 xStringResourceManager->setString( aPureIdStr, OUString() );
392 // Move strings to new Ids for all locales
393 const Sequence< Locale > aLocaleSeq = xStringResourceManager->getLocales();
394 Sequence< OUString > aOldIdStrings;
395 aPropertyValue >>= aOldIdStrings;
398 const OUString* pOldIdStrings = aOldIdStrings.getConstArray();
399 sal_Int32 nOldIdCount = aOldIdStrings.getLength();
400 for ( i = 0; i < nNewCount; ++i )
402 OUString aOldIdStr;
403 OUString aOldPureIdStr;
404 if( i < nOldIdCount )
406 aOldIdStr = pOldIdStrings[i];
407 aOldPureIdStr = aOldIdStr.copy( 1 );
409 OUString aNewPureIdStr = pNewPureIds[i];
411 for ( const Locale& rLocale : aLocaleSeq )
413 OUString aResourceStr;
414 if( !aOldPureIdStr.isEmpty() )
416 if( xStringResourceManager->hasEntryForIdAndLocale( aOldPureIdStr, rLocale ) )
418 aResourceStr = xStringResourceManager->
419 resolveStringForLocale( aOldPureIdStr, rLocale );
422 xStringResourceManager->setStringForLocale( aNewPureIdStr, aResourceStr, rLocale );
426 catch( const resource::MissingResourceException & )
430 // Set new strings for current locale and create
431 // new Id sequence as new property value
432 Sequence< OUString > aNewIdStrings;
433 aNewIdStrings.realloc( nNewCount );
434 OUString* pNewIdStrings = aNewIdStrings.getArray();
435 for ( i = 0; i < nNewCount; ++i )
437 const OUString& aPureIdStr = pNewPureIds[i];
438 const OUString& aStr = aNewStrings[i];
439 xStringResourceManager->setString( aPureIdStr, aStr );
441 pNewIdStrings[i] = "&" + aPureIdStr;
443 aValue <<= aNewIdStrings;
445 // Remove old ids from resource for all locales
446 for( const OUString& rIdStr : std::as_const(aOldIdStrings) )
448 OUString aPureIdStr = rIdStr.copy( 1 );
449 for ( const Locale& rLocale : aLocaleSeq )
453 xStringResourceManager->removeIdForLocale( aPureIdStr, rLocale );
455 catch( const resource::MissingResourceException & )
463 m_xComponent->setPropertyValue( _rPropertyName, aValue );
467 Any SAL_CALL FormComponentPropertyHandler::convertToPropertyValue( const OUString& _rPropertyName, const Any& _rControlValue )
469 ::osl::MutexGuard aGuard( m_aMutex );
470 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
471 Property aProperty( impl_getPropertyFromId_throw( nPropId ) );
473 Any aPropertyValue( _rControlValue );
474 if ( !aPropertyValue.hasValue() )
476 if ( ( aProperty.Attributes & PropertyAttribute::MAYBEVOID ) == 0 )
477 // default construct an instance of the proper type
478 aPropertyValue = Any( nullptr, aProperty.Type );
479 // nothing to do
480 return aPropertyValue;
483 /// care for the special "default" string, translate it to VOID
484 if ( m_aPropertiesWithDefListEntry.find( _rPropertyName ) != m_aPropertiesWithDefListEntry.end() )
486 // it's a control with a string list
487 OUString sStringValue;
488 if ( _rControlValue >>= sStringValue )
489 { // note that ColorListBoxes might transfer values either as string or as css.util.Color,
490 // so this check here is important
491 if ( sStringValue == m_sDefaultValueString )
492 return Any();
496 switch ( nPropId )
498 case PROPERTY_ID_DATASOURCE:
500 OUString sControlValue;
501 if( ! (_rControlValue >>= sControlValue) )
502 SAL_WARN("extensions.propctrlr", "convertToPropertyValue: unable to get property " << PROPERTY_ID_DATASOURCE);
504 if ( !sControlValue.isEmpty() )
506 Reference< XDatabaseContext > xDatabaseContext = sdb::DatabaseContext::create( m_xContext );
507 if ( !xDatabaseContext->hasByName( sControlValue ) )
509 ::svt::OFileNotation aTransformer(sControlValue);
510 aPropertyValue <<= aTransformer.get( ::svt::OFileNotation::N_URL );
514 break; // case PROPERTY_ID_DATASOURCE
516 case PROPERTY_ID_SHOW_POSITION:
517 case PROPERTY_ID_SHOW_NAVIGATION:
518 case PROPERTY_ID_SHOW_RECORDACTIONS:
519 case PROPERTY_ID_SHOW_FILTERSORT:
521 OUString sControlValue;
522 if( ! (_rControlValue >>= sControlValue) )
523 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for Show/Hide");
525 assert(SAL_N_ELEMENTS(RID_RSC_ENUM_SHOWHIDE) == 2 && "FormComponentPropertyHandler::convertToPropertyValue: broken resource for Show/Hide!");
526 bool bShow = sControlValue == PcrRes(RID_RSC_ENUM_SHOWHIDE[1]);
528 aPropertyValue <<= bShow;
530 break;
532 case PROPERTY_ID_TARGET_URL:
533 case PROPERTY_ID_IMAGE_URL:
535 OUString sControlValue;
536 if( ! (_rControlValue >>= sControlValue) )
537 SAL_WARN("extensions.propctrlr", "convertToPropertyValue: unable to get property for URLs");
538 // Don't convert a placeholder
539 if ( nPropId == PROPERTY_ID_IMAGE_URL && sControlValue == PcrRes(RID_EMBED_IMAGE_PLACEHOLDER) )
540 aPropertyValue <<= sControlValue;
541 else
543 INetURLObject aDocURL( impl_getDocumentURL_nothrow() );
544 aPropertyValue <<= URIHelper::SmartRel2Abs( aDocURL, sControlValue, Link<OUString *, bool>(), false, true );
547 break;
549 case PROPERTY_ID_DATEMIN:
550 case PROPERTY_ID_DATEMAX:
551 case PROPERTY_ID_DEFAULT_DATE:
552 case PROPERTY_ID_DATE:
554 util::Date aDate;
555 if( ! (_rControlValue >>= aDate) )
556 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for date");
557 aPropertyValue <<= aDate;
559 break;
561 case PROPERTY_ID_TIMEMIN:
562 case PROPERTY_ID_TIMEMAX:
563 case PROPERTY_ID_DEFAULT_TIME:
564 case PROPERTY_ID_TIME:
566 util::Time aTime;
567 if( ! (_rControlValue >>= aTime) )
568 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for time");
569 aPropertyValue <<= aTime;
571 break;
573 case PROPERTY_ID_WRITING_MODE:
575 aPropertyValue = FormComponentPropertyHandler_Base::convertToPropertyValue( _rPropertyName, _rControlValue );
577 sal_Int16 nNormalizedValue( 2 );
578 if( ! (aPropertyValue >>= nNormalizedValue) )
579 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for " << PROPERTY_ID_WRITING_MODE);
581 sal_Int16 nWritingMode = WritingMode2::CONTEXT;
582 switch ( nNormalizedValue )
584 case 0: nWritingMode = WritingMode2::LR_TB; break;
585 case 1: nWritingMode = WritingMode2::RL_TB; break;
586 case 2: nWritingMode = WritingMode2::CONTEXT; break;
587 default:
588 OSL_FAIL( "FormComponentPropertyHandler::convertToPropertyValue: unexpected 'normalized value' for WritingMode!" );
589 nWritingMode = WritingMode2::CONTEXT;
590 break;
593 aPropertyValue <<= nWritingMode;
595 break;
597 default:
598 aPropertyValue = FormComponentPropertyHandler_Base::convertToPropertyValue( _rPropertyName, _rControlValue );
599 break; // default
601 } // switch ( nPropId )
603 return aPropertyValue;
606 Any SAL_CALL FormComponentPropertyHandler::convertToControlValue( const OUString& _rPropertyName, const Any& _rPropertyValue, const Type& _rControlValueType )
608 ::osl::MutexGuard aGuard( m_aMutex );
609 sal_Int32 nPropId = m_pInfoService->getPropertyId( _rPropertyName );
610 DBG_ASSERT( nPropId != -1, "FormComponentPropertyHandler::convertToPropertyValue: not one of my properties!!" );
612 impl_getPropertyFromId_throw( nPropId );
614 Any aControlValue( _rPropertyValue );
615 if ( !aControlValue.hasValue() )
617 // if the property is represented with a list box or color list box, we need to
618 // translate this into the string "Default"
619 if ( m_aPropertiesWithDefListEntry.find( _rPropertyName ) != m_aPropertiesWithDefListEntry.end() )
620 aControlValue <<= m_sDefaultValueString;
622 return aControlValue;
625 switch ( nPropId )
628 case PROPERTY_ID_SHOW_POSITION:
629 case PROPERTY_ID_SHOW_NAVIGATION:
630 case PROPERTY_ID_SHOW_RECORDACTIONS:
631 case PROPERTY_ID_SHOW_FILTERSORT:
633 assert(SAL_N_ELEMENTS(RID_RSC_ENUM_SHOWHIDE) == 2 && "FormComponentPropertyHandler::convertToPropertyValue: broken resource for Show/Hide!");
634 OUString sControlValue = ::comphelper::getBOOL(_rPropertyValue)
635 ? PcrRes(RID_RSC_ENUM_SHOWHIDE[1])
636 : PcrRes(RID_RSC_ENUM_SHOWHIDE[0]);
637 aControlValue <<= sControlValue;
639 break;
642 case PROPERTY_ID_DATASOURCE:
644 OSL_ENSURE( _rControlValueType.getTypeClass() == TypeClass_STRING,
645 "FormComponentPropertyHandler::convertToControlValue: wrong ControlValueType!" );
647 OUString sDataSource;
648 _rPropertyValue >>= sDataSource;
649 if ( !sDataSource.isEmpty() )
651 ::svt::OFileNotation aTransformer( sDataSource );
652 sDataSource = aTransformer.get( ::svt::OFileNotation::N_SYSTEM );
654 aControlValue <<= sDataSource;
656 break;
659 case PROPERTY_ID_CONTROLLABEL:
661 OUString sControlValue;
663 Reference< XPropertySet > xSet;
664 _rPropertyValue >>= xSet;
665 Reference< XPropertySetInfo > xPSI;
666 if ( xSet.is() )
667 xPSI = xSet->getPropertySetInfo();
668 if ( xPSI.is() && xPSI->hasPropertyByName( PROPERTY_LABEL ) )
670 OUString sLabel;
671 if( ! (xSet->getPropertyValue( PROPERTY_LABEL) >>= sLabel) )
672 SAL_WARN("extensions.propctrlr", "convertToPropertyValue: unable to get property " PROPERTY_LABEL);
673 sControlValue = "<" + sLabel + ">";
676 aControlValue <<= sControlValue;
678 break;
681 case PROPERTY_ID_DATEMIN:
682 case PROPERTY_ID_DATEMAX:
683 case PROPERTY_ID_DEFAULT_DATE:
684 case PROPERTY_ID_DATE:
686 sal_Int32 nDate = 0;
687 if( ! (_rPropertyValue >>= nDate) )
688 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for dates");
689 aControlValue <<= DBTypeConversion::toDate( nDate );
691 break;
693 case PROPERTY_ID_TIMEMIN:
694 case PROPERTY_ID_TIMEMAX:
695 case PROPERTY_ID_DEFAULT_TIME:
696 case PROPERTY_ID_TIME:
698 sal_Int64 nTime = 0;
699 if( ! (_rPropertyValue >>= nTime) )
700 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property for times");
701 aControlValue <<= DBTypeConversion::toTime( nTime );
703 break;
705 case PROPERTY_ID_WRITING_MODE:
707 sal_Int16 nWritingMode( WritingMode2::CONTEXT );
708 if( ! (_rPropertyValue >>= nWritingMode) )
709 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property " << PROPERTY_ID_WRITING_MODE);
711 sal_Int16 nNormalized = 2;
712 switch ( nWritingMode )
714 case WritingMode2::LR_TB: nNormalized = 0; break;
715 case WritingMode2::RL_TB: nNormalized = 1; break;
716 case WritingMode2::CONTEXT: nNormalized = 2; break;
717 default:
718 OSL_FAIL( "FormComponentPropertyHandler::convertToControlValue: unsupported API value for WritingMode!" );
719 nNormalized = 2;
720 break;
723 aControlValue = FormComponentPropertyHandler_Base::convertToControlValue( _rPropertyName, makeAny( nNormalized ), _rControlValueType );
725 break;
727 case PROPERTY_ID_FONT:
729 FontDescriptor aFont;
730 if( ! (_rPropertyValue >>= aFont) )
731 SAL_WARN("extensions.propctrlr", "convertToControlValue: unable to get property " << PROPERTY_ID_FONT);
733 OUStringBuffer displayName;
734 if ( aFont.Name.isEmpty() )
736 displayName.append( PcrRes(RID_STR_FONT_DEFAULT) );
738 else
740 // font name
741 displayName.append( aFont.Name );
742 displayName.append( ", " );
744 // font style
745 ::FontWeight eWeight = vcl::unohelper::ConvertFontWeight( aFont.Weight );
746 const char* 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( ", " );
765 displayName.append( sal_Int32( aFont.Height ) );
769 aControlValue <<= displayName.makeStringAndClear();
771 break;
773 default:
774 aControlValue = FormComponentPropertyHandler_Base::convertToControlValue( _rPropertyName, _rPropertyValue, _rControlValueType );
775 break;
777 } // switch ( nPropId )
779 return aControlValue;
782 PropertyState SAL_CALL FormComponentPropertyHandler::getPropertyState( const OUString& _rPropertyName )
784 ::osl::MutexGuard aGuard( m_aMutex );
785 if ( m_xPropertyState.is() )
786 return m_xPropertyState->getPropertyState( _rPropertyName );
787 return PropertyState_DIRECT_VALUE;
790 void SAL_CALL FormComponentPropertyHandler::addPropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener )
792 ::osl::MutexGuard aGuard( m_aMutex );
793 FormComponentPropertyHandler_Base::addPropertyChangeListener( _rxListener );
794 if ( m_xComponent.is() )
795 m_xComponent->addPropertyChangeListener( OUString(), _rxListener );
798 void SAL_CALL FormComponentPropertyHandler::removePropertyChangeListener( const Reference< XPropertyChangeListener >& _rxListener )
800 ::osl::MutexGuard aGuard( m_aMutex );
801 if ( m_xComponent.is() )
802 m_xComponent->removePropertyChangeListener( OUString(), _rxListener );
803 FormComponentPropertyHandler_Base::removePropertyChangeListener( _rxListener );
806 Sequence< Property > FormComponentPropertyHandler::doDescribeSupportedProperties() const
808 if ( !m_xComponentPropertyInfo.is() )
809 return Sequence< Property >();
811 std::vector< Property > aProperties;
813 Sequence< Property > aAllProperties( m_xComponentPropertyInfo->getProperties() );
814 aProperties.reserve( aAllProperties.getLength() );
816 // filter the properties
817 PropertyId nPropId( 0 );
818 OUString sDisplayName;
820 for ( Property & rProperty : aAllProperties )
822 nPropId = m_pInfoService->getPropertyId( rProperty.Name );
823 if ( nPropId == -1 )
824 continue;
825 rProperty.Handle = nPropId;
827 sDisplayName = m_pInfoService->getPropertyTranslation( nPropId );
828 if ( sDisplayName.isEmpty() )
829 continue;
831 sal_uInt32 nPropertyUIFlags = m_pInfoService->getPropertyUIFlags( nPropId );
832 bool bIsVisibleForForms = ( nPropertyUIFlags & PROP_FLAG_FORM_VISIBLE ) != 0;
833 bool bIsVisibleForDialogs = ( nPropertyUIFlags & PROP_FLAG_DIALOG_VISIBLE ) != 0;
835 // depending on whether we're working for a form or a UNO dialog, some
836 // properties are not displayed
837 if ( ( m_eComponentClass == eFormControl && !bIsVisibleForForms )
838 || ( m_eComponentClass == eDialogControl && !bIsVisibleForDialogs )
840 continue;
842 // some generic sanity checks
843 if ( impl_shouldExcludeProperty_nothrow( rProperty ) )
844 continue;
846 switch ( nPropId )
848 case PROPERTY_ID_BORDER:
849 case PROPERTY_ID_TABSTOP:
850 // BORDER and TABSTOP are normalized (see impl_normalizePropertyValue_nothrow)
851 // to not allow VOID values
852 rProperty.Attributes &= ~PropertyAttribute::MAYBEVOID;
853 break;
855 case PROPERTY_ID_LISTSOURCE:
856 // no cursor source if no Base is installed.
857 if ( SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
858 const_cast< FormComponentPropertyHandler* >( this )->m_bHaveListSource = true;
859 break;
861 case PROPERTY_ID_COMMAND:
862 // no cursor source if no Base is installed.
863 if ( SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
864 const_cast< FormComponentPropertyHandler* >( this )->m_bHaveCommand = true;
865 break;
866 } // switch ( nPropId )
868 aProperties.push_back( rProperty );
871 if ( aProperties.empty() )
872 return Sequence< Property >();
873 return comphelper::containerToSequence(aProperties);
876 Sequence< OUString > SAL_CALL FormComponentPropertyHandler::getSupersededProperties( )
878 return Sequence< OUString >( );
881 Sequence< OUString > SAL_CALL FormComponentPropertyHandler::getActuatingProperties( )
883 ::osl::MutexGuard aGuard( m_aMutex );
884 std::vector< OUString > aInterestingProperties;
885 aInterestingProperties.push_back( PROPERTY_DATASOURCE );
886 aInterestingProperties.push_back( PROPERTY_COMMAND );
887 aInterestingProperties.push_back( PROPERTY_COMMANDTYPE );
888 aInterestingProperties.push_back( PROPERTY_LISTSOURCE );
889 aInterestingProperties.push_back( PROPERTY_LISTSOURCETYPE );
890 aInterestingProperties.push_back( PROPERTY_SUBMIT_ENCODING );
891 aInterestingProperties.push_back( PROPERTY_REPEAT );
892 aInterestingProperties.push_back( PROPERTY_TABSTOP );
893 aInterestingProperties.push_back( PROPERTY_BORDER );
894 aInterestingProperties.push_back( PROPERTY_CONTROLSOURCE );
895 aInterestingProperties.push_back( PROPERTY_DROPDOWN );
896 aInterestingProperties.push_back( PROPERTY_IMAGE_URL );
897 aInterestingProperties.push_back( PROPERTY_TARGET_URL );
898 aInterestingProperties.push_back( PROPERTY_STRINGITEMLIST );
899 aInterestingProperties.push_back( PROPERTY_BUTTONTYPE );
900 aInterestingProperties.push_back( PROPERTY_ESCAPE_PROCESSING );
901 aInterestingProperties.push_back( PROPERTY_TRISTATE );
902 aInterestingProperties.push_back( PROPERTY_DECIMAL_ACCURACY );
903 aInterestingProperties.push_back( PROPERTY_SHOWTHOUSANDSEP );
904 aInterestingProperties.push_back( PROPERTY_FORMATKEY );
905 aInterestingProperties.push_back( PROPERTY_EMPTY_IS_NULL );
906 aInterestingProperties.push_back( PROPERTY_TOGGLE );
907 return comphelper::containerToSequence(aInterestingProperties);
910 LineDescriptor SAL_CALL FormComponentPropertyHandler::describePropertyLine( const OUString& _rPropertyName,
911 const Reference< XPropertyControlFactory >& _rxControlFactory )
913 if ( !_rxControlFactory.is() )
914 throw NullPointerException();
916 ::osl::MutexGuard aGuard( m_aMutex );
917 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
918 Property aProperty( impl_getPropertyFromId_throw( nPropId ) );
921 // for the MultiLine property, we have different UI translations depending on the control
922 // type
923 if ( nPropId == PROPERTY_ID_MULTILINE )
925 if ( ( m_nClassId == FormComponentType::FIXEDTEXT )
926 || ( m_nClassId == FormComponentType::COMMANDBUTTON )
927 || ( m_nClassId == FormComponentType::RADIOBUTTON )
928 || ( m_nClassId == FormComponentType::CHECKBOX )
930 nPropId = PROPERTY_ID_WORDBREAK;
933 OUString sDisplayName = m_pInfoService->getPropertyTranslation( nPropId );
934 if ( sDisplayName.isEmpty() )
936 OSL_FAIL( "FormComponentPropertyHandler::describePropertyLine: did getSupportedProperties not work properly?" );
937 throw UnknownPropertyException();
941 LineDescriptor aDescriptor;
942 aDescriptor.HelpURL = HelpIdUrl::getHelpURL( m_pInfoService->getPropertyHelpId( nPropId ) );
943 aDescriptor.DisplayName = sDisplayName;
945 // for the moment, assume a text field
946 sal_Int16 nControlType = PropertyControlType::TextField;
947 bool bReadOnly = false;
948 aDescriptor.Control.clear();
951 bool bNeedDefaultStringIfVoidAllowed = false;
953 TypeClass eType = aProperty.Type.getTypeClass();
955 switch ( nPropId )
957 case PROPERTY_ID_DEFAULT_SELECT_SEQ:
958 case PROPERTY_ID_SELECTEDITEMS:
959 aDescriptor.PrimaryButtonId = UID_PROP_DLG_SELECTION;
960 break;
962 case PROPERTY_ID_FILTER:
963 aDescriptor.PrimaryButtonId = UID_PROP_DLG_FILTER;
964 break;
966 case PROPERTY_ID_SORT:
967 aDescriptor.PrimaryButtonId = UID_PROP_DLG_ORDER;
968 break;
970 case PROPERTY_ID_MASTERFIELDS:
971 case PROPERTY_ID_DETAILFIELDS:
972 nControlType = PropertyControlType::StringListField;
973 aDescriptor.PrimaryButtonId = UID_PROP_DLG_FORMLINKFIELDS;
974 break;
976 case PROPERTY_ID_COMMAND:
977 aDescriptor.PrimaryButtonId = UID_PROP_DLG_SQLCOMMAND;
978 break;
980 case PROPERTY_ID_TABINDEX:
982 Reference< XControlContainer > xControlContext( impl_getContextControlContainer_nothrow() );
983 if ( xControlContext.is() )
984 aDescriptor.PrimaryButtonId = UID_PROP_DLG_TABINDEX;
985 nControlType = PropertyControlType::NumericField;
987 break;
989 case PROPERTY_ID_FONT:
990 bReadOnly = true;
991 aDescriptor.PrimaryButtonId = UID_PROP_DLG_FONT_TYPE;
992 break;
994 case PROPERTY_ID_TARGET_URL:
995 case PROPERTY_ID_IMAGE_URL:
997 aDescriptor.Control = new OFileUrlControl( impl_getDefaultDialogParent_nothrow() );
999 aDescriptor.PrimaryButtonId = PROPERTY_ID_TARGET_URL == nPropId
1000 ? OUStringLiteral(UID_PROP_DLG_ATTR_TARGET_URL)
1001 : OUStringLiteral(UID_PROP_DLG_IMAGE_URL);
1003 break;
1005 case PROPERTY_ID_ECHO_CHAR:
1006 nControlType = PropertyControlType::CharacterField;
1007 break;
1009 case PROPERTY_ID_BACKGROUNDCOLOR:
1010 case PROPERTY_ID_FILLCOLOR:
1011 case PROPERTY_ID_SYMBOLCOLOR:
1012 case PROPERTY_ID_BORDERCOLOR:
1013 case PROPERTY_ID_GRIDLINECOLOR:
1014 case PROPERTY_ID_HEADERBACKGROUNDCOLOR:
1015 case PROPERTY_ID_HEADERTEXTCOLOR:
1016 case PROPERTY_ID_ACTIVESELECTIONBACKGROUNDCOLOR:
1017 case PROPERTY_ID_ACTIVESELECTIONTEXTCOLOR:
1018 case PROPERTY_ID_INACTIVESELECTIONBACKGROUNDCOLOR:
1019 case PROPERTY_ID_INACTIVESELECTIONTEXTCOLOR:
1020 nControlType = PropertyControlType::ColorListBox;
1022 switch( nPropId )
1024 case PROPERTY_ID_BACKGROUNDCOLOR:
1025 aDescriptor.PrimaryButtonId = UID_PROP_DLG_BACKGROUNDCOLOR; break;
1026 case PROPERTY_ID_FILLCOLOR:
1027 aDescriptor.PrimaryButtonId = UID_PROP_DLG_FILLCOLOR; break;
1028 case PROPERTY_ID_SYMBOLCOLOR:
1029 aDescriptor.PrimaryButtonId = UID_PROP_DLG_SYMBOLCOLOR; break;
1030 case PROPERTY_ID_BORDERCOLOR:
1031 aDescriptor.PrimaryButtonId = UID_PROP_DLG_BORDERCOLOR; break;
1032 case PROPERTY_ID_GRIDLINECOLOR:
1033 aDescriptor.PrimaryButtonId = HID_PROP_GRIDLINECOLOR; break;
1034 case PROPERTY_ID_HEADERBACKGROUNDCOLOR:
1035 aDescriptor.PrimaryButtonId = HID_PROP_HEADERBACKGROUNDCOLOR; break;
1036 case PROPERTY_ID_HEADERTEXTCOLOR:
1037 aDescriptor.PrimaryButtonId = HID_PROP_HEADERTEXTCOLOR; break;
1038 case PROPERTY_ID_ACTIVESELECTIONBACKGROUNDCOLOR:
1039 aDescriptor.PrimaryButtonId = HID_PROP_ACTIVESELECTIONBACKGROUNDCOLOR; break;
1040 case PROPERTY_ID_ACTIVESELECTIONTEXTCOLOR:
1041 aDescriptor.PrimaryButtonId = HID_PROP_ACTIVESELECTIONTEXTCOLOR; break;
1042 case PROPERTY_ID_INACTIVESELECTIONBACKGROUNDCOLOR:
1043 aDescriptor.PrimaryButtonId = HID_PROP_INACTIVESELECTIONBACKGROUNDCOLOR; break;
1044 case PROPERTY_ID_INACTIVESELECTIONTEXTCOLOR:
1045 aDescriptor.PrimaryButtonId = HID_PROP_INACTIVESELECTIONTEXTCOLOR; break;
1047 break;
1049 case PROPERTY_ID_LABEL:
1050 case PROPERTY_ID_URL:
1051 nControlType = PropertyControlType::MultiLineTextField;
1052 break;
1054 case PROPERTY_ID_DEFAULT_TEXT:
1056 if (FormComponentType::FILECONTROL == m_nClassId)
1057 nControlType = PropertyControlType::TextField;
1058 else
1059 nControlType = PropertyControlType::MultiLineTextField;
1061 break;
1063 case PROPERTY_ID_TEXT:
1064 if ( impl_componentHasProperty_throw( PROPERTY_MULTILINE ) )
1065 nControlType = PropertyControlType::MultiLineTextField;
1066 break;
1068 case PROPERTY_ID_CONTROLLABEL:
1069 bReadOnly = true;
1070 aDescriptor.PrimaryButtonId = UID_PROP_DLG_CONTROLLABEL;
1071 break;
1073 case PROPERTY_ID_FORMATKEY:
1074 case PROPERTY_ID_EFFECTIVE_MIN:
1075 case PROPERTY_ID_EFFECTIVE_MAX:
1076 case PROPERTY_ID_EFFECTIVE_DEFAULT:
1077 case PROPERTY_ID_EFFECTIVE_VALUE:
1079 // and the supplier is really available
1080 Reference< XNumberFormatsSupplier > xSupplier;
1081 m_xComponent->getPropertyValue( PROPERTY_FORMATSSUPPLIER ) >>= xSupplier;
1082 if (xSupplier.is())
1084 Reference< XUnoTunnel > xTunnel(xSupplier,UNO_QUERY);
1085 DBG_ASSERT(xTunnel.is(), "FormComponentPropertyHandler::describePropertyLine : xTunnel is invalid!");
1086 SvNumberFormatsSupplierObj* pSupplier = reinterpret_cast<SvNumberFormatsSupplierObj*>(xTunnel->getSomething(SvNumberFormatsSupplierObj::getUnoTunnelId()));
1088 if (pSupplier != nullptr)
1090 bool bIsFormatKey = (PROPERTY_ID_FORMATKEY == nPropId);
1092 bReadOnly = bIsFormatKey;
1094 if ( bIsFormatKey )
1096 OFormatSampleControl* pControl = new OFormatSampleControl( impl_getDefaultDialogParent_nothrow() );
1097 aDescriptor.Control = pControl;
1098 pControl->SetFormatSupplier( pSupplier );
1100 aDescriptor.PrimaryButtonId = UID_PROP_DLG_NUMBER_FORMAT;
1102 else
1104 OFormattedNumericControl* pControl = new OFormattedNumericControl( impl_getDefaultDialogParent_nothrow(), WB_TABSTOP | WB_BORDER );
1105 aDescriptor.Control = pControl;
1107 FormatDescription aDesc;
1108 aDesc.pSupplier = pSupplier;
1109 Any aFormatKeyValue = m_xComponent->getPropertyValue(PROPERTY_FORMATKEY);
1110 if ( !( aFormatKeyValue >>= aDesc.nKey ) )
1111 aDesc.nKey = 0;
1113 pControl->SetFormatDescription( aDesc );
1118 break;
1120 case PROPERTY_ID_DATEMIN:
1121 case PROPERTY_ID_DATEMAX:
1122 case PROPERTY_ID_DEFAULT_DATE:
1123 case PROPERTY_ID_DATE:
1124 nControlType = PropertyControlType::DateField;
1125 break;
1127 case PROPERTY_ID_TIMEMIN:
1128 case PROPERTY_ID_TIMEMAX:
1129 case PROPERTY_ID_DEFAULT_TIME:
1130 case PROPERTY_ID_TIME:
1131 nControlType = PropertyControlType::TimeField;
1132 break;
1134 case PROPERTY_ID_VALUEMIN:
1135 case PROPERTY_ID_VALUEMAX:
1136 case PROPERTY_ID_DEFAULT_VALUE:
1137 case PROPERTY_ID_VALUE:
1139 OFormattedNumericControl* pControl = new OFormattedNumericControl( impl_getDefaultDialogParent_nothrow(), WB_TABSTOP | WB_BORDER | WB_SPIN | WB_REPEAT );
1140 aDescriptor.Control = pControl;
1142 // we don't set a formatter so the control uses a default (which uses the application
1143 // language and a default numeric format)
1144 // but we set the decimal digits
1145 pControl->SetDecimalDigits(
1146 ::comphelper::getINT16( m_xComponent->getPropertyValue( PROPERTY_DECIMAL_ACCURACY ) )
1149 // and the thousands separator
1150 pControl->SetThousandsSep(
1151 ::comphelper::getBOOL( m_xComponent->getPropertyValue(PROPERTY_SHOWTHOUSANDSEP) )
1154 // and the default value for the property
1157 if (m_xPropertyState.is() && ((PROPERTY_ID_VALUEMIN == nPropId) || (PROPERTY_ID_VALUEMAX == nPropId)))
1159 double nDefault = 0;
1160 if ( m_xPropertyState->getPropertyDefault( aProperty.Name ) >>= nDefault )
1161 pControl->SetDefaultValue( nDefault );
1164 catch (const Exception&)
1166 // just ignore it
1169 // and allow empty values only for the default value and the value
1170 pControl->EnableEmptyField( ( PROPERTY_ID_DEFAULT_VALUE == nPropId )
1171 || ( PROPERTY_ID_VALUE == nPropId ) );
1173 break;
1175 default:
1176 if ( TypeClass_BYTE <= eType && eType <= TypeClass_DOUBLE )
1178 sal_Int16 nDigits = 0;
1179 sal_Int16 nValueUnit = -1;
1180 sal_Int16 nDisplayUnit = -1;
1181 if ( m_eComponentClass == eFormControl )
1183 if ( ( nPropId == PROPERTY_ID_WIDTH )
1184 || ( nPropId == PROPERTY_ID_ROWHEIGHT )
1185 || ( nPropId == PROPERTY_ID_HEIGHT )
1188 nValueUnit = MeasureUnit::MM_10TH;
1189 nDisplayUnit = impl_getDocumentMeasurementUnit_throw();
1190 nDigits = 2;
1194 Optional< double > aValueNotPresent( false, 0 );
1195 aDescriptor.Control = PropertyHandlerHelper::createNumericControl(
1196 _rxControlFactory, nDigits, aValueNotPresent, aValueNotPresent );
1198 Reference< XNumericControl > xNumericControl( aDescriptor.Control, UNO_QUERY_THROW );
1199 if ( nValueUnit != -1 )
1200 xNumericControl->setValueUnit( nValueUnit );
1201 if ( nDisplayUnit != -1 )
1202 xNumericControl->setDisplayUnit( nDisplayUnit );
1204 break;
1208 if ( eType == TypeClass_SEQUENCE )
1209 nControlType = PropertyControlType::StringListField;
1211 // boolean values
1212 if ( eType == TypeClass_BOOLEAN )
1214 if ( ( nPropId == PROPERTY_ID_SHOW_POSITION )
1215 || ( nPropId == PROPERTY_ID_SHOW_NAVIGATION )
1216 || ( nPropId == PROPERTY_ID_SHOW_RECORDACTIONS )
1217 || ( nPropId == PROPERTY_ID_SHOW_FILTERSORT )
1220 aDescriptor.Control = PropertyHandlerHelper::createListBoxControl(_rxControlFactory, RID_RSC_ENUM_SHOWHIDE, SAL_N_ELEMENTS(RID_RSC_ENUM_SHOWHIDE), false);
1222 else
1223 aDescriptor.Control = PropertyHandlerHelper::createListBoxControl(_rxControlFactory, RID_RSC_ENUM_YESNO, SAL_N_ELEMENTS(RID_RSC_ENUM_YESNO), false);
1224 bNeedDefaultStringIfVoidAllowed = true;
1228 // enum properties
1229 sal_uInt32 nPropertyUIFlags = m_pInfoService->getPropertyUIFlags( nPropId );
1230 bool bIsEnumProperty = ( nPropertyUIFlags & PROP_FLAG_ENUM ) != 0;
1231 if ( bIsEnumProperty || ( PROPERTY_ID_TARGET_FRAME == nPropId ) )
1233 std::vector< OUString > aEnumValues = m_pInfoService->getPropertyEnumRepresentations( nPropId );
1234 std::vector< OUString >::const_iterator pStart = aEnumValues.begin();
1235 std::vector< OUString >::const_iterator pEnd = aEnumValues.end();
1237 // for a checkbox: if "ambiguous" is not allowed, remove this from the sequence
1238 if ( ( PROPERTY_ID_DEFAULT_STATE == nPropId )
1239 || ( PROPERTY_ID_STATE == nPropId )
1242 if ( impl_componentHasProperty_throw( PROPERTY_TRISTATE ) )
1244 if ( !::comphelper::getBOOL( m_xComponent->getPropertyValue( PROPERTY_TRISTATE ) ) )
1245 { // remove the last sequence element
1246 if ( pEnd > pStart )
1247 --pEnd;
1250 else
1251 --pEnd;
1254 if ( PROPERTY_ID_LISTSOURCETYPE == nPropId )
1255 if ( FormComponentType::COMBOBOX == m_nClassId )
1256 // remove the first sequence element -> value list not possible for combo boxes
1257 ++pStart;
1259 // copy the sequence
1260 std::vector< OUString > aListEntries( pEnd - pStart );
1261 std::copy( pStart, pEnd, aListEntries.begin() );
1263 // create the control
1264 if ( PROPERTY_ID_TARGET_FRAME == nPropId )
1265 aDescriptor.Control = PropertyHandlerHelper::createComboBoxControl( _rxControlFactory, aListEntries, false );
1266 else
1268 aDescriptor.Control = PropertyHandlerHelper::createListBoxControl( _rxControlFactory, aListEntries, false, false );
1269 bNeedDefaultStringIfVoidAllowed = true;
1274 switch( nPropId )
1276 case PROPERTY_ID_REPEAT_DELAY:
1278 OTimeDurationControl* pControl = new OTimeDurationControl( impl_getDefaultDialogParent_nothrow() );
1279 aDescriptor.Control = pControl;
1281 pControl->setMinValue( Optional< double >( true, 0 ) );
1282 pControl->setMaxValue( Optional< double >( true, std::numeric_limits< double >::max() ) );
1284 break;
1286 case PROPERTY_ID_TABINDEX:
1287 case PROPERTY_ID_BOUNDCOLUMN:
1288 case PROPERTY_ID_VISIBLESIZE:
1289 case PROPERTY_ID_MAXTEXTLEN:
1290 case PROPERTY_ID_LINEINCREMENT:
1291 case PROPERTY_ID_BLOCKINCREMENT:
1292 case PROPERTY_ID_SPININCREMENT:
1294 Optional< double > aMinValue( true, 0 );
1295 Optional< double > aMaxValue( true, 0x7FFFFFFF );
1297 if ( nPropId == PROPERTY_ID_MAXTEXTLEN || nPropId == PROPERTY_ID_BOUNDCOLUMN )
1298 aMinValue.Value = -1;
1299 else if ( nPropId == PROPERTY_ID_VISIBLESIZE )
1300 aMinValue.Value = 1;
1301 else
1302 aMinValue.Value = 0;
1304 aDescriptor.Control = PropertyHandlerHelper::createNumericControl(
1305 _rxControlFactory, 0, aMinValue, aMaxValue );
1307 break;
1309 case PROPERTY_ID_DECIMAL_ACCURACY:
1311 Optional< double > aMinValue( true, 0 );
1312 Optional< double > aMaxValue( true, 20 );
1314 aDescriptor.Control = PropertyHandlerHelper::createNumericControl(
1315 _rxControlFactory, 0, aMinValue, aMaxValue );
1317 break;
1320 // DataSource
1321 case PROPERTY_ID_DATASOURCE:
1323 aDescriptor.PrimaryButtonId = UID_PROP_DLG_ATTR_DATASOURCE;
1325 std::vector< OUString > aListEntries;
1327 Reference< XDatabaseContext > xDatabaseContext = sdb::DatabaseContext::create( m_xContext );
1328 Sequence< OUString > aDatasources = xDatabaseContext->getElementNames();
1329 aListEntries.resize( aDatasources.getLength() );
1330 std::copy( aDatasources.begin(), aDatasources.end(), aListEntries.begin() );
1331 aDescriptor.Control = PropertyHandlerHelper::createComboBoxControl(
1332 _rxControlFactory, aListEntries, true );
1334 break;
1336 case PROPERTY_ID_CONTROLSOURCE:
1338 std::vector< OUString > aFieldNames;
1339 impl_initFieldList_nothrow( aFieldNames );
1340 aDescriptor.Control = PropertyHandlerHelper::createComboBoxControl(
1341 _rxControlFactory, aFieldNames, false );
1343 break;
1345 case PROPERTY_ID_COMMAND:
1346 impl_describeCursorSource_nothrow( aDescriptor, _rxControlFactory );
1347 break;
1349 case PROPERTY_ID_LISTSOURCE:
1350 impl_describeListSourceUI_throw( aDescriptor, _rxControlFactory );
1351 break;
1354 if ( !aDescriptor.Control.is() )
1355 aDescriptor.Control = _rxControlFactory->createPropertyControl( nControlType, bReadOnly );
1357 if ( ( aProperty.Attributes & PropertyAttribute::MAYBEVOID ) != 0 )
1359 // insert the string "Default" string, if necessary
1360 if (bNeedDefaultStringIfVoidAllowed)
1362 Reference< XStringListControl > xStringList( aDescriptor.Control, UNO_QUERY_THROW );
1363 xStringList->prependListEntry( m_sDefaultValueString );
1364 m_aPropertiesWithDefListEntry.insert( _rPropertyName );
1368 if ( !aDescriptor.PrimaryButtonId.isEmpty() )
1369 aDescriptor.HasPrimaryButton = true;
1370 if ( !aDescriptor.SecondaryButtonId.isEmpty() )
1371 aDescriptor.HasSecondaryButton = true;
1373 bool bIsDataProperty = ( nPropertyUIFlags & PROP_FLAG_DATA_PROPERTY ) != 0;
1374 aDescriptor.Category = bIsDataProperty ? OUStringLiteral("Data") : OUStringLiteral("General");
1375 return aDescriptor;
1378 InteractiveSelectionResult SAL_CALL FormComponentPropertyHandler::onInteractivePropertySelection( const OUString& _rPropertyName, sal_Bool /*_bPrimary*/, Any& _rData, const Reference< XObjectInspectorUI >& _rxInspectorUI )
1380 if ( !_rxInspectorUI.is() )
1381 throw NullPointerException();
1383 ::osl::ClearableMutexGuard aGuard( m_aMutex );
1384 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
1386 InteractiveSelectionResult eResult = InteractiveSelectionResult_Cancelled;
1387 switch ( nPropId )
1389 case PROPERTY_ID_DEFAULT_SELECT_SEQ:
1390 case PROPERTY_ID_SELECTEDITEMS:
1391 if ( impl_dialogListSelection_nothrow( _rPropertyName, aGuard ) )
1392 eResult = InteractiveSelectionResult_Success;
1393 break;
1395 case PROPERTY_ID_FILTER:
1396 case PROPERTY_ID_SORT:
1398 OUString sClause;
1399 if ( impl_dialogFilterOrSort_nothrow( PROPERTY_ID_FILTER == nPropId, sClause, aGuard ) )
1401 _rData <<= sClause;
1402 eResult = InteractiveSelectionResult_ObtainedValue;
1405 break;
1407 case PROPERTY_ID_MASTERFIELDS:
1408 case PROPERTY_ID_DETAILFIELDS:
1409 if ( impl_dialogLinkedFormFields_nothrow( aGuard ) )
1410 eResult = InteractiveSelectionResult_Success;
1411 break;
1413 case PROPERTY_ID_FORMATKEY:
1414 if ( impl_dialogFormatting_nothrow( _rData, aGuard ) )
1415 eResult = InteractiveSelectionResult_ObtainedValue;
1416 break;
1418 case PROPERTY_ID_IMAGE_URL:
1419 if ( impl_browseForImage_nothrow( _rData, aGuard ) )
1420 eResult = InteractiveSelectionResult_ObtainedValue;
1421 break;
1423 case PROPERTY_ID_TARGET_URL:
1424 if ( impl_browseForTargetURL_nothrow( _rData, aGuard ) )
1425 eResult = InteractiveSelectionResult_ObtainedValue;
1426 break;
1428 case PROPERTY_ID_FONT:
1429 if ( impl_executeFontDialog_nothrow( _rData, aGuard ) )
1430 eResult = InteractiveSelectionResult_ObtainedValue;
1431 break;
1433 case PROPERTY_ID_DATASOURCE:
1434 if ( impl_browseForDatabaseDocument_throw( _rData, aGuard ) )
1435 eResult = InteractiveSelectionResult_ObtainedValue;
1436 break;
1438 case PROPERTY_ID_BACKGROUNDCOLOR:
1439 case PROPERTY_ID_FILLCOLOR:
1440 case PROPERTY_ID_SYMBOLCOLOR:
1441 case PROPERTY_ID_BORDERCOLOR:
1442 case PROPERTY_ID_GRIDLINECOLOR:
1443 case PROPERTY_ID_HEADERBACKGROUNDCOLOR:
1444 case PROPERTY_ID_HEADERTEXTCOLOR:
1445 case PROPERTY_ID_ACTIVESELECTIONBACKGROUNDCOLOR:
1446 case PROPERTY_ID_ACTIVESELECTIONTEXTCOLOR:
1447 case PROPERTY_ID_INACTIVESELECTIONBACKGROUNDCOLOR:
1448 case PROPERTY_ID_INACTIVESELECTIONTEXTCOLOR:
1449 if ( impl_dialogColorChooser_throw( nPropId, _rData, aGuard ) )
1450 eResult = InteractiveSelectionResult_ObtainedValue;
1451 break;
1453 case PROPERTY_ID_CONTROLLABEL:
1454 if ( impl_dialogChooseLabelControl_nothrow( _rData, aGuard ) )
1455 eResult = InteractiveSelectionResult_ObtainedValue;
1456 break;
1458 case PROPERTY_ID_TABINDEX:
1459 if ( impl_dialogChangeTabOrder_nothrow( aGuard ) )
1460 eResult = InteractiveSelectionResult_Success;
1461 break;
1463 case PROPERTY_ID_COMMAND:
1464 case PROPERTY_ID_LISTSOURCE:
1465 if ( impl_doDesignSQLCommand_nothrow( _rxInspectorUI, nPropId ) )
1466 eResult = InteractiveSelectionResult_Pending;
1467 break;
1468 default:
1469 OSL_FAIL( "FormComponentPropertyHandler::onInteractivePropertySelection: request for a property which does not have dedicated UI!" );
1470 break;
1472 return eResult;
1475 namespace
1477 void lcl_rebuildAndResetCommand( const Reference< XObjectInspectorUI >& _rxInspectorUI, const Reference< XPropertyHandler >& _rxHandler )
1479 OSL_PRECOND( _rxInspectorUI.is(), "lcl_rebuildAndResetCommand: invalid BrowserUI!" );
1480 OSL_PRECOND( _rxHandler.is(), "lcl_rebuildAndResetCommand: invalid handler!" );
1481 _rxInspectorUI->rebuildPropertyUI( PROPERTY_COMMAND );
1482 _rxHandler->setPropertyValue( PROPERTY_COMMAND, makeAny( OUString() ) );
1486 void SAL_CALL FormComponentPropertyHandler::actuatingPropertyChanged( const OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool _bFirstTimeInit )
1488 if ( !_rxInspectorUI.is() )
1489 throw NullPointerException();
1491 ::osl::MutexGuard aGuard( m_aMutex );
1492 PropertyId nActuatingPropId( impl_getPropertyId_nothrow( _rActuatingPropertyName ) );
1494 std::vector< PropertyId > aDependentProperties;
1496 switch ( nActuatingPropId )
1498 // ----- EscapeProcessing -----
1499 case PROPERTY_ID_ESCAPE_PROCESSING:
1500 aDependentProperties.push_back( PROPERTY_ID_FILTER );
1501 aDependentProperties.push_back( PROPERTY_ID_SORT );
1502 break; // case PROPERTY_ID_ESCAPE_PROCESSING
1504 // ----- CommandType -----
1505 case PROPERTY_ID_COMMANDTYPE:
1506 // available commands (tables or queries) might have changed
1507 if ( !_bFirstTimeInit && m_bHaveCommand )
1508 lcl_rebuildAndResetCommand( _rxInspectorUI, this );
1509 aDependentProperties.push_back( PROPERTY_ID_COMMAND );
1510 break; // case PROPERTY_ID_COMMANDTYPE
1512 // ----- DataSourceName -----
1513 case PROPERTY_ID_DATASOURCE:
1514 // reset the connection, now that we have a new data source
1515 m_xRowSetConnection.clear();
1517 // available list source values (tables or queries) might have changed
1518 if ( !_bFirstTimeInit && m_bHaveListSource )
1519 _rxInspectorUI->rebuildPropertyUI( PROPERTY_LISTSOURCE );
1521 // available commands (tables or queries) might have changed
1522 if ( !_bFirstTimeInit && m_bHaveCommand )
1523 lcl_rebuildAndResetCommand( _rxInspectorUI, this );
1525 // Command also depends on DataSource
1526 aDependentProperties.push_back( PROPERTY_ID_COMMAND );
1527 [[fallthrough]];
1529 // ----- Command -----
1530 case PROPERTY_ID_COMMAND:
1531 aDependentProperties.push_back( PROPERTY_ID_FILTER );
1532 aDependentProperties.push_back( PROPERTY_ID_SORT );
1533 if ( m_bComponentIsSubForm )
1534 aDependentProperties.push_back( PROPERTY_ID_DETAILFIELDS );
1535 break;
1537 // ----- ListSourceType -----
1538 case PROPERTY_ID_LISTSOURCETYPE:
1539 if ( !_bFirstTimeInit && m_bHaveListSource )
1540 // available list source values (tables or queries) might have changed
1541 _rxInspectorUI->rebuildPropertyUI( PROPERTY_LISTSOURCE );
1542 aDependentProperties.push_back( PROPERTY_ID_STRINGITEMLIST );
1543 aDependentProperties.push_back( PROPERTY_ID_TYPEDITEMLIST );
1544 aDependentProperties.push_back( PROPERTY_ID_BOUNDCOLUMN );
1545 [[fallthrough]];
1547 // ----- StringItemList -----
1548 case PROPERTY_ID_STRINGITEMLIST:
1549 aDependentProperties.push_back( PROPERTY_ID_TYPEDITEMLIST );
1550 aDependentProperties.push_back( PROPERTY_ID_SELECTEDITEMS );
1551 aDependentProperties.push_back( PROPERTY_ID_DEFAULT_SELECT_SEQ );
1552 break;
1554 // ----- ListSource -----
1555 case PROPERTY_ID_LISTSOURCE:
1556 aDependentProperties.push_back( PROPERTY_ID_STRINGITEMLIST );
1557 aDependentProperties.push_back( PROPERTY_ID_TYPEDITEMLIST );
1558 break;
1560 // ----- DataField -----
1561 case PROPERTY_ID_CONTROLSOURCE:
1563 OUString sControlSource;
1564 _rNewValue >>= sControlSource;
1565 if ( impl_componentHasProperty_throw( PROPERTY_FILTERPROPOSAL ) )
1566 _rxInspectorUI->enablePropertyUI( PROPERTY_FILTERPROPOSAL, !sControlSource.isEmpty() );
1567 if ( impl_componentHasProperty_throw( PROPERTY_EMPTY_IS_NULL ) )
1568 _rxInspectorUI->enablePropertyUI( PROPERTY_EMPTY_IS_NULL, !sControlSource.isEmpty() );
1570 aDependentProperties.push_back( PROPERTY_ID_BOUNDCOLUMN );
1571 aDependentProperties.push_back( PROPERTY_ID_SCALEIMAGE );
1572 aDependentProperties.push_back( PROPERTY_ID_SCALE_MODE );
1573 aDependentProperties.push_back( PROPERTY_ID_INPUT_REQUIRED );
1575 break;
1577 case PROPERTY_ID_EMPTY_IS_NULL:
1578 aDependentProperties.push_back( PROPERTY_ID_INPUT_REQUIRED );
1579 break;
1581 // ----- SubmitEncoding -----
1582 case PROPERTY_ID_SUBMIT_ENCODING:
1584 FormSubmitEncoding eEncoding = FormSubmitEncoding_URL;
1585 if( ! (_rNewValue >>= eEncoding) )
1586 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_SUBMIT_ENCODING);
1587 _rxInspectorUI->enablePropertyUI( PROPERTY_SUBMIT_METHOD, eEncoding == FormSubmitEncoding_URL );
1589 break;
1591 // ----- Repeat -----
1592 case PROPERTY_ID_REPEAT:
1594 bool bIsRepeating = false;
1595 if( ! (_rNewValue >>= bIsRepeating) )
1596 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_REPEAT);
1597 _rxInspectorUI->enablePropertyUI( PROPERTY_REPEAT_DELAY, bIsRepeating );
1599 break;
1601 // ----- TabStop -----
1602 case PROPERTY_ID_TABSTOP:
1604 if ( !impl_componentHasProperty_throw( PROPERTY_TABINDEX ) )
1605 break;
1606 bool bHasTabStop = false;
1607 _rNewValue >>= bHasTabStop;
1608 _rxInspectorUI->enablePropertyUI( PROPERTY_TABINDEX, bHasTabStop );
1610 break;
1612 // ----- Border -----
1613 case PROPERTY_ID_BORDER:
1615 sal_Int16 nBordeType = VisualEffect::NONE;
1616 if( ! (_rNewValue >>= nBordeType) )
1617 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_BORDER);
1618 _rxInspectorUI->enablePropertyUI( PROPERTY_BORDERCOLOR, nBordeType == VisualEffect::FLAT );
1620 break;
1622 // ----- DropDown -----
1623 case PROPERTY_ID_DROPDOWN:
1625 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_LINECOUNT ) )
1627 bool bDropDown = true;
1628 _rNewValue >>= bDropDown;
1629 _rxInspectorUI->enablePropertyUI( PROPERTY_LINECOUNT, bDropDown );
1632 break;
1634 // ----- ImageURL -----
1635 case PROPERTY_ID_IMAGE_URL:
1637 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_IMAGEPOSITION ) )
1639 OUString sImageURL;
1640 if( ! (_rNewValue >>= sImageURL) )
1641 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_IMAGE_URL);
1642 _rxInspectorUI->enablePropertyUI( PROPERTY_IMAGEPOSITION, !sImageURL.isEmpty() );
1645 aDependentProperties.push_back( PROPERTY_ID_SCALEIMAGE );
1646 aDependentProperties.push_back( PROPERTY_ID_SCALE_MODE );
1648 break;
1650 // ----- ButtonType -----
1651 case PROPERTY_ID_BUTTONTYPE:
1653 FormButtonType eButtonType( FormButtonType_PUSH );
1654 if( ! (_rNewValue >>= eButtonType) )
1655 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_BUTTONTYPE);
1656 _rxInspectorUI->enablePropertyUI( PROPERTY_TARGET_URL, FormButtonType_URL == eButtonType );
1657 [[fallthrough]];
1660 // ----- TargetURL -----
1661 case PROPERTY_ID_TARGET_URL:
1662 aDependentProperties.push_back( PROPERTY_ID_TARGET_FRAME );
1663 break; // case PROPERTY_ID_TARGET_URL
1665 // ----- TriState -----
1666 case PROPERTY_ID_TRISTATE:
1667 if ( !_bFirstTimeInit )
1668 _rxInspectorUI->rebuildPropertyUI( m_eComponentClass == eFormControl ? OUString(PROPERTY_DEFAULT_STATE) : OUString(PROPERTY_STATE) );
1669 break; // case PROPERTY_ID_TRISTATE
1671 // ----- DecimalAccuracy -----
1672 case PROPERTY_ID_DECIMAL_ACCURACY:
1673 // ----- ShowThousandsSeparator -----
1674 case PROPERTY_ID_SHOWTHOUSANDSEP:
1676 bool bAccuracy = (PROPERTY_ID_DECIMAL_ACCURACY == nActuatingPropId);
1677 sal_uInt16 nNewDigits = 0;
1678 bool bUseSep = false;
1679 if ( bAccuracy )
1681 if( ! (_rNewValue >>= nNewDigits) )
1682 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_DECIMAL_ACCURACY);
1684 else
1686 if( ! (_rNewValue >>= bUseSep) )
1687 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_SHOWTHOUSANDSEP);
1690 // propagate the changes to the min/max/default fields
1691 OUString aAffectedProps[] = { OUString(PROPERTY_VALUE), OUString(PROPERTY_DEFAULT_VALUE), OUString(PROPERTY_VALUEMIN), OUString(PROPERTY_VALUEMAX) };
1692 for (const OUString & aAffectedProp : aAffectedProps)
1694 Reference< XPropertyControl > xControl;
1697 xControl = _rxInspectorUI->getPropertyControl( aAffectedProp );
1699 catch( const UnknownPropertyException& ) {}
1700 if ( xControl.is() )
1702 OFormattedNumericControl* pControl = dynamic_cast< OFormattedNumericControl* >( xControl.get() );
1703 DBG_ASSERT( pControl, "FormComponentPropertyHandler::actuatingPropertyChanged: invalid control!" );
1704 if ( pControl )
1706 if ( bAccuracy )
1707 pControl->SetDecimalDigits( nNewDigits );
1708 else
1709 pControl->SetThousandsSep( bUseSep );
1714 break;
1716 // ----- FormatKey -----
1717 case PROPERTY_ID_FORMATKEY:
1719 FormatDescription aNewDesc;
1721 Reference< XNumberFormatsSupplier > xSupplier;
1722 if( ! (m_xComponent->getPropertyValue( PROPERTY_FORMATSSUPPLIER ) >>= xSupplier) )
1723 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_FORMATKEY);
1725 Reference< XUnoTunnel > xTunnel( xSupplier, UNO_QUERY );
1726 DBG_ASSERT(xTunnel.is(), "FormComponentPropertyHandler::actuatingPropertyChanged: xTunnel is invalid!");
1727 if ( xTunnel.is() )
1729 SvNumberFormatsSupplierObj* pSupplier = reinterpret_cast<SvNumberFormatsSupplierObj*>(xTunnel->getSomething(SvNumberFormatsSupplierObj::getUnoTunnelId()));
1730 // the same again
1732 aNewDesc.pSupplier = pSupplier;
1733 if ( !( _rNewValue >>= aNewDesc.nKey ) )
1734 aNewDesc.nKey = 0;
1736 // give each control which has to know this an own copy of the description
1737 OUString aFormattedPropertyControls[] = {
1738 OUString(PROPERTY_EFFECTIVE_MIN), OUString(PROPERTY_EFFECTIVE_MAX), OUString(PROPERTY_EFFECTIVE_DEFAULT), OUString(PROPERTY_EFFECTIVE_VALUE)
1740 for (const OUString & aFormattedPropertyControl : aFormattedPropertyControls)
1742 Reference< XPropertyControl > xControl;
1745 xControl = _rxInspectorUI->getPropertyControl( aFormattedPropertyControl );
1747 catch( const UnknownPropertyException& ) {}
1748 if ( xControl.is() )
1750 OFormattedNumericControl* pControl = dynamic_cast< OFormattedNumericControl* >( xControl.get() );
1751 DBG_ASSERT( pControl, "FormComponentPropertyHandler::actuatingPropertyChanged: invalid control!" );
1752 if ( pControl )
1753 pControl->SetFormatDescription( aNewDesc );
1758 break;
1760 case PROPERTY_ID_TOGGLE:
1762 bool bIsToggleButton = false;
1763 if( ! (_rNewValue >>= bIsToggleButton) )
1764 SAL_WARN("extensions.propctrlr", "actuatingPropertyChanged: unable to get property " << PROPERTY_ID_TOGGLE);
1765 _rxInspectorUI->enablePropertyUI( PROPERTY_DEFAULT_STATE, bIsToggleButton );
1767 break;
1768 case -1:
1769 throw RuntimeException();
1770 break;
1771 default:
1772 OSL_FAIL( "FormComponentPropertyHandler::actuatingPropertyChanged: did not register for this property!" );
1773 break;
1775 } // switch ( nActuatingPropId )
1777 for (auto const& dependentProperty : aDependentProperties)
1779 if ( impl_isSupportedProperty_nothrow(dependentProperty) )
1780 impl_updateDependentProperty_nothrow(dependentProperty, _rxInspectorUI);
1784 void FormComponentPropertyHandler::impl_updateDependentProperty_nothrow( PropertyId _nPropId, const Reference< XObjectInspectorUI >& _rxInspectorUI ) const
1788 switch ( _nPropId )
1790 // ----- StringItemList -----
1791 case PROPERTY_ID_STRINGITEMLIST:
1793 ListSourceType eLSType = ListSourceType_VALUELIST;
1794 if( ! (impl_getPropertyValue_throw( PROPERTY_LISTSOURCETYPE ) >>= eLSType) )
1795 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " PROPERTY_LISTSOURCETYPE);
1797 OUString sListSource;
1799 Sequence< OUString > aListSource;
1800 Any aListSourceValue( impl_getPropertyValue_throw( PROPERTY_LISTSOURCE ) );
1801 if ( aListSourceValue >>= aListSource )
1803 if ( aListSource.hasElements() )
1804 sListSource = aListSource[0];
1806 else
1807 if( ! (aListSourceValue >>= sListSource) )
1808 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " PROPERTY_LISTSOURCE);
1811 bool bIsEnabled = ( ( eLSType == ListSourceType_VALUELIST )
1812 || ( sListSource.isEmpty() )
1814 _rxInspectorUI->enablePropertyUI( PROPERTY_STRINGITEMLIST, bIsEnabled );
1816 break; // case PROPERTY_ID_STRINGITEMLIST
1818 // ----- TypedItemList -----
1819 case PROPERTY_ID_TYPEDITEMLIST:
1821 /* TODO: anything? */
1823 break; // case PROPERTY_ID_TYPEDITEMLIST
1825 // ----- BoundColumn -----
1826 case PROPERTY_ID_BOUNDCOLUMN:
1828 ListSourceType eLSType = ListSourceType_VALUELIST;
1829 if( ! (impl_getPropertyValue_throw( PROPERTY_LISTSOURCETYPE ) >>= eLSType) )
1830 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " PROPERTY_LISTSOURCETYPE);
1832 _rxInspectorUI->enablePropertyUI( PROPERTY_BOUNDCOLUMN,
1833 ( eLSType != ListSourceType_VALUELIST )
1836 break; // case PROPERTY_ID_BOUNDCOLUMN
1838 // ----- ScaleImage, ScaleMode -----
1839 case PROPERTY_ID_SCALEIMAGE:
1840 case PROPERTY_ID_SCALE_MODE:
1842 OUString sControlSource;
1843 if ( impl_isSupportedProperty_nothrow( PROPERTY_ID_CONTROLSOURCE ) )
1844 impl_getPropertyValue_throw( PROPERTY_CONTROLSOURCE ) >>= sControlSource;
1846 OUString sImageURL;
1847 impl_getPropertyValue_throw( PROPERTY_IMAGE_URL ) >>= sImageURL;
1849 _rxInspectorUI->enablePropertyUI( impl_getPropertyNameFromId_nothrow( _nPropId ),
1850 ( !sControlSource.isEmpty() ) || ( !sImageURL.isEmpty() )
1853 break; // case PROPERTY_ID_SCALEIMAGE, PROPERTY_ID_SCALE_MODE
1855 // ----- InputRequired -----
1856 case PROPERTY_ID_INPUT_REQUIRED:
1858 OUString sControlSource;
1859 if( ! (impl_getPropertyValue_throw( PROPERTY_CONTROLSOURCE ) >>= sControlSource) )
1860 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " PROPERTY_CONTROLSOURCE);
1862 bool bEmptyIsNULL = false;
1863 bool bHasEmptyIsNULL = impl_componentHasProperty_throw( PROPERTY_EMPTY_IS_NULL );
1864 if ( bHasEmptyIsNULL )
1865 if( ! (impl_getPropertyValue_throw( PROPERTY_EMPTY_IS_NULL ) >>= bEmptyIsNULL) )
1866 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " PROPERTY_EMPTY_IS_NULL);
1868 // if the control is not bound to a DB field, there is no sense in having the "Input required"
1869 // property
1870 // Also, if an empty input of this control are *not* written as NULL, but as empty strings,
1871 // then "Input required" does not make sense, too (since there's always an input, even if the control
1872 // is empty).
1873 _rxInspectorUI->enablePropertyUI( PROPERTY_INPUT_REQUIRED,
1874 ( !sControlSource.isEmpty() ) && ( !bHasEmptyIsNULL || bEmptyIsNULL )
1877 break;
1879 // ----- SelectedItems, DefaultSelection -----
1880 case PROPERTY_ID_SELECTEDITEMS:
1881 case PROPERTY_ID_DEFAULT_SELECT_SEQ:
1883 Sequence< OUString > aEntries;
1884 impl_getPropertyValue_throw( PROPERTY_STRINGITEMLIST ) >>= aEntries;
1885 bool isEnabled = aEntries.hasElements();
1887 if ( ( m_nClassId == FormComponentType::LISTBOX ) && ( m_eComponentClass == eFormControl ) )
1889 ListSourceType eLSType = ListSourceType_VALUELIST;
1890 impl_getPropertyValue_throw( PROPERTY_LISTSOURCETYPE ) >>= eLSType;
1891 isEnabled &= ( eLSType == ListSourceType_VALUELIST );
1893 _rxInspectorUI->enablePropertyUIElements( impl_getPropertyNameFromId_nothrow( _nPropId ),
1894 PropertyLineElement::PrimaryButton, isEnabled );
1896 break; // case PROPERTY_ID_DEFAULT_SELECT_SEQ
1898 // ----- TargetFrame ------
1899 case PROPERTY_ID_TARGET_FRAME:
1901 OUString sTargetURL;
1902 impl_getPropertyValue_throw( PROPERTY_TARGET_URL ) >>= sTargetURL;
1903 FormButtonType eButtonType( FormButtonType_URL );
1904 if ( 0 != m_nClassId )
1906 if( ! (impl_getPropertyValue_throw( PROPERTY_BUTTONTYPE ) >>= eButtonType) )
1907 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " PROPERTY_BUTTONTYPE);
1909 // if m_nClassId is 0, then we're inspecting a form. In this case, eButtonType is always
1910 // FormButtonType_URL here
1911 _rxInspectorUI->enablePropertyUI( PROPERTY_TARGET_FRAME,
1912 ( eButtonType == FormButtonType_URL ) && ( !sTargetURL.isEmpty() )
1915 break;
1917 // ----- Order ------
1918 case PROPERTY_ID_SORT:
1919 // ----- Filter ------
1920 case PROPERTY_ID_FILTER:
1922 Reference< XConnection > xConnection;
1923 bool bAllowEmptyDS = ::dbtools::isEmbeddedInDatabase( m_xComponent, xConnection );
1925 // if there's no escape processing, we cannot enter any values for this property
1926 bool bDoEscapeProcessing( false );
1927 impl_getPropertyValue_throw( PROPERTY_ESCAPE_PROCESSING ) >>= bDoEscapeProcessing;
1928 _rxInspectorUI->enablePropertyUI(
1929 impl_getPropertyNameFromId_nothrow( _nPropId ),
1930 bDoEscapeProcessing
1933 // also care for the browse button - enabled if we have escape processing, and a valid
1934 // data source signature
1935 _rxInspectorUI->enablePropertyUIElements(
1936 impl_getPropertyNameFromId_nothrow( _nPropId ),
1937 PropertyLineElement::PrimaryButton,
1938 impl_hasValidDataSourceSignature_nothrow( m_xComponent, bAllowEmptyDS )
1939 && bDoEscapeProcessing
1942 break; // case PROPERTY_ID_FILTER:
1944 // ----- Command -----
1945 case PROPERTY_ID_COMMAND:
1947 sal_Int32 nCommandType( CommandType::COMMAND );
1948 if( ! (impl_getPropertyValue_throw( PROPERTY_COMMANDTYPE ) >>= nCommandType) )
1949 SAL_WARN("extensions.propctrlr", "impl_updateDependentProperty_nothrow: unable to get property " PROPERTY_COMMANDTYPE);
1951 impl_ensureRowsetConnection_nothrow();
1952 Reference< XConnection > xConnection = m_xRowSetConnection.getTyped();
1953 bool bAllowEmptyDS = false;
1954 if ( !xConnection.is() )
1955 bAllowEmptyDS = ::dbtools::isEmbeddedInDatabase( m_xComponent, xConnection );
1957 bool doEnable = ( nCommandType == CommandType::COMMAND )
1958 && ( m_xRowSetConnection.is()
1959 || xConnection.is()
1960 || impl_hasValidDataSourceSignature_nothrow( m_xComponent, bAllowEmptyDS)
1963 _rxInspectorUI->enablePropertyUIElements(
1964 PROPERTY_COMMAND,
1965 PropertyLineElement::PrimaryButton,
1966 doEnable
1969 break; // case PROPERTY_ID_COMMAND
1971 // ----- DetailFields -----
1972 case PROPERTY_ID_DETAILFIELDS:
1974 Reference< XConnection > xConnection;
1975 bool bAllowEmptyDS = ::dbtools::isEmbeddedInDatabase( m_xComponent, xConnection );
1977 // both our current form, and its parent form, need to have a valid
1978 // data source signature
1979 bool bDoEnableMasterDetailFields =
1980 impl_hasValidDataSourceSignature_nothrow( m_xComponent, bAllowEmptyDS )
1981 && impl_hasValidDataSourceSignature_nothrow( Reference< XPropertySet >( m_xObjectParent, UNO_QUERY ), bAllowEmptyDS );
1983 // in opposite to the other properties, here in real *two* properties are
1984 // affected
1985 _rxInspectorUI->enablePropertyUIElements( PROPERTY_DETAILFIELDS, PropertyLineElement::PrimaryButton, bDoEnableMasterDetailFields );
1986 _rxInspectorUI->enablePropertyUIElements( PROPERTY_MASTERFIELDS, PropertyLineElement::PrimaryButton, bDoEnableMasterDetailFields );
1988 break;
1990 default:
1991 OSL_FAIL( "FormComponentPropertyHandler::impl_updateDependentProperty_nothrow: unexpected property to update!" );
1992 break;
1994 } // switch
1996 catch( const Exception& )
1998 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
1999 OSL_FAIL( "FormComponentPropertyHandler::impl_updateDependentProperty_nothrow: caught an exception!" );
2003 void SAL_CALL FormComponentPropertyHandler::disposing()
2005 FormComponentPropertyHandler_Base::disposing();
2006 if ( m_xCommandDesigner.is() && m_xCommandDesigner->isActive() )
2007 m_xCommandDesigner->dispose();
2010 sal_Bool SAL_CALL FormComponentPropertyHandler::suspend( sal_Bool _bSuspend )
2012 ::osl::MutexGuard aGuard( m_aMutex );
2013 if ( _bSuspend )
2014 if ( m_xCommandDesigner.is() && m_xCommandDesigner->isActive() )
2015 return m_xCommandDesigner->suspend();
2016 return true;
2019 void FormComponentPropertyHandler::onNewComponent()
2021 FormComponentPropertyHandler_Base::onNewComponent();
2022 if ( !m_xComponentPropertyInfo.is() && m_xComponent.is() )
2023 throw NullPointerException();
2025 m_xPropertyState.set( m_xComponent, UNO_QUERY );
2026 m_eComponentClass = eUnknown;
2027 m_bComponentIsSubForm = m_bHaveListSource = m_bHaveCommand = false;
2028 m_nClassId = 0;
2032 // component class
2033 m_eComponentClass = eUnknown;
2035 if ( impl_componentHasProperty_throw( PROPERTY_WIDTH )
2036 && impl_componentHasProperty_throw( PROPERTY_HEIGHT )
2037 && impl_componentHasProperty_throw( PROPERTY_POSITIONX )
2038 && impl_componentHasProperty_throw( PROPERTY_POSITIONY )
2039 && impl_componentHasProperty_throw( PROPERTY_STEP )
2040 && impl_componentHasProperty_throw( PROPERTY_TABINDEX )
2043 m_eComponentClass = eDialogControl;
2045 else
2047 m_eComponentClass = eFormControl;
2051 // (database) sub form?
2052 Reference< XForm > xAsForm( m_xComponent, UNO_QUERY );
2053 if ( xAsForm.is() )
2055 Reference< XForm > xFormsParent( xAsForm->getParent(), css::uno::UNO_QUERY );
2056 m_bComponentIsSubForm = xFormsParent.is();
2060 // ClassId
2061 Reference< XChild > xCompAsChild( m_xComponent, UNO_QUERY );
2062 if ( xCompAsChild.is() )
2063 m_xObjectParent = xCompAsChild->getParent();
2066 // ClassId
2067 impl_classifyControlModel_throw();
2069 catch( const RuntimeException& )
2071 throw;
2073 catch( const Exception& )
2075 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
2076 OSL_FAIL( "FormComponentPropertyHandler::onNewComponent: caught an exception!" );
2080 void FormComponentPropertyHandler::impl_classifyControlModel_throw( )
2082 if ( impl_componentHasProperty_throw( PROPERTY_CLASSID ) )
2084 if( ! (m_xComponent->getPropertyValue( PROPERTY_CLASSID ) >>= m_nClassId) )
2085 SAL_WARN("extensions.propctrlr", "impl_classifyControlModel_throw: unable to get property " PROPERTY_CLASSID);
2087 else if ( eDialogControl == m_eComponentClass )
2089 Reference< XServiceInfo > xServiceInfo( m_xComponent, UNO_QUERY );
2090 if ( xServiceInfo.is() )
2092 // it's a control model, and can tell about it's supported services
2093 m_nClassId = FormComponentType::CONTROL;
2095 const sal_Char* aControlModelServiceNames[] =
2097 "UnoControlButtonModel",
2098 "UnoControlCheckBoxModel",
2099 "UnoControlComboBoxModel",
2100 "UnoControlCurrencyFieldModel",
2101 "UnoControlDateFieldModel",
2102 "UnoControlEditModel",
2103 "UnoControlFileControlModel",
2104 "UnoControlFixedTextModel",
2105 "UnoControlGroupBoxModel",
2106 "UnoControlImageControlModel",
2107 "UnoControlListBoxModel",
2108 "UnoControlNumericFieldModel",
2109 "UnoControlPatternFieldModel",
2110 "UnoControlRadioButtonModel",
2111 "UnoControlScrollBarModel",
2112 "UnoControlSpinButtonModel",
2113 "UnoControlTimeFieldModel",
2115 "UnoControlFixedLineModel",
2116 "UnoControlFormattedFieldModel",
2117 "UnoControlProgressBarModel"
2119 const sal_Int16 nClassIDs[] =
2121 FormComponentType::COMMANDBUTTON,
2122 FormComponentType::CHECKBOX,
2123 FormComponentType::COMBOBOX,
2124 FormComponentType::CURRENCYFIELD,
2125 FormComponentType::DATEFIELD,
2126 FormComponentType::TEXTFIELD,
2127 FormComponentType::FILECONTROL,
2128 FormComponentType::FIXEDTEXT,
2129 FormComponentType::GROUPBOX,
2130 FormComponentType::IMAGECONTROL,
2131 FormComponentType::LISTBOX,
2132 FormComponentType::NUMERICFIELD,
2133 FormComponentType::PATTERNFIELD,
2134 FormComponentType::RADIOBUTTON,
2135 FormComponentType::SCROLLBAR,
2136 FormComponentType::SPINBUTTON,
2137 FormComponentType::TIMEFIELD,
2139 ControlType::FIXEDLINE,
2140 ControlType::FORMATTEDFIELD,
2141 ControlType::PROGRESSBAR
2144 sal_Int32 nKnownControlTypes = SAL_N_ELEMENTS( aControlModelServiceNames );
2145 OSL_ENSURE( nKnownControlTypes == SAL_N_ELEMENTS( nClassIDs ),
2146 "FormComponentPropertyHandler::impl_classifyControlModel_throw: inconsistence" );
2148 for ( sal_Int32 i = 0; i < nKnownControlTypes; ++i )
2150 OUString sServiceName = "com.sun.star.awt." +
2151 OUString::createFromAscii( aControlModelServiceNames[ i ] );
2153 if ( xServiceInfo->supportsService( sServiceName ) )
2155 m_nClassId = nClassIDs[ i ];
2156 break;
2163 void FormComponentPropertyHandler::impl_normalizePropertyValue_nothrow( Any& _rValue, PropertyId _nPropId ) const
2165 switch ( _nPropId )
2167 case PROPERTY_ID_TABSTOP:
2168 if ( !_rValue.hasValue() )
2170 switch ( m_nClassId )
2172 case FormComponentType::COMMANDBUTTON:
2173 case FormComponentType::RADIOBUTTON:
2174 case FormComponentType::CHECKBOX:
2175 case FormComponentType::TEXTFIELD:
2176 case FormComponentType::LISTBOX:
2177 case FormComponentType::COMBOBOX:
2178 case FormComponentType::FILECONTROL:
2179 case FormComponentType::DATEFIELD:
2180 case FormComponentType::TIMEFIELD:
2181 case FormComponentType::NUMERICFIELD:
2182 case ControlType::FORMATTEDFIELD:
2183 case FormComponentType::CURRENCYFIELD:
2184 case FormComponentType::PATTERNFIELD:
2185 _rValue <<= true;
2186 break;
2187 default:
2188 _rValue <<= false;
2189 break;
2192 break;
2196 bool FormComponentPropertyHandler::isReportModel() const
2198 Reference<XModel> xModel(impl_getContextDocument_nothrow());
2199 Reference<XReportDefinition> xReportDef(xModel, css::uno::UNO_QUERY);
2200 return xReportDef.is();
2203 bool FormComponentPropertyHandler::impl_shouldExcludeProperty_nothrow( const Property& _rProperty ) const
2205 OSL_ENSURE( _rProperty.Handle == m_pInfoService->getPropertyId( _rProperty.Name ),
2206 "FormComponentPropertyHandler::impl_shouldExcludeProperty_nothrow: inconsistency in the property!" );
2208 if ( _rProperty.Handle == PROPERTY_ID_CONTROLLABEL )
2209 // prevent that this is caught below
2210 return false;
2212 if ( ( _rProperty.Type.getTypeClass() == TypeClass_INTERFACE )
2213 || ( _rProperty.Type.getTypeClass() == TypeClass_UNKNOWN )
2215 return true;
2217 if ( ( _rProperty.Attributes & PropertyAttribute::TRANSIENT ) && ( m_eComponentClass != eDialogControl ) )
2218 // strange enough, dialog controls declare a lot of their properties as transient
2219 return true;
2221 if ( _rProperty.Attributes & PropertyAttribute::READONLY )
2222 return true;
2224 switch ( _rProperty.Handle )
2226 case PROPERTY_ID_MASTERFIELDS:
2227 case PROPERTY_ID_DETAILFIELDS:
2228 if ( !m_bComponentIsSubForm )
2229 // no master and detail fields for forms which are no sub forms
2230 return true;
2231 break;
2233 case PROPERTY_ID_DATASOURCE:
2235 // don't show DataSource if the component is part of an embedded form document
2236 Reference< XConnection > xConn;
2237 if ( isEmbeddedInDatabase( m_xComponent, xConn ) )
2238 return true;
2240 break;
2242 case PROPERTY_ID_TEXT:
2243 // don't show the "Text" property of formatted fields
2244 if ( ControlType::FORMATTEDFIELD == m_nClassId )
2245 return true;
2246 break;
2248 case PROPERTY_ID_FORMATKEY:
2249 case PROPERTY_ID_EFFECTIVE_MIN:
2250 case PROPERTY_ID_EFFECTIVE_MAX:
2251 case PROPERTY_ID_EFFECTIVE_DEFAULT:
2252 case PROPERTY_ID_EFFECTIVE_VALUE:
2253 // only if the set has a formats supplier, too
2254 if ( !impl_componentHasProperty_throw( PROPERTY_FORMATSSUPPLIER ) )
2255 return true;
2256 // (form) date and time fields also have a formats supplier, but the format itself
2257 // is reflected in another property
2258 if ( ( FormComponentType::DATEFIELD == m_nClassId )
2259 || ( FormComponentType::TIMEFIELD == m_nClassId )
2261 return true;
2262 break;
2264 case PROPERTY_ID_SCALEIMAGE:
2265 if ( impl_componentHasProperty_throw( PROPERTY_SCALE_MODE ) )
2266 // ScaleImage is superseded by ScaleMode
2267 return true;
2268 break;
2270 case PROPERTY_ID_WRITING_MODE:
2271 if ( !SvtCTLOptions().IsCTLFontEnabled() )
2272 return true;
2273 break;
2276 sal_uInt32 nPropertyUIFlags = m_pInfoService->getPropertyUIFlags( _rProperty.Handle );
2278 // don't show experimental properties unless allowed to do so
2279 if ( ( nPropertyUIFlags & PROP_FLAG_EXPERIMENTAL ) != 0 )
2280 return true;
2282 // no data properties if no Base is installed.
2283 if ( ( nPropertyUIFlags & PROP_FLAG_DATA_PROPERTY ) != 0 )
2284 if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
2285 return true;
2287 if ((nPropertyUIFlags & PROP_FLAG_REPORT_INVISIBLE) != 0 && isReportModel())
2288 return true;
2290 return false;
2293 Reference< XRowSet > FormComponentPropertyHandler::impl_getRowSet_throw( ) const
2295 Reference< XRowSet > xRowSet = m_xRowSet;
2296 if ( !xRowSet.is() )
2298 xRowSet.set( m_xComponent, UNO_QUERY );
2299 if ( !xRowSet.is() )
2301 xRowSet.set( m_xObjectParent, UNO_QUERY );
2302 if ( !xRowSet.is() )
2304 // are we inspecting a grid column?
2305 if (Reference< XGridColumnFactory >( m_xObjectParent, UNO_QUERY) .is())
2306 { // yes
2307 Reference< XChild > xParentAsChild( m_xObjectParent, UNO_QUERY );
2308 if ( xParentAsChild.is() )
2309 xRowSet.set( xParentAsChild->getParent(), UNO_QUERY );
2312 if ( !xRowSet.is() )
2313 xRowSet = m_xRowSet;
2315 DBG_ASSERT( xRowSet.is(), "FormComponentPropertyHandler::impl_getRowSet_throw: could not obtain the rowset for the introspectee!" );
2317 return xRowSet;
2321 Reference< XRowSet > FormComponentPropertyHandler::impl_getRowSet_nothrow( ) const
2323 Reference< XRowSet > xReturn;
2326 xReturn = impl_getRowSet_throw();
2328 catch( const Exception& )
2330 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
2331 OSL_FAIL( "FormComponentPropertyHandler::impl_getRowSet_nothrow: caught an exception!" );
2333 return xReturn;
2337 void FormComponentPropertyHandler::impl_initFieldList_nothrow( std::vector< OUString >& _rFieldNames ) const
2339 clearContainer( _rFieldNames );
2342 weld::WaitObject aWaitCursor(impl_getDefaultDialogFrame_nothrow());
2344 // get the form of the control we're inspecting
2345 Reference< XPropertySet > xFormSet( impl_getRowSet_throw(), UNO_QUERY );
2346 if ( !xFormSet.is() )
2347 return;
2349 OUString sObjectName;
2350 if( ! (xFormSet->getPropertyValue( PROPERTY_COMMAND ) >>= sObjectName) )
2351 SAL_WARN("extensions.propctrlr", "impl_initFieldList_nothrow: unable to get property " PROPERTY_COMMAND);
2352 // when there is no command we don't need to ask for columns
2353 if ( !sObjectName.isEmpty() && impl_ensureRowsetConnection_nothrow() )
2355 OUString aDatabaseName;
2356 if( ! (xFormSet->getPropertyValue( PROPERTY_DATASOURCE ) >>= aDatabaseName) )
2357 SAL_WARN("extensions.propctrlr", "impl_initFieldList_nothrow: unable to get property " PROPERTY_DATASOURCE);
2358 sal_Int32 nObjectType = CommandType::COMMAND;
2359 if( ! (xFormSet->getPropertyValue( PROPERTY_COMMANDTYPE ) >>= nObjectType) )
2360 SAL_WARN("extensions.propctrlr", "impl_initFieldList_nothrow: unable to get property " PROPERTY_COMMANDTYPE);
2362 const Sequence<OUString> aNames = ::dbtools::getFieldNamesByCommandDescriptor( m_xRowSetConnection, nObjectType, sObjectName );
2363 for ( const OUString& rField : aNames )
2364 _rFieldNames.push_back( rField );
2367 catch (const Exception&)
2369 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
2370 OSL_FAIL( "FormComponentPropertyHandler::impl_initFieldList_nothrow: caught an exception!" );
2375 void FormComponentPropertyHandler::impl_displaySQLError_nothrow( const ::dbtools::SQLExceptionInfo& _rErrorDescriptor ) const
2377 ::dbtools::showError( _rErrorDescriptor, VCLUnoHelper::GetInterface( impl_getDefaultDialogParent_nothrow() ), m_xContext );
2381 bool FormComponentPropertyHandler::impl_ensureRowsetConnection_nothrow() const
2383 if ( !m_xRowSetConnection.is() )
2385 uno::Reference<sdbc::XConnection> xConnection;
2386 Any any = m_xContext->getValueByName( "ActiveConnection" );
2387 any >>= xConnection;
2388 m_xRowSetConnection.reset(xConnection,::dbtools::SharedConnection::NoTakeOwnership);
2390 if ( m_xRowSetConnection.is() )
2391 return true;
2393 Reference< XRowSet > xRowSet( impl_getRowSet_throw() );
2394 Reference< XPropertySet > xRowSetProps( xRowSet, UNO_QUERY );
2396 // connect the row set - this is delegated to elsewhere - while observing errors
2397 SQLExceptionInfo aError;
2400 if ( xRowSetProps.is() )
2402 weld::WaitObject aWaitCursor(impl_getDefaultDialogFrame_nothrow());
2403 m_xRowSetConnection = ::dbtools::ensureRowSetConnection( xRowSet, m_xContext, nullptr );
2406 catch ( const SQLException& ) { aError = SQLExceptionInfo( ::cppu::getCaughtException() ); }
2407 catch ( const WrappedTargetException& e ) { aError = SQLExceptionInfo( e.TargetException ); }
2408 catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION("extensions.propctrlr"); }
2410 // report errors, if necessary
2411 if ( aError.isValid() )
2413 OUString sDataSourceName;
2416 xRowSetProps->getPropertyValue( PROPERTY_DATASOURCE ) >>= sDataSourceName;
2418 catch( const Exception& )
2420 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
2421 OSL_FAIL( "FormComponentPropertyHandler::impl_ensureRowsetConnection_nothrow: caught an exception during error handling!" );
2423 // additional info about what happened
2424 INetURLObject aParser( sDataSourceName );
2425 if ( aParser.GetProtocol() != INetProtocol::NotValid )
2426 sDataSourceName = aParser.getBase( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
2427 OUString sInfo(PcrRes(RID_STR_UNABLETOCONNECT).replaceAll("$name$", sDataSourceName));
2428 SQLContext aContext;
2429 aContext.Message = sInfo;
2430 aContext.NextException = aError.get();
2431 impl_displaySQLError_nothrow( aContext );
2434 return m_xRowSetConnection.is();
2438 void FormComponentPropertyHandler::impl_describeCursorSource_nothrow( LineDescriptor& _out_rProperty, const Reference< XPropertyControlFactory >& _rxControlFactory ) const
2442 weld::WaitObject aWaitCursor(impl_getDefaultDialogFrame_nothrow());
2445 // Set the UI data
2446 _out_rProperty.DisplayName = m_pInfoService->getPropertyTranslation( PROPERTY_ID_COMMAND );
2448 _out_rProperty.HelpURL = HelpIdUrl::getHelpURL( m_pInfoService->getPropertyHelpId( PROPERTY_ID_COMMAND ) );
2449 _out_rProperty.PrimaryButtonId = UID_PROP_DLG_SQLCOMMAND;
2452 sal_Int32 nCommandType = CommandType::COMMAND;
2453 impl_getPropertyValue_throw( PROPERTY_COMMANDTYPE ) >>= nCommandType;
2455 switch ( nCommandType )
2457 case CommandType::TABLE:
2458 case CommandType::QUERY:
2460 std::vector< OUString > aNames;
2461 if ( impl_ensureRowsetConnection_nothrow() )
2463 if ( nCommandType == CommandType::TABLE )
2464 impl_fillTableNames_throw( aNames );
2465 else
2466 impl_fillQueryNames_throw( aNames );
2468 _out_rProperty.Control = PropertyHandlerHelper::createComboBoxControl( _rxControlFactory, aNames, true );
2470 break;
2472 default:
2473 _out_rProperty.Control = _rxControlFactory->createPropertyControl( PropertyControlType::MultiLineTextField, false );
2474 break;
2477 catch (const Exception&)
2479 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
2480 OSL_FAIL("FormComponentPropertyHandler::impl_describeCursorSource_nothrow: caught an exception !");
2485 void FormComponentPropertyHandler::impl_fillTableNames_throw( std::vector< OUString >& _out_rNames ) const
2487 OSL_PRECOND( m_xRowSetConnection.is(), "FormComponentPropertyHandler::impl_fillTableNames_throw: need a connection!" );
2488 _out_rNames.resize( 0 );
2490 Reference< XTablesSupplier > xSupplyTables( m_xRowSetConnection, UNO_QUERY );
2491 Reference< XNameAccess > xTableNames;
2492 if ( xSupplyTables.is() )
2493 xTableNames = xSupplyTables->getTables();
2494 DBG_ASSERT( xTableNames.is(), "FormComponentPropertyHandler::impl_fillTableNames_throw: no way to obtain the tables of the connection!" );
2495 if ( !xTableNames.is() )
2496 return;
2498 const Sequence<OUString> aNames = xTableNames->getElementNames();
2499 for ( const OUString& rTableName : aNames )
2500 _out_rNames.push_back( rTableName );
2504 void FormComponentPropertyHandler::impl_fillQueryNames_throw( std::vector< OUString >& _out_rNames ) const
2506 OSL_PRECOND( m_xRowSetConnection.is(), "FormComponentPropertyHandler::impl_fillQueryNames_throw: need a connection!" );
2507 _out_rNames.resize( 0 );
2509 Reference< XQueriesSupplier > xSupplyQueries( m_xRowSetConnection, UNO_QUERY );
2510 Reference< XNameAccess > xQueryNames;
2511 if ( xSupplyQueries.is() )
2513 xQueryNames = xSupplyQueries->getQueries();
2514 impl_fillQueryNames_throw(xQueryNames,_out_rNames);
2518 void FormComponentPropertyHandler::impl_fillQueryNames_throw( const Reference< XNameAccess >& _xQueryNames,std::vector< OUString >& _out_rNames,const OUString& _sName ) const
2520 DBG_ASSERT( _xQueryNames.is(), "FormComponentPropertyHandler::impl_fillQueryNames_throw: no way to obtain the queries of the connection!" );
2521 if ( !_xQueryNames.is() )
2522 return;
2524 bool bAdd = !_sName.isEmpty();
2526 const Sequence<OUString> aQueryNames =_xQueryNames->getElementNames();
2527 for ( const OUString& rQueryName : aQueryNames )
2529 OUStringBuffer sTemp;
2530 if ( bAdd )
2532 sTemp.append(_sName);
2533 sTemp.append("/");
2535 sTemp.append(rQueryName);
2536 Reference< XNameAccess > xSubQueries(_xQueryNames->getByName(rQueryName),UNO_QUERY);
2537 if ( xSubQueries.is() )
2538 impl_fillQueryNames_throw(xSubQueries,_out_rNames,sTemp.makeStringAndClear());
2539 else
2540 _out_rNames.push_back( sTemp.makeStringAndClear() );
2545 void FormComponentPropertyHandler::impl_describeListSourceUI_throw( LineDescriptor& _out_rDescriptor, const Reference< XPropertyControlFactory >& _rxControlFactory ) const
2547 OSL_PRECOND( m_xComponent.is(), "FormComponentPropertyHandler::impl_describeListSourceUI_throw: no component!" );
2550 // read out ListSourceTypes
2551 Any aListSourceType( m_xComponent->getPropertyValue( PROPERTY_LISTSOURCETYPE ) );
2553 sal_Int32 nListSourceType = sal_Int32(ListSourceType_VALUELIST);
2554 ::cppu::enum2int( nListSourceType, aListSourceType );
2555 ListSourceType eListSourceType = static_cast<ListSourceType>(nListSourceType);
2557 _out_rDescriptor.DisplayName = m_pInfoService->getPropertyTranslation( PROPERTY_ID_LISTSOURCE );
2558 _out_rDescriptor.HelpURL = HelpIdUrl::getHelpURL( m_pInfoService->getPropertyHelpId( PROPERTY_ID_LISTSOURCE ) );
2561 // set enums
2562 switch( eListSourceType )
2564 case ListSourceType_VALUELIST:
2565 _out_rDescriptor.Control = _rxControlFactory->createPropertyControl( PropertyControlType::StringListField, false );
2566 break;
2568 case ListSourceType_TABLEFIELDS:
2569 case ListSourceType_TABLE:
2570 case ListSourceType_QUERY:
2572 std::vector< OUString > aListEntries;
2573 if ( impl_ensureRowsetConnection_nothrow() )
2575 if ( eListSourceType == ListSourceType_QUERY )
2576 impl_fillQueryNames_throw( aListEntries );
2577 else
2578 impl_fillTableNames_throw( aListEntries );
2580 _out_rDescriptor.Control = PropertyHandlerHelper::createComboBoxControl( _rxControlFactory, aListEntries, false );
2582 break;
2583 case ListSourceType_SQL:
2584 case ListSourceType_SQLPASSTHROUGH:
2585 impl_ensureRowsetConnection_nothrow();
2586 _out_rDescriptor.HasPrimaryButton = m_xRowSetConnection.is();
2587 break;
2588 default: break;
2592 bool FormComponentPropertyHandler::impl_dialogListSelection_nothrow( const OUString& _rProperty, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2594 OSL_PRECOND(m_pInfoService, "FormComponentPropertyHandler::impl_dialogListSelection_"
2595 "nothrow: no property meta data!");
2597 OUString sPropertyUIName( m_pInfoService->getPropertyTranslation( m_pInfoService->getPropertyId( _rProperty ) ) );
2598 ListSelectionDialog aDialog(impl_getDefaultDialogFrame_nothrow(), m_xComponent, _rProperty, sPropertyUIName);
2599 _rClearBeforeDialog.clear();
2600 return ( RET_OK == aDialog.run() );
2603 bool FormComponentPropertyHandler::impl_dialogFilterOrSort_nothrow( bool _bFilter, OUString& _out_rSelectedClause, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2605 OSL_PRECOND( Reference< XRowSet >( m_xComponent, UNO_QUERY ).is(),
2606 "FormComponentPropertyHandler::impl_dialogFilterOrSort_nothrow: to be called for forms only!" );
2608 _out_rSelectedClause.clear();
2609 bool bSuccess = false;
2610 SQLExceptionInfo aErrorInfo;
2613 if ( !impl_ensureRowsetConnection_nothrow() )
2614 return false;
2616 // get a composer for the statement which the form is currently based on
2617 Reference< XSingleSelectQueryComposer > xComposer( ::dbtools::getCurrentSettingsComposer( m_xComponent, m_xContext, nullptr ) );
2618 OSL_ENSURE( xComposer.is(), "FormComponentPropertyHandler::impl_dialogFilterOrSort_nothrow: could not obtain a composer!" );
2619 if ( !xComposer.is() )
2620 return false;
2622 OUString sPropertyUIName( m_pInfoService->getPropertyTranslation( _bFilter ? PROPERTY_ID_FILTER : PROPERTY_ID_SORT ) );
2624 // create the dialog
2625 Reference< XExecutableDialog > xDialog;
2626 if ( _bFilter)
2628 xDialog.set( sdb::FilterDialog::createDefault(m_xContext) );
2630 else
2632 xDialog.set( sdb::OrderDialog::createDefault(m_xContext) );
2636 // initialize the dialog
2637 Reference< XPropertySet > xDialogProps( xDialog, UNO_QUERY_THROW );
2638 xDialogProps->setPropertyValue("QueryComposer", makeAny( xComposer ) );
2639 xDialogProps->setPropertyValue("RowSet", makeAny( m_xComponent ) );
2640 xDialogProps->setPropertyValue("ParentWindow", makeAny( VCLUnoHelper::GetInterface( impl_getDefaultDialogParent_nothrow() ) ) );
2641 xDialogProps->setPropertyValue("Title", makeAny( sPropertyUIName ) );
2643 _rClearBeforeDialog.clear();
2644 bSuccess = ( xDialog->execute() != 0 );
2645 if ( bSuccess )
2646 _out_rSelectedClause = _bFilter ? xComposer->getFilter() : xComposer->getOrder();
2648 catch (const SQLContext& e) { aErrorInfo = e; }
2649 catch (const SQLWarning& e) { aErrorInfo = e; }
2650 catch (const SQLException& e) { aErrorInfo = e; }
2651 catch( const Exception& )
2653 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
2654 OSL_FAIL( "FormComponentPropertyHandler::impl_dialogFilterOrSort_nothrow: caught an exception!" );
2657 if ( aErrorInfo.isValid() )
2658 impl_displaySQLError_nothrow( aErrorInfo );
2660 return bSuccess;
2664 bool FormComponentPropertyHandler::impl_dialogLinkedFormFields_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2666 Reference< XForm > xDetailForm( m_xComponent, UNO_QUERY );
2667 Reference< XForm > xMasterForm( m_xObjectParent, UNO_QUERY );
2668 uno::Reference<beans::XPropertySet> xMasterProp(m_xObjectParent,uno::UNO_QUERY);
2669 OSL_PRECOND( xDetailForm.is() && xMasterForm.is(), "FormComponentPropertyHandler::impl_dialogLinkedFormFields_nothrow: no forms!" );
2670 if ( !xDetailForm.is() || !xMasterForm.is() )
2671 return false;
2673 FormLinkDialog aDialog(impl_getDefaultDialogFrame_nothrow(), m_xComponent, xMasterProp, m_xContext);
2674 _rClearBeforeDialog.clear();
2675 return ( RET_OK == aDialog.run() );
2678 bool FormComponentPropertyHandler::impl_dialogFormatting_nothrow( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2680 bool bChanged = false;
2683 // create the itemset for the dialog
2684 SfxItemSet aCoreSet(
2685 SfxGetpApp()->GetPool(),
2686 svl::Items<
2687 SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO>{});
2688 // ripped this somewhere ... don't understand it :(
2690 // get the number formats supplier
2691 Reference< XNumberFormatsSupplier > xSupplier;
2692 m_xComponent->getPropertyValue( PROPERTY_FORMATSSUPPLIER ) >>= xSupplier;
2694 DBG_ASSERT(xSupplier.is(), "FormComponentPropertyHandler::impl_dialogFormatting_nothrow: invalid call !" );
2695 Reference< XUnoTunnel > xTunnel( xSupplier, UNO_QUERY_THROW );
2696 SvNumberFormatsSupplierObj* pSupplier =
2697 reinterpret_cast< SvNumberFormatsSupplierObj* >( xTunnel->getSomething( SvNumberFormatsSupplierObj::getUnoTunnelId() ) );
2698 DBG_ASSERT( pSupplier != nullptr, "FormComponentPropertyHandler::impl_dialogFormatting_nothrow: invalid call !" );
2700 sal_Int32 nFormatKey = 0;
2701 impl_getPropertyValue_throw( PROPERTY_FORMATKEY ) >>= nFormatKey;
2702 aCoreSet.Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE, nFormatKey ) );
2704 SvNumberFormatter* pFormatter = pSupplier->GetNumberFormatter();
2705 double dPreviewVal = OFormatSampleControl::getPreviewValue(pFormatter,nFormatKey);
2706 SvxNumberInfoItem aFormatter( pFormatter, dPreviewVal, PcrRes(RID_STR_TEXT_FORMAT), SID_ATTR_NUMBERFORMAT_INFO );
2707 aCoreSet.Put( aFormatter );
2709 // a tab dialog with a single page
2710 SfxSingleTabDialogController aDialog(impl_getDefaultDialogFrame_nothrow(), &aCoreSet,
2711 "cui/ui/formatnumberdialog.ui", "FormatNumberDialog");
2712 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
2713 ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SVXPAGE_NUMBERFORMAT );
2714 if ( !fnCreatePage )
2715 throw RuntimeException(); // caught below
2717 aDialog.SetTabPage((*fnCreatePage)(aDialog.get_content_area(), &aDialog, &aCoreSet));
2719 _rClearBeforeDialog.clear();
2720 if ( RET_OK == aDialog.run() )
2722 const SfxItemSet* pResult = aDialog.GetOutputItemSet();
2724 const SfxPoolItem* pItem = pResult->GetItem( SID_ATTR_NUMBERFORMAT_INFO );
2725 const SvxNumberInfoItem* pInfoItem = dynamic_cast< const SvxNumberInfoItem* >( pItem );
2726 if (pInfoItem)
2728 for (sal_uInt32 key : pInfoItem->GetDelFormats())
2729 pFormatter->DeleteEntry(key);
2732 pItem = nullptr;
2733 if ( SfxItemState::SET == pResult->GetItemState( SID_ATTR_NUMBERFORMAT_VALUE, false, &pItem ) )
2735 _out_rNewValue <<= static_cast<sal_Int32>( static_cast< const SfxUInt32Item* >( pItem )->GetValue() );
2736 bChanged = true;
2740 catch( const Exception& )
2742 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
2743 OSL_FAIL( "FormComponentPropertyHandler::impl_dialogFormatting_nothrow: : caught an exception!" );
2745 return bChanged;
2748 bool FormComponentPropertyHandler::impl_browseForImage_nothrow( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2750 bool bIsLink = true;// reflect the legacy behavior
2751 OUString aStrTrans = m_pInfoService->getPropertyTranslation( PROPERTY_ID_IMAGE_URL );
2753 weld::Window* pWin = impl_getDefaultDialogFrame_nothrow();
2754 ::sfx2::FileDialogHelper aFileDlg(
2755 ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW,
2756 FileDialogFlags::Graphic, pWin);
2758 aFileDlg.SetTitle(aStrTrans);
2759 // non-linked images ( e.g. those located in the document
2760 // stream ) only if document is available
2761 bool bHandleNonLink;
2763 Reference< XModel > xModel( impl_getContextDocument_nothrow() );
2764 bHandleNonLink = xModel.is();
2765 // Not implemented in reports
2766 if (bHandleNonLink)
2768 Reference< XReportDefinition > xReportDef( xModel, css::uno::UNO_QUERY );
2769 bHandleNonLink = !xReportDef.is();
2773 Reference< XFilePickerControlAccess > xController(aFileDlg.GetFilePicker(), UNO_QUERY);
2774 DBG_ASSERT(xController.is(), "FormComponentPropertyHandler::impl_browseForImage_nothrow: missing the controller interface on the file picker!");
2775 if (xController.is())
2777 // do a preview by default
2778 xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_PREVIEW, 0, css::uno::Any(true));
2780 xController->setValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0, css::uno::Any(bIsLink));
2781 xController->enableControl(ExtendedFilePickerElementIds::CHECKBOX_LINK, bHandleNonLink );
2785 OUString sCurValue;
2786 if( ! (impl_getPropertyValue_throw( PROPERTY_IMAGE_URL ) >>= sCurValue) )
2787 SAL_WARN("extensions.propctrlr", "impl_browseForImage_nothrow: unable to get property " PROPERTY_IMAGE_URL);
2788 if (!sCurValue.isEmpty())
2790 aFileDlg.SetDisplayDirectory( sCurValue );
2791 // TODO: need to set the display directory _and_ the default name
2794 _rClearBeforeDialog.clear();
2795 bool bSuccess = ( ERRCODE_NONE == aFileDlg.Execute() );
2796 if ( bSuccess )
2798 if ( bHandleNonLink && xController.is() )
2800 xController->getValue(ExtendedFilePickerElementIds::CHECKBOX_LINK, 0) >>= bIsLink;
2802 if ( !bIsLink )
2804 Graphic aGraphic;
2805 aFileDlg.GetGraphic(aGraphic);
2807 Reference< graphic::XGraphicObject > xGrfObj = graphic::GraphicObject::create( m_xContext );
2808 xGrfObj->setGraphic( aGraphic.GetXGraphic() );
2810 _out_rNewValue <<= xGrfObj;
2813 else
2814 _out_rNewValue <<= aFileDlg.GetPath();
2816 return bSuccess;
2819 bool FormComponentPropertyHandler::impl_browseForTargetURL_nothrow( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2821 weld::Window* pWin = impl_getDefaultDialogFrame_nothrow();
2822 ::sfx2::FileDialogHelper aFileDlg(
2823 ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
2824 FileDialogFlags::NONE, pWin);
2826 OUString sURL;
2827 if( ! (impl_getPropertyValue_throw( PROPERTY_TARGET_URL ) >>= sURL) )
2828 SAL_WARN("extensions.propctrlr", "impl_browseForTargetURL_nothrow: unable to get property " PROPERTY_TARGET_URL);
2829 INetURLObject aParser( sURL );
2830 if ( INetProtocol::File == aParser.GetProtocol() )
2831 // set the initial directory only for file-URLs. Everything else
2832 // is considered to be potentially expensive
2833 aFileDlg.SetDisplayDirectory( sURL );
2835 _rClearBeforeDialog.clear();
2836 bool bSuccess = ( ERRCODE_NONE == aFileDlg.Execute() );
2837 if ( bSuccess )
2838 _out_rNewValue <<= aFileDlg.GetPath();
2839 return bSuccess;
2842 bool FormComponentPropertyHandler::impl_executeFontDialog_nothrow( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2844 bool bSuccess = false;
2846 // create an item set for use with the dialog
2847 std::unique_ptr<SfxItemSet> pSet;
2848 SfxItemPool* pPool = nullptr;
2849 std::vector<SfxPoolItem*>* pDefaults = nullptr;
2850 ControlCharacterDialog::createItemSet(pSet, pPool, pDefaults);
2851 ControlCharacterDialog::translatePropertiesToItems(m_xComponent, pSet.get());
2853 { // do this in an own block. The dialog needs to be destroyed before we call
2854 // destroyItemSet
2855 ControlCharacterDialog aDlg(impl_getDefaultDialogFrame_nothrow(), *pSet);
2856 _rClearBeforeDialog.clear();
2857 if (RET_OK == aDlg.run())
2859 const SfxItemSet* pOut = aDlg.GetOutputItemSet();
2860 if ( pOut )
2862 std::vector< NamedValue > aFontPropertyValues;
2863 ControlCharacterDialog::translateItemsToProperties( *pOut, aFontPropertyValues );
2864 _out_rNewValue <<= comphelper::containerToSequence(aFontPropertyValues);
2865 bSuccess = true;
2870 ControlCharacterDialog::destroyItemSet(pSet, pPool, pDefaults);
2871 return bSuccess;
2875 bool FormComponentPropertyHandler::impl_browseForDatabaseDocument_throw( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2877 weld::Window* pWin = impl_getDefaultDialogFrame_nothrow();
2878 ::sfx2::FileDialogHelper aFileDlg(
2879 ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION, FileDialogFlags::NONE,
2880 "sdatabase", SfxFilterFlags::NONE, SfxFilterFlags::NONE, pWin);
2882 OUString sDataSource;
2883 if( ! (impl_getPropertyValue_throw( PROPERTY_DATASOURCE ) >>= sDataSource) )
2884 SAL_WARN("extensions.propctrlr", "impl_browseForDatabaseDocument_throw: unable to get property " PROPERTY_DATASOURCE);
2885 INetURLObject aParser( sDataSource );
2886 if ( INetProtocol::File == aParser.GetProtocol() )
2887 // set the initial directory only for file-URLs. Everything else
2888 // is considered to be potentially expensive
2889 aFileDlg.SetDisplayDirectory( sDataSource );
2891 std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetFilterByName("StarOffice XML (Base)");
2892 OSL_ENSURE(pFilter,"Filter: StarOffice XML (Base) could not be found!");
2893 if ( pFilter )
2895 aFileDlg.SetCurrentFilter(pFilter->GetUIName());
2896 //aFileDlg.AddFilter(pFilter->GetFilterName(),pFilter->GetDefaultExtension());
2899 _rClearBeforeDialog.clear();
2900 bool bSuccess = ( ERRCODE_NONE == aFileDlg.Execute() );
2901 if ( bSuccess )
2902 _out_rNewValue <<= aFileDlg.GetPath();
2903 return bSuccess;
2906 bool FormComponentPropertyHandler::impl_dialogColorChooser_throw( sal_Int32 _nColorPropertyId, Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2908 ::Color aColor;
2909 if( ! (impl_getPropertyValue_throw( impl_getPropertyNameFromId_nothrow( _nColorPropertyId )) >>= aColor) )
2910 SAL_WARN("extensions.propctrlr", "impl_dialogColorChooser_throw: unable to get property " << _nColorPropertyId);
2911 SvColorDialog aColorDlg;
2912 aColorDlg.SetColor( aColor );
2914 _rClearBeforeDialog.clear();
2915 weld::Window* pParent = impl_getDefaultDialogFrame_nothrow();
2916 if (!aColorDlg.Execute(pParent))
2917 return false;
2919 _out_rNewValue <<= aColorDlg.GetColor();
2920 return true;
2923 bool FormComponentPropertyHandler::impl_dialogChooseLabelControl_nothrow( Any& _out_rNewValue, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2925 weld::Window* pParent = impl_getDefaultDialogFrame_nothrow();
2926 OSelectLabelDialog dlgSelectLabel(pParent, m_xComponent);
2927 _rClearBeforeDialog.clear();
2928 bool bSuccess = (RET_OK == dlgSelectLabel.run());
2929 if ( bSuccess )
2930 _out_rNewValue <<= dlgSelectLabel.GetSelected();
2931 return bSuccess;
2935 Reference< XControlContainer > FormComponentPropertyHandler::impl_getContextControlContainer_nothrow() const
2937 Reference< XControlContainer > xControlContext;
2938 Any any = m_xContext->getValueByName( "ControlContext" );
2939 any >>= xControlContext;
2940 return xControlContext;
2944 bool FormComponentPropertyHandler::impl_dialogChangeTabOrder_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const
2946 OSL_PRECOND( impl_getContextControlContainer_nothrow().is(), "FormComponentPropertyHandler::impl_dialogChangeTabOrder_nothrow: invalid control context!" );
2948 Reference< XTabControllerModel > xTabControllerModel( impl_getRowSet_nothrow(), UNO_QUERY );
2949 TabOrderDialog aDialog(impl_getDefaultDialogFrame_nothrow(), xTabControllerModel,
2950 impl_getContextControlContainer_nothrow(), m_xContext);
2951 _rClearBeforeDialog.clear();
2952 return RET_OK == aDialog.run();
2955 namespace
2958 //- ISQLCommandPropertyUI
2960 class ISQLCommandPropertyUI : public ISQLCommandAdapter
2962 public:
2963 /** returns the empty-string-terminated list of names of properties
2964 whose UI is to be disabled while the SQL command property is
2965 being edited.
2967 virtual OUString* getPropertiesToDisable() = 0;
2971 //- SQLCommandPropertyUI
2973 class SQLCommandPropertyUI : public ISQLCommandPropertyUI
2975 protected:
2976 explicit SQLCommandPropertyUI( const Reference< XPropertySet >& _rxObject )
2977 : m_xObject(_rxObject)
2979 if ( !m_xObject.is() )
2980 throw NullPointerException();
2983 protected:
2984 Reference< XPropertySet > m_xObject;
2988 //- FormSQLCommandUI - declaration
2990 class FormSQLCommandUI : public SQLCommandPropertyUI
2992 public:
2993 explicit FormSQLCommandUI( const Reference< XPropertySet >& _rxForm );
2995 // ISQLCommandAdapter
2996 virtual OUString getSQLCommand() const override;
2997 virtual bool getEscapeProcessing() const override;
2998 virtual void setSQLCommand( const OUString& _rCommand ) const override;
2999 virtual void setEscapeProcessing( const bool _bEscapeProcessing ) const override;
3001 // ISQLCommandPropertyUI
3002 virtual OUString* getPropertiesToDisable() override;
3006 //- FormSQLCommandUI - implementation
3009 FormSQLCommandUI::FormSQLCommandUI( const Reference< XPropertySet >& _rxForm )
3010 :SQLCommandPropertyUI( _rxForm )
3015 OUString FormSQLCommandUI::getSQLCommand() const
3017 OUString sCommand;
3018 if( ! (m_xObject->getPropertyValue( PROPERTY_COMMAND ) >>= sCommand) )
3019 SAL_WARN("extensions.propctrlr", "getSQLCommand: unable to get property " PROPERTY_COMMAND);
3020 return sCommand;
3024 bool FormSQLCommandUI::getEscapeProcessing() const
3026 bool bEscapeProcessing( false );
3027 if( ! (m_xObject->getPropertyValue( PROPERTY_ESCAPE_PROCESSING ) >>= bEscapeProcessing) )
3028 SAL_WARN("extensions.propctrlr", "getSQLCommand: unable to get property " PROPERTY_ESCAPE_PROCESSING);
3029 return bEscapeProcessing;
3033 void FormSQLCommandUI::setSQLCommand( const OUString& _rCommand ) const
3035 m_xObject->setPropertyValue( PROPERTY_COMMAND, makeAny( _rCommand ) );
3039 void FormSQLCommandUI::setEscapeProcessing( const bool _bEscapeProcessing ) const
3041 m_xObject->setPropertyValue( PROPERTY_ESCAPE_PROCESSING, makeAny( _bEscapeProcessing ) );
3045 OUString* FormSQLCommandUI::getPropertiesToDisable()
3047 static OUString s_aCommandProps[] = {
3048 OUString(PROPERTY_DATASOURCE),
3049 OUString(PROPERTY_COMMAND),
3050 OUString(PROPERTY_COMMANDTYPE),
3051 OUString(PROPERTY_ESCAPE_PROCESSING),
3052 OUString()
3054 return s_aCommandProps;
3057 //- ValueListCommandUI - declaration
3059 class ValueListCommandUI : public SQLCommandPropertyUI
3061 public:
3062 explicit ValueListCommandUI( const Reference< XPropertySet >& _rxListOrCombo );
3064 // ISQLCommandAdapter
3065 virtual OUString getSQLCommand() const override;
3066 virtual bool getEscapeProcessing() const override;
3067 virtual void setSQLCommand( const OUString& _rCommand ) const override;
3068 virtual void setEscapeProcessing( const bool _bEscapeProcessing ) const override;
3070 // ISQLCommandPropertyUI
3071 virtual OUString* getPropertiesToDisable() override;
3072 private:
3073 mutable bool m_bPropertyValueIsList;
3077 //- ValueListCommandUI - implementation
3080 ValueListCommandUI::ValueListCommandUI( const Reference< XPropertySet >& _rxListOrCombo )
3081 :SQLCommandPropertyUI( _rxListOrCombo )
3082 ,m_bPropertyValueIsList( false )
3087 OUString ValueListCommandUI::getSQLCommand() const
3089 OUString sValue;
3090 m_bPropertyValueIsList = false;
3092 // for combo boxes, the property is a mere string
3093 Any aValue( m_xObject->getPropertyValue( PROPERTY_LISTSOURCE ) );
3094 if ( aValue >>= sValue )
3095 return sValue;
3097 Sequence< OUString > aValueList;
3098 if ( aValue >>= aValueList )
3100 m_bPropertyValueIsList = true;
3101 if ( aValueList.hasElements() )
3102 sValue = aValueList[0];
3103 return sValue;
3106 OSL_FAIL( "ValueListCommandUI::getSQLCommand: unexpected property type!" );
3107 return sValue;
3111 bool ValueListCommandUI::getEscapeProcessing() const
3113 ListSourceType eType = ListSourceType_SQL;
3114 if( ! (m_xObject->getPropertyValue( PROPERTY_LISTSOURCETYPE ) >>= eType) )
3115 SAL_WARN("extensions.propctrlr", "getEscapeProcessing: unable to get property " PROPERTY_LISTSOURCETYPE);
3116 OSL_ENSURE( ( eType == ListSourceType_SQL ) || ( eType == ListSourceType_SQLPASSTHROUGH ),
3117 "ValueListCommandUI::getEscapeProcessing: unexpected list source type!" );
3118 return ( eType == ListSourceType_SQL );
3122 void ValueListCommandUI::setSQLCommand( const OUString& _rCommand ) const
3124 Any aValue;
3125 if ( m_bPropertyValueIsList )
3126 aValue <<= Sequence< OUString >( &_rCommand, 1 );
3127 else
3128 aValue <<= _rCommand;
3129 m_xObject->setPropertyValue( PROPERTY_LISTSOURCE, aValue );
3133 void ValueListCommandUI::setEscapeProcessing( const bool _bEscapeProcessing ) const
3135 m_xObject->setPropertyValue( PROPERTY_LISTSOURCETYPE, makeAny(
3136 _bEscapeProcessing ? ListSourceType_SQL : ListSourceType_SQLPASSTHROUGH ) );
3140 OUString* ValueListCommandUI::getPropertiesToDisable()
3142 static OUString s_aListSourceProps[] = {
3143 OUString(PROPERTY_LISTSOURCETYPE),
3144 OUString(PROPERTY_LISTSOURCE),
3145 OUString()
3147 return s_aListSourceProps;
3152 bool FormComponentPropertyHandler::impl_doDesignSQLCommand_nothrow( const Reference< XObjectInspectorUI >& _rxInspectorUI, PropertyId _nDesignForProperty )
3156 if ( m_xCommandDesigner.is() )
3158 if ( m_xCommandDesigner->isActive() )
3160 m_xCommandDesigner->raise();
3161 return true;
3163 m_xCommandDesigner->dispose();
3164 m_xCommandDesigner.set( nullptr );
3167 if ( !impl_ensureRowsetConnection_nothrow() )
3168 return false;
3170 Reference< XPropertySet > xComponentProperties( m_xComponent, UNO_SET_THROW );
3172 ::rtl::Reference< ISQLCommandPropertyUI > xCommandUI;
3173 switch ( _nDesignForProperty )
3175 case PROPERTY_ID_COMMAND:
3176 xCommandUI = new FormSQLCommandUI( xComponentProperties );
3177 break;
3178 case PROPERTY_ID_LISTSOURCE:
3179 xCommandUI = new ValueListCommandUI( xComponentProperties );
3180 break;
3181 default:
3182 OSL_FAIL( "FormComponentPropertyHandler::OnDesignerClosed: invalid property id!" );
3183 return false;
3186 m_xCommandDesigner.set( new SQLCommandDesigner( m_xContext, xCommandUI.get(), m_xRowSetConnection, LINK( this, FormComponentPropertyHandler, OnDesignerClosed ) ) );
3188 DBG_ASSERT( _rxInspectorUI.is(), "FormComponentPropertyHandler::OnDesignerClosed: no access to the property browser ui!" );
3189 if ( m_xCommandDesigner->isActive() && _rxInspectorUI.is() )
3191 m_xBrowserUI = _rxInspectorUI;
3192 // disable everything which would affect this property
3193 const OUString* pToDisable = xCommandUI->getPropertiesToDisable();
3194 while ( !pToDisable->isEmpty() )
3196 m_xBrowserUI->enablePropertyUIElements( *pToDisable++, PropertyLineElement::All, false );
3199 // but enable the browse button for the property itself - so it can be used to raise the query designer
3200 OUString sPropertyName( impl_getPropertyNameFromId_nothrow( _nDesignForProperty ) );
3201 m_xBrowserUI->enablePropertyUIElements( sPropertyName, PropertyLineElement::PrimaryButton, true );
3204 catch( const Exception& )
3206 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
3208 return m_xCommandDesigner.is();
3212 IMPL_LINK_NOARG( FormComponentPropertyHandler, OnDesignerClosed, SQLCommandDesigner&, void )
3214 OSL_ENSURE( m_xBrowserUI.is() && m_xCommandDesigner.is(), "FormComponentPropertyHandler::OnDesignerClosed: too many NULLs!" );
3215 if ( m_xBrowserUI.is() && m_xCommandDesigner.is() )
3219 ::rtl::Reference< ISQLCommandPropertyUI > xCommandUI(
3220 dynamic_cast< ISQLCommandPropertyUI* >( m_xCommandDesigner->getPropertyAdapter().get() ) );
3221 if ( !xCommandUI.is() )
3222 throw NullPointerException();
3224 const OUString* pToEnable = xCommandUI->getPropertiesToDisable();
3225 while ( !pToEnable->isEmpty() )
3227 m_xBrowserUI->enablePropertyUIElements( *pToEnable++, PropertyLineElement::All, true );
3230 catch( const Exception& )
3232 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
3238 bool FormComponentPropertyHandler::impl_hasValidDataSourceSignature_nothrow( const Reference< XPropertySet >& _xFormProperties, bool _bAllowEmptyDataSourceName )
3240 bool bHas = false;
3241 if ( _xFormProperties.is() )
3245 OUString sPropertyValue;
3246 // first, we need the name of an existent data source
3247 if ( _xFormProperties->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATASOURCE) )
3248 _xFormProperties->getPropertyValue( PROPERTY_DATASOURCE ) >>= sPropertyValue;
3249 bHas = ( !sPropertyValue.isEmpty() ) || _bAllowEmptyDataSourceName;
3251 // then, the command should not be empty
3252 if ( bHas )
3254 if ( _xFormProperties->getPropertySetInfo()->hasPropertyByName(PROPERTY_COMMAND) )
3255 _xFormProperties->getPropertyValue( PROPERTY_COMMAND ) >>= sPropertyValue;
3256 bHas = !sPropertyValue.isEmpty();
3259 catch( const Exception& )
3261 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
3262 OSL_FAIL( "FormComponentPropertyHandler::impl_hasValidDataSourceSignature_nothrow: caught an exception!" );
3265 return bHas;
3268 OUString FormComponentPropertyHandler::impl_getDocumentURL_nothrow() const
3270 OUString sURL;
3273 Reference< XModel > xDocument( impl_getContextDocument_nothrow() );
3274 if ( xDocument.is() )
3275 sURL = xDocument->getURL();
3277 catch( const Exception& )
3279 DBG_UNHANDLED_EXCEPTION("extensions.propctrlr");
3281 return sURL;
3284 ::cppu::IPropertyArrayHelper* FormComponentPropertyHandler::createArrayHelper( ) const
3286 uno::Sequence< beans::Property > aProps;
3287 describeProperties(aProps);
3288 return new ::cppu::OPropertyArrayHelper(aProps);
3292 ::cppu::IPropertyArrayHelper & FormComponentPropertyHandler::getInfoHelper()
3294 return *getArrayHelper();
3297 uno::Reference< beans::XPropertySetInfo > SAL_CALL FormComponentPropertyHandler::getPropertySetInfo( )
3299 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
3303 } // namespace pcr
3306 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */