/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
FmFormObj::FmFormObj(
SdrModel& rSdrModel, const OUString& rModelName)
: SdrUnoObj(rSdrModel, rModelName)
,m_nPos(-1)
,m_pLastKnownRefDevice(nullptr)
{ // normally, this is done in SetUnoControlModel, but if the call happened in the base class ctor, // then our incarnation of it was not called (since we were not constructed at this time).
impl_checkRefDevice_nothrow( true );
}
FmFormObj::FmFormObj(SdrModel& rSdrModel)
: SdrUnoObj(rSdrModel, u""_ustr)
,m_nPos(-1)
,m_pLastKnownRefDevice(nullptr)
{ // Stuff that old SetModel also did:
impl_checkRefDevice_nothrow();
}
FmFormObj::FmFormObj(SdrModel& rSdrModel, FmFormObj const & rSource)
: SdrUnoObj(rSdrModel, rSource)
,m_nPos(-1)
,m_pLastKnownRefDevice(nullptr)
{ // Stuff that old SetModel also did:
impl_checkRefDevice_nothrow();
// If UnoControlModel is part of an event environment, // events may assigned to it.
Reference< XFormComponent > xContent(rSource.m_xUnoControlModel, UNO_QUERY); if (xContent.is())
{
Reference< XEventAttacherManager > xManager(xContent->getParent(), UNO_QUERY);
Reference< XIndexAccess > xManagerAsIndex(xManager, UNO_QUERY); if (xManagerAsIndex.is())
{
sal_Int32 nPos = getElementPos( xManagerAsIndex, xContent ); if ( nPos >= 0 )
aEvts = xManager->getScriptEvents( nPos );
}
} else
aEvts = rSource.aEvts;
Reference< XChild > xSourceAsChild(rSource.GetUnoControlModel(), UNO_QUERY); if (!xSourceAsChild.is()) return;
ensureModelEnv(xSourceContainer, m_xEnvironmentHistory);
m_aEventsHistory = aEvts; // if we were clone there was a call to operator=, so aEvts are exactly the events we need here...
}
FmFormObj::~FmFormObj()
{
if (m_xEnvironmentHistory.is())
m_xEnvironmentHistory->dispose();
FmFormPage* pNewFormPage = dynamic_cast<FmFormPage*>( pNewPage ); if ( !pNewFormPage )
{ // Maybe it makes sense to create an environment history here : if somebody set's our page to NULL, and we have a valid page before, // me may want to remember our place within the old page. For this we could create a new m_xEnvironmentHistory to store it. // So the next SetPage with a valid new page would restore that environment within the new page. // But for the original Bug (#57300#) we don't need that, so I omit it here. Maybe this will be implemented later.
impl_isolateControlModel_nothrow();
SdrUnoObj::handlePageChange(pOldPage, pNewPage); return;
}
// calc the new parent for my model (within the new page's forms hierarchy) // do we have a history ? (from :Clone) if ( m_xEnvironmentHistory.is() )
{ // the element in m_xEnvironmentHistory which is equivalent to my new parent (which (perhaps) has to be created within pNewPage->GetForms) // is the right-most element in the tree.
Reference< XIndexContainer > xRightMostLeaf( m_xEnvironmentHistory, UNO_QUERY_THROW ); try
{ while ( xRightMostLeaf->getCount() )
{
xRightMostLeaf.set(
xRightMostLeaf->getByIndex( xRightMostLeaf->getCount() - 1 ),
UNO_QUERY_THROW
);
}
// we successfully cloned the environment in m_xEnvironmentHistory, so we can use m_aEventsHistory // (which describes the events of our model at the moment m_xEnvironmentHistory was created)
aNewEvents = m_aEventsHistory;
} catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("svx");
}
}
if ( !xNewParent.is() )
{ // are we a valid part of our current page forms ?
Reference< XIndexContainer > xOldForms; if ( pOldFormPage )
xOldForms.set( pOldFormPage->GetForms(), UNO_QUERY_THROW );
if ( xOldForms.is() )
{ // search (upward from our model) for xOldForms
Reference< XChild > xSearch( GetUnoControlModel(), UNO_QUERY ); while (xSearch.is())
{ if ( xSearch == xOldForms ) break;
xSearch.set( xSearch->getParent(), UNO_QUERY );
} if ( xSearch.is() ) // implies xSearch == xOldForms, which means we're a valid part of our current page forms hierarchy
{
Reference< XChild > xMeAsChild( GetUnoControlModel(), UNO_QUERY );
xNewParent.set( ensureModelEnv( xMeAsChild->getParent(), xNewPageForms ), UNO_QUERY );
if ( xNewParent.is() )
{ try
{ // transfer the events from our (model's) parent to the new (model's) parent, too
Reference< XEventAttacherManager > xEventManager(xMeAsChild->getParent(), UNO_QUERY);
Reference< XIndexAccess > xManagerAsIndex(xEventManager, UNO_QUERY); if (xManagerAsIndex.is())
{
sal_Int32 nPos = getElementPos(xManagerAsIndex, xMeAsChild); if (nPos >= 0)
aNewEvents = xEventManager->getScriptEvents(nPos);
} else
aNewEvents = aEvts;
} catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("svx");
}
}
}
}
}
// now set the page
SdrUnoObj::handlePageChange(pOldPage, pNewPage);
// place my model within the new parent container if (xNewParent.is())
{
Reference< XFormComponent > xMeAsFormComp(GetUnoControlModel(), UNO_QUERY); if (xMeAsFormComp.is())
{ // check if I have another parent (and remove me, if necessary)
Reference< XIndexContainer > xOldParent(xMeAsFormComp->getParent(), UNO_QUERY); if (xOldParent.is())
{
sal_Int32 nPos = getElementPos(xOldParent, xMeAsFormComp); if (nPos > -1)
xOldParent->removeByIndex(nPos);
}
// and insert into the new container
xNewParent->insertByIndex(xNewParent->getCount(), Any(xMeAsFormComp));
// transfer the events if (aNewEvents.hasElements())
{ try
{
Reference< XEventAttacherManager > xEventManager(xNewParent, UNO_QUERY);
Reference< XIndexAccess > xManagerAsIndex(xEventManager, UNO_QUERY); if (xManagerAsIndex.is())
{
sal_Int32 nPos = getElementPos(xManagerAsIndex, xMeAsFormComp);
DBG_ASSERT(nPos >= 0, "FmFormObj::SetPage : inserted but not present ?");
xEventManager->registerScriptEvents(nPos, aNewEvents);
}
} catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("svx");
}
}
}
}
// delete my history if (m_xEnvironmentHistory.is())
m_xEnvironmentHistory->dispose();
// while the current content is a form
OUString sReturn; while (xChild.is())
{ // get the content's relative pos within its parent container
sal_Int32 nPos = getElementPos(xParent, xChild);
// prepend this current relative pos
OUString sCurrentIndex = OUString::number(nPos); if (!sReturn.isEmpty())
{
sCurrentIndex += "\\" + sReturn;
}
sReturn = sCurrentIndex;
// travel up
xChild.set(xParent, css::uno::UNO_QUERY); if (xChild.is())
xParent.set(xChild->getParent(), UNO_QUERY);
}
_rTopLevelElement = xParent; return sReturn;
}
}
Reference< XInterface > FmFormObj::ensureModelEnv(const Reference< XInterface > & _rSourceContainer, const Reference<css::form::XForms>& _rTopLevelDestContainer)
{
Reference< XInterface > xTopLevelSource;
OUString sAccessPath = lcl_getFormComponentAccessPath(_rSourceContainer, xTopLevelSource); if (!xTopLevelSource.is()) // something went wrong, maybe _rSourceContainer isn't part of a valid forms hierarchy return Reference< XInterface > ();
Reference< XIndexContainer > xDestContainer(_rTopLevelDestContainer, UNO_QUERY_THROW);
Reference< XIndexContainer > xSourceContainer(xTopLevelSource, UNO_QUERY);
DBG_ASSERT(xSourceContainer.is(), "FmFormObj::ensureModelEnv : the top level source is invalid !");
// get the DSS of the source form (we have to find an equivalent for)
DBG_ASSERT(nIndex<xSourceContainer->getCount(), "FmFormObj::ensureModelEnv : invalid access path !");
Reference< XPropertySet > xSourceForm;
xSourceContainer->getByIndex(nIndex) >>= xSourceForm;
DBG_ASSERT(xSourceForm.is(), "FmFormObj::ensureModelEnv : invalid source form !");
Any aSrcCursorSource, aSrcCursorSourceType, aSrcDataSource;
DBG_ASSERT(::comphelper::hasProperty(FM_PROP_COMMAND, xSourceForm) && ::comphelper::hasProperty(FM_PROP_COMMANDTYPE, xSourceForm)
&& ::comphelper::hasProperty(FM_PROP_DATASOURCE, xSourceForm), "FmFormObj::ensureModelEnv : invalid access path or invalid form (missing props) !"); // the parent access path should refer to a row set try
{
aSrcCursorSource = xSourceForm->getPropertyValue(FM_PROP_COMMAND);
aSrcCursorSourceType = xSourceForm->getPropertyValue(FM_PROP_COMMANDTYPE);
aSrcDataSource = xSourceForm->getPropertyValue(FM_PROP_DATASOURCE);
} catch(Exception&)
{
OSL_FAIL("FmFormObj::ensureModelEnv : could not retrieve a source DSS !");
}
// calc the number of (source) form siblings with the same DSS
Reference< XPropertySet > xCurrentSourceForm, xCurrentDestForm;
sal_Int16 nCurrentSourceIndex = 0;
sal_Int32 nCurrentDestIndex = 0; while (nCurrentSourceIndex <= nIndex)
{ bool bEqualDSS = false; while (!bEqualDSS) // (we don't have to check nCurrentSourceIndex here : it's bound by nIndex)
{
xSourceContainer->getByIndex(nCurrentSourceIndex) >>= xCurrentSourceForm;
DBG_ASSERT(xCurrentSourceForm.is(), "FmFormObj::ensureModelEnv : invalid form ancestor (2) !");
bEqualDSS = false; if (::comphelper::hasProperty(FM_PROP_DATASOURCE, xCurrentSourceForm))
{ // it is a form try
{ if ( xCurrentSourceForm->getPropertyValue(FM_PROP_COMMAND) == aSrcCursorSource
&& xCurrentSourceForm->getPropertyValue(FM_PROP_COMMANDTYPE) == aSrcCursorSourceType
&& xCurrentSourceForm->getPropertyValue(FM_PROP_DATASOURCE) == aSrcDataSource
)
{
bEqualDSS = true;
}
} catch(Exception&)
{
TOOLS_WARN_EXCEPTION("svx.form", "exception while getting a sibling's DSS !");
}
}
++nCurrentSourceIndex;
}
DBG_ASSERT(bEqualDSS, "FmFormObj::ensureModelEnv : found no source form !"); // ??? at least the nIndex-th one should have been found ???
// now search the next one with the given DSS (within the destination container)
bEqualDSS = false; while (!bEqualDSS && (nCurrentDestIndex < xDestContainer->getCount()))
{
xDestContainer->getByIndex(nCurrentDestIndex) >>= xCurrentDestForm;
DBG_ASSERT(xCurrentDestForm.is(), "FmFormObj::ensureModelEnv : invalid destination form !");
bEqualDSS = false; if (::comphelper::hasProperty(FM_PROP_DATASOURCE, xCurrentDestForm))
{ // it is a form try
{ if ( xCurrentDestForm->getPropertyValue(FM_PROP_COMMAND) == aSrcCursorSource
&& xCurrentDestForm->getPropertyValue(FM_PROP_COMMANDTYPE) == aSrcCursorSourceType
&& xCurrentDestForm->getPropertyValue(FM_PROP_DATASOURCE) == aSrcDataSource
)
{
bEqualDSS = true;
}
} catch(Exception&)
{
TOOLS_WARN_EXCEPTION("svx.form", "exception while getting a destination DSS !");
}
}
++nCurrentDestIndex;
}
if (!bEqualDSS)
{ // There is at least one more source form with the given DSS than destination forms are. // correct this ... try
{ // create and insert (into the destination) a copy of the form
xCurrentDestForm.set(
::comphelper::getProcessServiceFactory()->createInstance(u"com.sun.star.form.component.DataForm"_ustr),
UNO_QUERY_THROW );
::comphelper::copyProperties( xCurrentSourceForm, xCurrentDestForm );
DBG_ASSERT(nCurrentDestIndex == xDestContainer->getCount(), "FmFormObj::ensureModelEnv : something went wrong with the numbers !");
xDestContainer->insertByIndex(nCurrentDestIndex, Any(xCurrentDestForm));
++nCurrentDestIndex; // like nCurrentSourceIndex, nCurrentDestIndex now points 'behind' the form it actually means
} catch(Exception&)
{
OSL_FAIL("FmFormObj::ensureModelEnv : something went seriously wrong while creating a new form !"); // no more options anymore ... return Reference< XInterface > ();
}
}
}
// now xCurrentDestForm is a form equivalent to xSourceForm (which means they have the same DSS and the same number // of left siblings with the same DSS, which counts for all their ancestors, too)
// go down
xDestContainer.set(xCurrentDestForm, UNO_QUERY);
xSourceContainer.set(xSourceForm, UNO_QUERY);
DBG_ASSERT(xDestContainer.is() && xSourceContainer.is(), "FmFormObj::ensureModelEnv : invalid container !");
} while ( nTokIndex >= 0 );
if ( !xParentForm.is() )
{ // model is not yet part of a form component hierarchy
xParentForm.set( pFormPage->GetImpl().findPlaceInFormComponentHierarchy( xContent ), UNO_SET_THROW );
xFormToInsertInto.set( xParentForm, UNO_QUERY_THROW );
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.