29 #include <svx/strings.hrc>
32 #include <com/sun/star/sdb/CommandType.hpp>
33 #include <com/sun/star/sdbc/XRowSet.hpp>
34 #include <com/sun/star/container/EnumerableMap.hpp>
35 #include <com/sun/star/drawing/XControlShape.hpp>
36 #include <com/sun/star/form/Forms.hpp>
37 #include <com/sun/star/form/FormComponentType.hpp>
57 using ::com::sun::star::awt::XControlModel;
58 using ::com::sun::star::container::XMap;
59 using ::com::sun::star::container::EnumerableMap;
60 using ::com::sun::star::drawing::XControlShape;
67 ,m_bFirstActivation( true )
68 ,m_bAttemptedFormCreation(
false )
75 class FormComponentInfo
78 static size_t childCount(
const Reference< XInterface >& _component )
80 Reference< XIndexAccess > xContainer( _component, UNO_QUERY );
81 if ( xContainer.is() )
82 return xContainer->getCount();
86 static Reference< XInterface > getChild(
const Reference< XInterface >& _component,
size_t _index )
88 Reference< XIndexAccess > xContainer( _component, UNO_QUERY_THROW );
89 return Reference< XInterface >( xContainer->getByIndex( _index ), UNO_QUERY );
93 typedef ::std::pair< Reference< XInterface >, Reference< XInterface > > FormComponentPair;
95 class FormHierarchyComparator
98 FormHierarchyComparator()
102 static size_t childCount(
const FormComponentPair& _components )
104 size_t lhsCount = FormComponentInfo::childCount( _components.first );
105 size_t rhsCount = FormComponentInfo::childCount( _components.second );
106 if ( lhsCount != rhsCount )
107 throw RuntimeException(
"Found inconsistent form component hierarchies (1)!" );
111 static FormComponentPair getChild(
const FormComponentPair& _components,
size_t _index )
113 return FormComponentPair(
114 FormComponentInfo::getChild( _components.first, _index ),
115 FormComponentInfo::getChild( _components.second, _index )
120 typedef ::std::map< Reference< XControlModel >, Reference< XControlModel > > MapControlModels;
122 class FormComponentAssignment
125 explicit FormComponentAssignment( MapControlModels& _out_controlModelMap )
126 :m_rControlModelMap( _out_controlModelMap )
130 void process(
const FormComponentPair& _component )
132 Reference< XControlModel > lhsControlModel( _component.first, UNO_QUERY );
133 Reference< XControlModel > rhsControlModel( _component.second, UNO_QUERY );
134 if ( lhsControlModel.is() != rhsControlModel.is() )
135 throw RuntimeException(
"Found inconsistent form component hierarchies (2)!" );
137 if ( lhsControlModel.is() )
138 m_rControlModelMap[ lhsControlModel ] = rhsControlModel;
142 MapControlModels& m_rControlModelMap;
150 const Reference< css::form::XForms > xForeignForms( i_foreignImpl.
getForms(
false ) );
152 if ( !xForeignForms.is() )
157 m_xForms.set( xForeignForms->createClone(), UNO_QUERY_THROW );
160 MapControlModels aModelAssignment;
163 FormComponentVisitor aVisitor{ FormHierarchyComparator() };
165 FormComponentAssignment aAssignmentProcessor( aModelAssignment );
166 aVisitor.process( FormComponentPair( xForeignForms,
m_xForms ), aAssignmentProcessor );
172 OSL_ENSURE( aForeignIter.
IsMore() == aOwnIter.
IsMore(),
"FmFormPageImpl::FmFormPageImpl: inconsistent number of objects (1)!" );
175 FmFormObj* pForeignObj =
dynamic_cast< FmFormObj*
>( aForeignIter.
Next() );
176 FmFormObj* pOwnObj =
dynamic_cast< FmFormObj*
>( aOwnIter.
Next() );
178 bool bForeignIsForm = pForeignObj && ( pForeignObj->GetObjInventor() ==
SdrInventor::FmForm );
181 if ( bForeignIsForm != bOwnIsForm )
184 SAL_WARN(
"svx.form",
"FmFormPageImpl::FmFormPageImpl: inconsistent ordering of objects!" );
188 if ( !bForeignIsForm )
192 Reference< XControlModel > xForeignModel( pForeignObj->GetUnoControlModel() );
193 if ( !xForeignModel.is() )
197 SAL_WARN(
"svx.form",
"FmFormPageImpl::FmFormPageImpl: control shape without control!" );
201 MapControlModels::const_iterator
assignment = aModelAssignment.find( xForeignModel );
202 if ( assignment == aModelAssignment.end() )
207 SAL_WARN(
"svx.form",
"FmFormPageImpl::FmFormPageImpl: no clone found for this model!" );
211 pOwnObj->SetUnoControlModel( assignment->second );
213 OSL_ENSURE( aForeignIter.
IsMore() == aOwnIter.
IsMore(),
"FmFormPageImpl::FmFormPageImpl: inconsistent number of objects (2)!" );
222 Reference< XMap > FmFormPageImpl::getControlToShapeMap()
225 if ( xControlShapeMap.is() )
226 return xControlShapeMap;
230 return xControlShapeMap;
236 void lcl_insertFormObject_throw(
const FmFormObj& _object,
const Reference< XMap >& _map )
239 Reference< XControlModel > xControlModel = _object.GetUnoControlModel();
240 OSL_ENSURE( xControlModel.is(),
"lcl_insertFormObject_throw: suspicious: no control model!" );
241 if ( !xControlModel.is() )
244 Reference< XControlShape > xControlShape( const_cast< FmFormObj& >( _object ).getUnoShape(), UNO_QUERY );
245 OSL_ENSURE( xControlShape.is(),
"lcl_insertFormObject_throw: suspicious: no control shape!" );
246 if ( !xControlShape.is() )
249 _map->put(
Any( xControlModel ),
Any( xControlShape ) );
252 void lcl_removeFormObject_throw(
const FmFormObj& _object,
const Reference< XMap >& _map )
255 Reference< XControlModel > xControlModel = _object.GetUnoControlModel();
256 OSL_ENSURE( xControlModel.is(),
"lcl_removeFormObject: suspicious: no control model!" );
257 if ( !xControlModel.is() )
262 Any aOldAssignment = _map->remove(
Any( xControlModel ) );
264 aOldAssignment ==
Any( Reference< XControlShape >( const_cast< FmFormObj& >( _object ).getUnoShape(), UNO_QUERY ) ),
265 "lcl_removeFormObject: map was inconsistent!" );
272 Reference< XMap > xMap;
282 while ( aPageIter.
IsMore() )
285 FmFormObj* pCurrent = FmFormObj::GetFormObject( aPageIter.
Next() );
289 lcl_insertFormObject_throw( *pCurrent, xMap );
302 if (
m_xForms.is() || !_bForceCreate )
310 m_xForms = css::form::Forms::create( xContext );
322 m_xForms->setParent( pObjShell->GetModel() );
335 ::comphelper::disposeComponent(
m_xForms );
359 Reference< XForm > xForm;
361 Reference< XForms > xForms(
getForms() );
370 OUString sStandardFormname =
SvxResId(RID_STR_STDFORMNAME);
374 if ( xForms->hasByName( sStandardFormname ) )
375 xForm.set( xForms->getByName( sStandardFormname ), UNO_QUERY_THROW );
378 xForm.set( xForms->getByIndex(0), UNO_QUERY_THROW );
397 if( rModel.IsUndoEnabled() )
400 OUString aUndoStr(
SvxResId(RID_STR_UNDO_CONTAINER_INSERT));
401 rModel.BegUndo(aUndoStr.replaceFirst(
"'#'", aStr));
416 if( rModel.IsUndoEnabled() )
419 std::make_unique<FmUndoContainerAction>(
420 static_cast< FmFormModel& >(rModel),
424 xForms->getCount()));
426 xForms->insertByName( sName,
Any( xForm ) );
435 if( rModel.IsUndoEnabled() )
445 const OUString& rDBTitle,
const OUString& rCursorSource, sal_Int32 nCommandType )
448 if (!rContent.is() || rContent->getParent().is())
451 Reference< XForm > xForm;
455 if (rDatabase.is() && !rCursorSource.isEmpty())
462 Reference< css::container::XIndexAccess > xFormsByIndex =
getForms();
463 DBG_ASSERT(xFormsByIndex.is(),
"FmFormPageImpl::findPlaceInFormComponentHierarchy : no index access for my forms collection !");
464 sal_Int32
nCount = xFormsByIndex->getCount();
465 for (sal_Int32
i = 0; !xForm.is() &&
i < nCount;
i++)
467 Reference< css::form::XForm > xToSearch;
468 xFormsByIndex->getByIndex(
i) >>= xToSearch;
476 const bool bUndo(rModel.IsUndoEnabled());
481 OUString aUndoStr(
SvxResId(RID_STR_UNDO_CONTAINER_INSERT));
482 aUndoStr = aUndoStr.replaceFirst(
"#", aStr);
483 rModel.BegUndo(aUndoStr);
488 Reference< css::beans::XPropertySet > xFormProps(xForm, UNO_QUERY);
492 if (!rDBTitle.isEmpty())
496 Reference< css::beans::XPropertySet > xDatabaseProps(rDatabase, UNO_QUERY);
498 xFormProps->setPropertyValue(
FM_PROP_URL, aDatabaseUrl);
504 Reference< css::container::XNameAccess > xNamedSet =
getForms();
506 const bool bTableOrQuery = ( CommandType::TABLE == nCommandType ) || ( CommandType::QUERY == nCommandType );
507 OUString
sName = FormControlFactory::getUniqueName( xNamedSet,
508 bTableOrQuery ? rCursorSource :
SvxResId(RID_STR_STDFORMNAME) );
514 Reference< css::container::XIndexContainer > xContainer =
getForms();
516 std::make_unique<FmUndoContainerAction>(
517 static_cast< FmFormModel& >(rModel),
521 xContainer->getCount()));
539 const OUString& _rCursorSource, sal_Int32 nCommandType)
541 Reference< XForm > xResultForm;
542 Reference< XRowSet > xDBForm(rForm, UNO_QUERY);
544 if (!xDBForm.is() || !xFormProps.is())
547 OSL_ENSURE(_rxDatabase.is(),
"FmFormPageImpl::findFormForDataSource: invalid data source!");
548 OUString sLookupName;
549 OUString sFormDataSourceName;
554 xDSProps->getPropertyValue(
FM_PROP_NAME) >>= sLookupName;
559 if (sFormDataSourceName.isEmpty())
563 if ( !xFormConnection.is() )
565 if (xFormConnection.is())
567 Reference< XChild > xConnAsChild(xFormConnection, UNO_QUERY);
568 if (xConnAsChild.is())
573 xDSProps.set(xFormDS, css::uno::UNO_QUERY);
575 xDSProps->getPropertyValue(
FM_PROP_NAME) >>= sFormDataSourceName;
586 if (sLookupName == sFormDataSourceName)
589 OUString aCursorSource = ::comphelper::getString(xFormProps->getPropertyValue(
FM_PROP_COMMAND));
591 if (aCursorSource.isEmpty() || ((nType == nCommandType) && (aCursorSource == _rCursorSource)))
595 if (aCursorSource.isEmpty())
604 Reference< XIndexAccess > xComponents(rForm, UNO_QUERY);
605 sal_Int32
nCount = xComponents->getCount();
606 for (sal_Int32
i = 0; !xResultForm.is() &&
i < nCount; ++
i)
608 Reference< css::form::XForm > xSearchForm;
609 xComponents->getByIndex(
i) >>= xSearchForm;
611 if (xSearchForm.is())
620 #if OSL_DEBUG_LEVEL > 0
623 OSL_ENSURE( !xFormComponent->getParent().is(),
"FmFormPageImpl::setUniqueName: to be called before insertion!" );
631 Reference< css::beans::XPropertySet > xSet(xFormComponent, UNO_QUERY);
634 sName = ::comphelper::getString( xSet->getPropertyValue(
FM_PROP_NAME ) );
635 Reference< css::container::XNameAccess > xNameAcc(xControls, UNO_QUERY);
637 if (sName.isEmpty() || xNameAcc->hasByName(sName))
640 sal_Int16 nClassId( FormComponentType::CONTROL );
643 OUString sDefaultName = FormControlFactory::getDefaultUniqueName_ByComponentType(
647 if (sName.isEmpty() || nClassId != css::form::FormComponentType::RADIOBUTTON)
652 sName = sDefaultName;
662 if ( !xControlShapeMap.is() )
668 lcl_removeFormObject_throw( _object, xControlShapeMap );
669 lcl_insertFormObject_throw( _object, xControlShapeMap );
681 if ( !xControlShapeMap.is() )
687 lcl_insertFormObject_throw( _object, xControlShapeMap );
699 if ( !xControlShapeMap.is() )
705 lcl_removeFormObject_throw( _object, xControlShapeMap );
css::uno::Reference< css::form::XForms > m_xForms
constexpr OUStringLiteral FM_SUN_COMPONENT_FORM
css::uno::Reference< css::form::XForm > getDefaultForm()
css::uno::Reference< css::form::XForm > findPlaceInFormComponentHierarchy(const css::uno::Reference< css::form::XFormComponent > &rContent, const css::uno::Reference< css::sdbc::XDataSource > &rDatabase=css::uno::Reference< css::sdbc::XDataSource >(), const OUString &rDBTitle=OUString(), const OUString &rCursorSource=OUString(), sal_Int32 nCommandType=0)
finds a place in the form component hierarchy where to insert the given component ...
static OUString setUniqueName(const css::uno::Reference< css::form::XFormComponent > &xFormComponent, const css::uno::Reference< css::form::XForm > &xControls)
css::uno::Reference< css::form::XForm > findFormForDataSource(const css::uno::Reference< css::form::XForm > &rForm, const css::uno::Reference< css::sdbc::XDataSource > &rDatabase, const OUString &rCommand, sal_Int32 nCommandType)
finds a form with a given data source signature
Link< FmFormPageImpl &, void > m_aFormsCreationHdl
css::uno::Reference< css::container::XMap > impl_createControlShapeMap_nothrow()
constexpr OUStringLiteral FM_PROP_CLASSID
css::uno::WeakReference< css::container::XMap > m_aControlShapeMap
OUString SvxResId(TranslateId aId)
#define DBG_UNHANDLED_EXCEPTION(...)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_ASSERT(sCon, aError)
constexpr OUStringLiteral FM_PROP_DATASOURCE
constexpr OUStringLiteral FM_PROP_COMMANDTYPE
HRESULT createInstance(REFIID iid, Ifc **ppIfc)
void formModelAssigned(const FmFormObj &_object)
constexpr OUStringLiteral FM_PROP_URL
SdrModel & getSdrModelFromSdrPage() const
void formObjectInserted(const FmFormObj &_object)
Reference< XMultiServiceFactory > getProcessServiceFactory()
void AddForms(const css::uno::Reference< css::container::XNameContainer > &rForms)
css::uno::Reference< css::form::XForm > xCurrentForm
bool m_bAttemptedFormCreation
constexpr OUStringLiteral FM_PROP_NAME
Reference< XComponentContext > getProcessComponentContext()
constexpr OUStringLiteral FM_PROP_COMMAND
void formObjectRemoved(const FmFormObj &_object)
void setCurForm(const css::uno::Reference< css::form::XForm > &xForm)
#define SAL_WARN(area, stream)
::boost::spirit::classic::rule< ScannerT > assignment
const css::uno::Reference< css::form::XForms > & getForms(bool _bForceCreate=true)
void initFrom(FmFormPageImpl &i_foreignImpl)
bool validateCurForm()
returns an object mapping from control models to drawing shapes.
FmFormPageImpl(FmFormPage &_rPage)
bool m_bDetectedRangeSegmentation false
constexpr OUStringLiteral FM_PROP_ACTIVE_CONNECTION