/* -*- 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 .
*/
// Try getting the code name from the container first (faster), // then from the element if that fails (slower).
Reference<XInterface> xThis = static_cast<XContainer*>(this);
OUString sCodeName = xNameQuery->getCodeNameForContainer(xThis); if (sCodeName.isEmpty())
sCodeName = xNameQuery->getCodeNameForObject(xElement);
void OInterfaceContainer::disposing()
{ // dispose all elements for (sal_Int32 i = m_aItems.size(); i > 0; --i)
{
Reference<XPropertySet> xSet(m_aItems[i - 1], UNO_QUERY); if (xSet.is())
xSet->removePropertyChangeListener(PROPERTY_NAME, this);
// revoke event knittings if ( m_xEventAttacher.is() )
{
m_xEventAttacher->detach( i - 1, Reference<XInterface>(xSet, UNO_QUERY) );
m_xEventAttacher->removeEntry( i - 1 );
}
Reference<XComponent> xComponent(xSet, UNO_QUERY); if (xComponent.is())
xComponent->dispose();
}
m_aMap.clear();
m_aItems.clear();
sal_Int32 i=0; for (autoconst& elem : _rSave)
{
_rxManager->revokeScriptEvents( i );
_rxManager->registerScriptEvents(i, elem);
++i;
}
}
}
void SAL_CALL OInterfaceContainer::writeEvents(const Reference<XObjectOutputStream>& _rxOutStream)
{ // We're writing a document in SO 5.2 format (or even from earlier versions) // -> convert the events from the new runtime format to the format of the 5.2 files // but before, remember the current script events set for our children
::std::vector< Sequence< ScriptEventDescriptor > > aSave; if ( m_xEventAttacher.is() )
lcl_saveEvents( aSave, m_xEventAttacher, m_aItems.size() );
// it's a starbasic macro
sal_Int32 nPrefixLength = _rDescriptor.ScriptCode.indexOf( ':' ); if ( 0 <= nPrefixLength )
{ // the macro name does not already contain a : #ifdef DBG_UTIL const OUString sPrefix = _rDescriptor.ScriptCode.copy( 0, nPrefixLength );
DBG_ASSERT( sPrefix == "document"
|| sPrefix == "application", "TransformEventTo52Format: invalid (unknown) prefix!" ); #endif // cut the prefix
_rDescriptor.ScriptCode = _rDescriptor.ScriptCode.copy( nPrefixLength + 1 );
}
}
};
}
void OInterfaceContainer::transformEvents()
{
OSL_ENSURE( m_xEventAttacher.is(), "OInterfaceContainer::transformEvents: no event attacher manager!" ); if ( !m_xEventAttacher.is() ) return;
try
{ // loop through all our children
sal_Int32 nItems = m_aItems.size();
Sequence< ScriptEventDescriptor > aChildEvents;
for (sal_Int32 i=0; i<nItems; ++i)
{ // get the script events for this object
aChildEvents = m_xEventAttacher->getScriptEvents( i );
if ( aChildEvents.hasElements() )
{ // do the transformation auto [begin, end] = asNonConstRange(aChildEvents);
::std::for_each( begin, end, TransformEventTo52Format() );
// revoke the script events
m_xEventAttacher->revokeScriptEvents( i ); // and re-register them
m_xEventAttacher->registerScriptEvents( i, aChildEvents );
}
}
} catch( const Exception& )
{
DBG_UNHANDLED_EXCEPTION("forms.misc");
}
}
// after ::read the object is expected to be in the state it was when ::write was called, so we have // to empty ourself here while (getCount())
removeByIndex(0);
// Only writes depending on the length
sal_Int32 nLen = _rxInStream->readLong();
if (nLen)
{ // 1. Version
_rxInStream->readShort();
// 2. Objects for (sal_Int32 i = 0; i < nLen; i++)
{
Reference<XPersistObject> xObj; try
{
xObj = _rxInStream->readObject();
} catch(const WrongFormatException&)
{ // the object could not be read // create an object (so the readEvents below will assign the events to the right controls)
xObj = lcl_createPlaceHolder( m_xContext ); if ( !xObj.is() ) // couldn't handle it throw;
} catch(const Exception&)
{ // Clear the map while (!m_aItems.empty())
removeElementsNoEvents();
// Rethrow the exception throw;
}
if ( xObj.is() )
{
Reference< XPropertySet > xElement( xObj, UNO_QUERY ); try
{
implInsert(
m_aItems.size(), // position
xElement, // element to insert false, // no event attacher manager handling
nullptr, // not yet approved - let implInsert do it true// fire the event
);
} catch( const Exception& )
{
SAL_WARN("forms.misc", "OInterfaceContainerHelper3::read: reading succeeded, but not inserting!" ); // create a placeholder
xElement.set(lcl_createPlaceHolder( m_xContext ), css::uno::UNO_QUERY); if ( !xElement.is() ) // couldn't handle it throw; // insert the placeholder
implInsert( m_aItems.size(), xElement, false, nullptr, true );
}
}
}
OInterfaceArray::iterator j; for ( j = m_aItems.begin(); j != m_aItems.end(); ++j )
{
DBG_ASSERT( j->get() == Reference< XInterface >( *j, UNO_QUERY ).get(), "OInterfaceContainer::disposing: vector element not normalized!" );
if ( xSource.get() == j->get() ) // found the element break;
}
if ( m_aItems.end() == j ) return;
m_aItems.erase(j);
// look up in, and erase from, m_aMap, too
OInterfaceMap::iterator i = m_aMap.begin(); while ( i != m_aMap.end() )
{
DBG_ASSERT( i->second.get() == Reference< XInterface >( i->second, UNO_QUERY ).get(), "OInterfaceContainer::disposing: map element not normalized!" );
if ( i->second.get() == xSource.get() )
{ // found it
m_aMap.erase(i); break;
}
++i;
DBG_ASSERT( i != m_aMap.end(), "OInterfaceContainer::disposing: inconsistency: the element was in m_aItems, but not in m_aMap!" );
}
}
// XPropertyChangeListener
void OInterfaceContainer::propertyChange(const PropertyChangeEvent& evt) { if (evt.PropertyName != PROPERTY_NAME) return;
::osl::MutexGuard aGuard( m_rMutex ); auto range = m_aMap.equal_range(::comphelper::getString(evt.OldValue)); for (auto it = range.first; it != range.second; ++it) if (it->second == evt.Source)
{
css::uno::Reference<css::uno::XInterface> xCorrectType(it->second);
m_aMap.erase(it);
m_aMap.insert(::std::pair<const OUString, css::uno::Reference<css::uno::XInterface> >(::comphelper::getString(evt.NewValue),xCorrectType)); break;
}
}
void OInterfaceContainer::approveNewElement( const Reference< XPropertySet >& _rxObject, ElementDescription* _pElement )
{ // it has to be non-NULL if ( !_rxObject.is() ) throw IllegalArgumentException(ResourceManager::loadString(RID_STR_NEED_NON_NULL_OBJECT), static_cast<XContainer*>(this), 1);
// it has to support our element type interface
Any aCorrectType = _rxObject->queryInterface( m_aElementType ); if ( !aCorrectType.hasValue() ) throw IllegalArgumentException();
// it has to have a "Name" property if ( !hasProperty( PROPERTY_NAME, _rxObject ) ) throw IllegalArgumentException();
// it has to be a child, and it must not have a parent already
Reference< XChild > xChild( _rxObject, UNO_QUERY ); if ( !xChild.is() || xChild->getParent().is() )
{ throw IllegalArgumentException();
}
// passed all tests. cache the information we have so far
DBG_ASSERT( _pElement, "OInterfaceContainer::approveNewElement: invalid event descriptor!" ); if ( _pElement )
{
_pElement->xPropertySet = _rxObject;
_pElement->xChild = std::move(xChild);
_pElement->aElementTypeInterface = std::move(aCorrectType);
_pElement->xInterface = Reference< XInterface >( _rxObject, UNO_QUERY ); // normalized XInterface
}
}
std::unique_ptr< ElementDescription > aAutoDeleteMetaData;
ElementDescription* pElementMetaData = _pApprovalResult; if ( !pElementMetaData )
{ // not yet approved by the caller -> do ourself
pElementMetaData = createElementMetaData();
assert(pElementMetaData && "OInterfaceContainer::implInsert: createElementMetaData returned nonsense!");
// ensure that the meta data structure will be deleted later on
aAutoDeleteMetaData.reset( pElementMetaData );
// will throw an exception if necessary
approveNewElement( _rxElement, pElementMetaData );
}
// approveNewElement (no matter if called here or outside) has ensure that all relevant interfaces // exist
// set the name, and add as change listener for the name
OUString sName;
_rxElement->getPropertyValue(PROPERTY_NAME) >>= sName;
_rxElement->addPropertyChangeListener(PROPERTY_NAME, this);
// insert the object into our internal structures if (_nIndex > static_cast<sal_Int32>(m_aItems.size())) // Calculate the actual index
{
_nIndex = m_aItems.size();
m_aItems.push_back( pElementMetaData->xInterface );
} else
m_aItems.insert( m_aItems.begin() + _nIndex, pElementMetaData->xInterface );
// approve the new object
std::unique_ptr< ElementDescription > aElementMetaData( createElementMetaData() );
DBG_ASSERT(aElementMetaData, "OInterfaceContainer::implReplaceByIndex: createElementMetaData returned nonsense!");
{
Reference< XPropertySet > xElementProps;
_rNewElement >>= xElementProps;
approveNewElement( xElementProps, aElementMetaData.get() );
}
// get the old element
css::uno::Reference<css::uno::XInterface> xOldElement( m_aItems[ _nIndex ] );
DBG_ASSERT( xOldElement.get() == Reference< XInterface >( xOldElement, UNO_QUERY ).get(), "OInterfaceContainer::implReplaceByIndex: elements should be held normalized!" );
// locate the old element in the map
OInterfaceMap::iterator j = std::find_if(m_aMap.begin(), m_aMap.end(),
[&xOldElement](const OInterfaceMap::value_type& rEntry) { return rEntry.second.get() == xOldElement.get(); });
// don't listen for property changes anymore
Reference<XPropertySet> xSet( xOldElement, UNO_QUERY ); if (xSet.is())
xSet->removePropertyChangeListener(PROPERTY_NAME, this);
// give the old element a new (void) parent
Reference<XChild> xChild(xOldElement, UNO_QUERY); if (xChild.is())
xChild->setParent(css::uno::Reference<css::uno::XInterface> ());
// remove the old one
m_aMap.erase(j);
// examine the new element
OUString sName;
DBG_ASSERT(aElementMetaData->xPropertySet.is(), "OInterfaceContainer::implReplaceByIndex: what did approveNewElement do?");
// insert the new one
m_aMap.insert(::std::pair<const OUString, css::uno::Reference<css::uno::XInterface>>(
sName, aElementMetaData->xInterface));
m_aItems[_nIndex] = aElementMetaData->xInterface;
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 ist noch experimentell.