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>
57using ::com::sun::star::awt::XControlModel;
58using ::com::sun::star::container::XMap;
59using ::com::sun::star::container::EnumerableMap;
60using ::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 );
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)!" );
222Reference< 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 );
335 ::comphelper::disposeComponent(
m_xForms );
359 Reference< XForm > xForm;
361 Reference< XForms > xForms(
getForms() );
367 if ( Reference<XNameAccess>(xForms,UNO_QUERY_THROW)->hasElements() )
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 );
400 OUString aUndoStr(
SvxResId(RID_STR_UNDO_CONTAINER_INSERT));
401 rModel.
BegUndo(aUndoStr.replaceFirst(
"'#'",
aStr));
409 Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW );
419 std::make_unique<FmUndoContainerAction>(
424 xForms->getCount()));
426 xForms->insertByName(
sName,
Any( xForm ) );
444 const Reference< XFormComponent > & rContent,
const Reference< XDataSource > & rDatabase,
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;
481 OUString aUndoStr(
SvxResId(RID_STR_UNDO_CONTAINER_INSERT));
482 aUndoStr = aUndoStr.replaceFirst(
"#",
aStr);
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>(
521 xContainer->getCount()));
538 const Reference< XForm > & rForm,
const Reference< XDataSource > & _rxDatabase,
539 const OUString& _rCursorSource, sal_Int32 nCommandType)
541 Reference< XForm > xResultForm;
542 Reference< XRowSet > xDBForm(rForm, UNO_QUERY);
543 Reference< XPropertySet > xFormProps(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;
552 Reference< XPropertySet > xDSProps(_rxDatabase, UNO_QUERY);
554 xDSProps->getPropertyValue(
FM_PROP_NAME) >>= sLookupName;
559 if (sFormDataSourceName.isEmpty())
561 Reference< XConnection > xFormConnection;
563 if ( !xFormConnection.is() )
565 if (xFormConnection.is())
567 Reference< XChild > xConnAsChild(xFormConnection, UNO_QUERY);
568 if (xConnAsChild.is())
570 Reference< XDataSource > xFormDS(xConnAsChild->getParent(), UNO_QUERY);
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);
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(
644 Reference< XNameAccess >( xControls, UNO_QUERY ), xSet );
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 );
::boost::spirit::classic::rule< ScannerT > assignment
HRESULT createInstance(REFIID iid, Ifc **ppIfc)
void initFrom(FmFormPageImpl &i_foreignImpl)
void formModelAssigned(const FmFormObj &_object)
Link< FmFormPageImpl &, void > m_aFormsCreationHdl
void formObjectInserted(const FmFormObj &_object)
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
const css::uno::Reference< css::form::XForms > & getForms(bool _bForceCreate=true)
static OUString setUniqueName(const css::uno::Reference< css::form::XFormComponent > &xFormComponent, const css::uno::Reference< css::form::XForm > &xControls)
css::uno::Reference< css::form::XForms > m_xForms
css::uno::Reference< css::container::XMap > impl_createControlShapeMap_nothrow()
FmFormPageImpl(FmFormPage &_rPage)
void setCurForm(const css::uno::Reference< css::form::XForm > &xForm)
bool m_bAttemptedFormCreation
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
void formObjectRemoved(const FmFormObj &_object)
bool validateCurForm()
returns an object mapping from control models to drawing shapes.
css::uno::WeakReference< css::container::XMap > m_aControlShapeMap
css::uno::Reference< css::form::XForm > xCurrentForm
void AddForms(const css::uno::Reference< css::container::XNameContainer > &rForms)
void AddUndo(std::unique_ptr< SdrUndoAction > pUndo)
bool IsUndoEnabled() const
returns true if undo is currently enabled This returns false if undo was disabled using EnableUndo( f...
SdrModel & getSdrModelFromSdrPage() const
css::uno::Reference< css::frame::XModel3 > GetModel() const
#define DBG_ASSERT(sCon, aError)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
OUString SvxResId(TranslateId aId)
constexpr OUStringLiteral FM_PROP_ACTIVE_CONNECTION
constexpr OUStringLiteral FM_PROP_COMMAND
constexpr OUStringLiteral FM_PROP_CLASSID
constexpr OUStringLiteral FM_PROP_NAME
constexpr OUStringLiteral FM_PROP_URL
constexpr OUStringLiteral FM_PROP_COMMANDTYPE
constexpr OUStringLiteral FM_PROP_DATASOURCE
constexpr OUStringLiteral FM_SUN_COMPONENT_FORM
#define SAL_WARN(area, stream)
Reference< XComponentContext > getProcessComponentContext()
void * _map(void *p, typelib_TypeDescriptionReference *pType, typelib_TypeDescription *pTypeDescr, uno_Mapping *mapping)