diff options
Diffstat (limited to 'sd/source/core')
39 files changed, 23894 insertions, 0 deletions
diff --git a/sd/source/core/CustomAnimationCloner.cxx b/sd/source/core/CustomAnimationCloner.cxx new file mode 100644 index 000000000000..4b7cf5dee74c --- /dev/null +++ b/sd/source/core/CustomAnimationCloner.cxx @@ -0,0 +1,343 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <com/sun/star/animations/XAnimationNode.hpp> +#include <com/sun/star/animations/Event.hpp> +#include <com/sun/star/animations/XAnimateColor.hpp> +#include <com/sun/star/animations/XAnimateSet.hpp> +#include <com/sun/star/animations/XCommand.hpp> +#include <com/sun/star/animations/XAnimateMotion.hpp> +#include <com/sun/star/animations/XAnimateTransform.hpp> +#include <com/sun/star/animations/XTransitionFilter.hpp> +#include <com/sun/star/animations/XIterateContainer.hpp> +#include <com/sun/star/animations/XAudio.hpp> +#include <com/sun/star/animations/AnimationNodeType.hpp> +#include <com/sun/star/animations/ValuePair.hpp> +#include <com/sun/star/presentation/EffectNodeType.hpp> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/presentation/ParagraphTarget.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/beans/NamedValue.hpp> + +#include <map> + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "rtl/ref.hxx" +#include <animations/animationnodehelper.hxx> + +// header for class SdrObjListIter +#include <svx/svditer.hxx> + +#include "sdpage.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::container; + +using ::rtl::OUString; +using ::rtl::OString; +using ::com::sun::star::drawing::XShape; +using ::com::sun::star::beans::NamedValue; + +namespace sd +{ + class CustomAnimationClonerImpl + { + public: + CustomAnimationClonerImpl(); + Reference< XAnimationNode > Clone( const Reference< XAnimationNode >& xSourceNode, const SdPage* pSource = 0, const SdPage* pTarget = 0 ); + + private: + void transformNode( const Reference< XAnimationNode >& xNode ); + Any transformValue( const Any& rValue ); + + Reference< XShape > getClonedShape( const Reference< XShape >& xSource ) const; + Reference< XAnimationNode > getClonedNode( const Reference< XAnimationNode >& xSource ) const; + + mutable ::std::map< Reference< XShape >, Reference< XShape > > maShapeMap; + std::vector< Reference< XAnimationNode > > maSourceNodeVector; + std::vector< Reference< XAnimationNode > > maCloneNodeVector; + }; + + CustomAnimationClonerImpl::CustomAnimationClonerImpl() + { + } + + Reference< XAnimationNode > Clone( const Reference< XAnimationNode >& xSourceNode, const SdPage* pSource, const SdPage* pTarget ) + { + CustomAnimationClonerImpl aCloner; + return aCloner.Clone( xSourceNode, pSource, pTarget ); + } + + Reference< XAnimationNode > CustomAnimationClonerImpl::Clone( const Reference< XAnimationNode >& xSourceNode, const SdPage* pSourcePage, const SdPage* pTargetPage ) + { + try + { + // clone animation hierarchie + Reference< ::com::sun::star::util::XCloneable > xClonable( xSourceNode, UNO_QUERY_THROW ); + Reference< XAnimationNode > xCloneNode( xClonable->createClone(), UNO_QUERY_THROW ); + + // create a dictionary to map source to cloned shapes + if( pSourcePage && pTargetPage ) + { + SdrObjListIter aSourceIter( *pSourcePage, IM_DEEPWITHGROUPS ); + SdrObjListIter aTargetIter( *pTargetPage, IM_DEEPWITHGROUPS ); + + while( aSourceIter.IsMore() && aTargetIter.IsMore() ) + { + SdrObject* pSource = aSourceIter.Next(); + SdrObject* pTarget = aTargetIter.Next(); + + if( pSource && pTarget) + { + Reference< XShape > xSource( pSource->getUnoShape(), UNO_QUERY ); + Reference< XShape > xTarget( pTarget->getUnoShape(), UNO_QUERY ); + if( xSource.is() && xTarget.is() ) + { + maShapeMap[xSource] = xTarget; + } + } + } + } + + // create a dictionary to map source to cloned nodes + ::anim::create_deep_vector( xSourceNode, maSourceNodeVector ); + ::anim::create_deep_vector( xCloneNode, maCloneNodeVector ); + + transformNode( xCloneNode ); + + return xCloneNode; + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( + (OString("sd::CustomAnimationClonerImpl::Clone(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + + Reference< XAnimationNode > xEmpty; + return xEmpty; + } + } + + void CustomAnimationClonerImpl::transformNode( const Reference< XAnimationNode >& xNode ) + { + try + { + xNode->setBegin( transformValue( xNode->getBegin() ) ); + xNode->setEnd( transformValue( xNode->getEnd() ) ); + + sal_Int16 nNodeType( xNode->getType() ); + switch( nNodeType ) + { + case AnimationNodeType::ITERATE: + { + Reference< XIterateContainer > xIter( xNode, UNO_QUERY_THROW ); + xIter->setTarget( transformValue( xIter->getTarget() ) ); + } + // its intended that here is no break! + case AnimationNodeType::PAR: + case AnimationNodeType::SEQ: + { + Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW ); + transformNode( xChildNode ); + } + } + break; + + case AnimationNodeType::ANIMATE: + case AnimationNodeType::SET: + case AnimationNodeType::ANIMATEMOTION: + case AnimationNodeType::ANIMATECOLOR: + case AnimationNodeType::ANIMATETRANSFORM: + case AnimationNodeType::TRANSITIONFILTER: + { + Reference< XAnimate > xAnimate( xNode, UNO_QUERY_THROW ); + xAnimate->setTarget( transformValue( xAnimate->getTarget() ) ); + } + break; + + case AnimationNodeType::COMMAND: + { + Reference< XCommand > xCommand( xNode, UNO_QUERY_THROW ); + xCommand->setTarget( transformValue( xCommand->getTarget() ) ); + } + break; + + case AnimationNodeType::AUDIO: + { + Reference< XAudio > xAudio( xNode, UNO_QUERY_THROW ); + xAudio->setSource( transformValue( xAudio->getSource() ) ); + } + break; + } + + Sequence< NamedValue > aUserData( xNode->getUserData() ); + if( aUserData.hasElements() ) + { + NamedValue* pValue = aUserData.getArray(); + const sal_Int32 nLength = aUserData.getLength(); + sal_Int32 nElement; + for( nElement = 0; nElement < nLength; nElement++, pValue++ ) + { + pValue->Value = transformValue( pValue->Value ); + } + + xNode->setUserData( aUserData ); + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( + (OString("sd::CustomAnimationClonerImpl::transformNode(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + } + } + + Any CustomAnimationClonerImpl::transformValue( const Any& rValue ) + { + if( rValue.hasValue() ) try + { + if( rValue.getValueType() == ::getCppuType((const ValuePair*)0) ) + { + ValuePair aValuePair; + rValue >>= aValuePair; + + aValuePair.First = transformValue( aValuePair.First ); + aValuePair.Second = transformValue( aValuePair.Second ); + + return makeAny( aValuePair ); + } + else if( rValue.getValueType() == ::getCppuType((Sequence<Any>*)0) ) + { + Sequence<Any> aSequence; + rValue >>= aSequence; + + const sal_Int32 nLength = aSequence.getLength(); + sal_Int32 nElement; + Any* pAny = aSequence.getArray(); + + for( nElement = 0; nElement < nLength; nElement++, pAny++ ) + *pAny = transformValue( *pAny ); + + return makeAny( aSequence ); + } + else if( rValue.getValueTypeClass() == TypeClass_INTERFACE ) + { + Reference< XShape > xShape; + rValue >>= xShape; + if( xShape.is() ) + { + return makeAny( getClonedShape( xShape ) ); + } + else + { + Reference< XAnimationNode > xNode; + rValue >>= xNode; + if( xNode.is() ) + return makeAny( getClonedNode( xNode ) ); + } + } + else if( rValue.getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + { + ParagraphTarget aParaTarget; + rValue >>= aParaTarget; + + aParaTarget.Shape = getClonedShape( aParaTarget.Shape ); + + return makeAny( aParaTarget ); + } + else if( rValue.getValueType() == ::getCppuType((const Event*)0) ) + { + Event aEvent; + rValue >>= aEvent; + + aEvent.Source = transformValue( aEvent.Source ); + + return makeAny( aEvent ); + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( + (OString("sd::CustomAnimationClonerImpl::transformValue(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 )).getStr() ); + } + + return rValue; + } + + Reference< XShape > CustomAnimationClonerImpl::getClonedShape( const Reference< XShape >& xSource ) const + { + if( xSource.is() ) + { + if( maShapeMap.find(xSource) != maShapeMap.end() ) + { + return maShapeMap[xSource]; + } + + DBG_ASSERT( maShapeMap.empty(), "sd::CustomAnimationClonerImpl::getClonedShape() failed!" ); + } + return xSource; + } + + Reference< XAnimationNode > CustomAnimationClonerImpl::getClonedNode( const Reference< XAnimationNode >& xSource ) const + { + sal_Int32 nNode, nNodeCount = maSourceNodeVector.size(); + + for( nNode = 0; nNode < nNodeCount; nNode++ ) + { + if( maSourceNodeVector[nNode] == xSource ) + return maCloneNodeVector[nNode]; + } + + DBG_ERROR( "sd::CustomAnimationClonerImpl::getClonedNode() failed!" ); + return xSource; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/CustomAnimationEffect.cxx b/sd/source/core/CustomAnimationEffect.cxx new file mode 100644 index 000000000000..058b51efea16 --- /dev/null +++ b/sd/source/core/CustomAnimationEffect.cxx @@ -0,0 +1,3795 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <tools/debug.hxx> +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/animations/AnimationFill.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/presentation/EffectNodeType.hpp> +#include <com/sun/star/presentation/EffectCommands.hpp> +#include <com/sun/star/presentation/EffectPresetClass.hpp> +#include <com/sun/star/presentation/ParagraphTarget.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/presentation/ShapeAnimationSubType.hpp> +#include <com/sun/star/animations/AnimationNodeType.hpp> +#include <com/sun/star/animations/XCommand.hpp> +#include <com/sun/star/animations/AnimationTransformType.hpp> +#include <com/sun/star/animations/XIterateContainer.hpp> +#include <com/sun/star/animations/XAnimateTransform.hpp> +#include <com/sun/star/animations/Event.hpp> +#include <com/sun/star/animations/EventTrigger.hpp> +#include <com/sun/star/animations/Timing.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/animations/XAnimate.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/util/XChangesNotifier.hpp> +#include <com/sun/star/animations/XAnimateMotion.hpp> +#include <comphelper/processfactory.hxx> +#include <comphelper/sequence.hxx> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/i18n/XBreakIterator.hpp> +#include <com/sun/star/i18n/CharacterIteratorMode.hpp> +#include <com/sun/star/i18n/WordType.hpp> +#include <com/sun/star/presentation/TextAnimationType.hpp> + +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> + +#include <algorithm> + +#include <cppuhelper/implbase1.hxx> + +#include <svx/svdopath.hxx> +#include <svx/svdpage.hxx> +#include <svx/unoapi.hxx> +#include "CustomAnimationEffect.hxx" +#include <CustomAnimationPreset.hxx> +#include "animations.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::presentation; +using namespace ::com::sun::star::animations; + +using ::rtl::OUString; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::XInterface; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::makeAny; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::container::XEnumerationAccess; +using ::com::sun::star::container::XEnumeration; +using ::com::sun::star::beans::NamedValue; +using ::com::sun::star::container::XChild; +using ::com::sun::star::container::XElementAccess; +using ::com::sun::star::drawing::XShape; +using ::com::sun::star::lang::XInitialization; +using ::com::sun::star::drawing::XShapes; +using ::com::sun::star::drawing::XDrawPage; +using ::com::sun::star::text::XText; +using ::com::sun::star::text::XTextRange; +using ::com::sun::star::beans::XPropertySet; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::util::XCloneable; +using ::com::sun::star::lang::Locale; +using ::com::sun::star::util::XChangesNotifier; +using ::com::sun::star::util::XChangesListener; + +namespace sd +{ +class MainSequenceChangeGuard +{ +public: + MainSequenceChangeGuard( EffectSequenceHelper* pSequence ) + { + mpMainSequence = dynamic_cast< MainSequence* >( pSequence ); + if( mpMainSequence == 0 ) + { + InteractiveSequence* pI = dynamic_cast< InteractiveSequence* >( pSequence ); + if( pI ) + mpMainSequence = pI->mpMainSequence; + } + DBG_ASSERT( mpMainSequence, "sd::MainSequenceChangeGuard::MainSequenceChangeGuard(), no main sequence to guard!" ); + + if( mpMainSequence ) + mpMainSequence->mbIgnoreChanges++; + } + + ~MainSequenceChangeGuard() + { + if( mpMainSequence ) + mpMainSequence->mbIgnoreChanges++; + } + +private: + MainSequence* mpMainSequence; +}; + +CustomAnimationEffect::CustomAnimationEffect( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) +: mnNodeType(-1), + mnPresetClass(-1), + mfBegin(-1.0), + mfDuration(-1.0), + mfAbsoluteDuration(-1.0), + mnGroupId(-1), + mnIterateType(0), + mfIterateInterval(0.0), + mnParaDepth( -1 ), + mbHasText(sal_False), + mfAcceleration( 1.0 ), + mfDecelerate( 1.0 ), + mbAutoReverse(false), + mnTargetSubItem(0), + mnCommand(0), + mpEffectSequence( 0 ), + mbHasAfterEffect(false), + mbAfterEffectOnNextEffect(false) +{ + setNode( xNode ); +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setNode( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) +{ + mxNode = xNode; + mxAudio.clear(); + + Sequence< NamedValue > aUserData( mxNode->getUserData() ); + sal_Int32 nLength = aUserData.getLength(); + const NamedValue* p = aUserData.getConstArray(); + + while( nLength-- ) + { + if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) ) + { + p->Value >>= mnNodeType; + } + else if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-id" ) ) ) + { + p->Value >>= maPresetId; + } + else if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-sub-type" ) ) ) + { + p->Value >>= maPresetSubType; + } + else if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-class" ) ) ) + { + p->Value >>= mnPresetClass; + } + else if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-property" ) ) ) + { + p->Value >>= maProperty; + } + else if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "group-id" ) ) ) + { + p->Value >>= mnGroupId; + } + + p++; + } + + // get effect start time + mxNode->getBegin() >>= mfBegin; + + mfAcceleration = mxNode->getAcceleration(); + mfDecelerate = mxNode->getDecelerate(); + mbAutoReverse = mxNode->getAutoReverse(); + + // get iteration data + Reference< XIterateContainer > xIter( mxNode, UNO_QUERY ); + if( xIter.is() ) + { + mfIterateInterval = xIter->getIterateInterval(); + mnIterateType = xIter->getIterateType(); + maTarget = xIter->getTarget(); + mnTargetSubItem = xIter->getSubItem(); + } + else + { + mfIterateInterval = 0.0f; + mnIterateType = 0; + } + + // calculate effect duration and get target shape + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY ); + if( xEnumerationAccess.is() ) + { + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY ); + if( xEnumeration.is() ) + { + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY ); + if( !xChildNode.is() ) + continue; + + if( xChildNode->getType() == AnimationNodeType::AUDIO ) + { + mxAudio.set( xChildNode, UNO_QUERY ); + } + else if( xChildNode->getType() == AnimationNodeType::COMMAND ) + { + Reference< XCommand > xCommand( xChildNode, UNO_QUERY ); + if( xCommand.is() ) + { + mnCommand = xCommand->getCommand(); + if( !maTarget.hasValue() ) + maTarget = xCommand->getTarget(); + } + } + else + { + double fBegin = 0.0; + double fDuration = 0.0; + xChildNode->getBegin() >>= fBegin; + xChildNode->getDuration() >>= fDuration; + + fDuration += fBegin; + if( fDuration > mfDuration ) + mfDuration = fDuration; + + // no target shape yet? + if( !maTarget.hasValue() ) + { + // go get it boys! + Reference< XAnimate > xAnimate( xChildNode, UNO_QUERY ); + if( xAnimate.is() ) + { + maTarget = xAnimate->getTarget(); + mnTargetSubItem = xAnimate->getSubItem(); + } + } + } + } + } + } + + mfAbsoluteDuration = mfDuration; + checkForText(); +} + +// -------------------------------------------------------------------- + +sal_Int32 CustomAnimationEffect::getNumberOfSubitems( const Any& aTarget, sal_Int16 nIterateType ) +{ + sal_Int32 nSubItems = 0; + + try + { + // first get target text + sal_Int32 nOnlyPara = -1; + + Reference< XText > xShape; + aTarget >>= xShape; + if( !xShape.is() ) + { + ParagraphTarget aParaTarget; + if( aTarget >>= aParaTarget ) + { + xShape.set( aParaTarget.Shape, UNO_QUERY ); + nOnlyPara = aParaTarget.Paragraph; + } + } + + // now use the break iterator to iterate over the given text + // and count the sub items + + if( xShape.is() ) + { + // TODO/LATER: Optimize this, don't create a break iterator each time + Reference< lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory() ); + Reference < i18n::XBreakIterator > xBI( xMSF->createInstance( OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.i18n.BreakIterator" )) ), UNO_QUERY ); + DBG_ASSERT( xBI.is(), "sd::CustomAnimationEffect::getNumberOfSubitems(), could not create a 'com.sun.star.i18n.BreakIterator'!" ); + + if( xBI.is() ) + { + Reference< XEnumerationAccess > xEA( xShape, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEA->createEnumeration(), UNO_QUERY_THROW ); + Locale aLocale; + const OUString aStrLocaleName( RTL_CONSTASCII_USTRINGPARAM("CharLocale") ); + Reference< XTextRange > xParagraph; + + sal_Int32 nPara = 0; + while( xEnumeration->hasMoreElements() ) + { + xEnumeration->nextElement() >>= xParagraph; + + // skip this if its not the only paragraph we want to count + if( (nOnlyPara != -1) && (nOnlyPara != nPara ) ) + continue; + + if( nIterateType == TextAnimationType::BY_PARAGRAPH ) + { + nSubItems++; + } + else + { + const OUString aText( xParagraph->getString() ); + Reference< XPropertySet > xSet( xParagraph, UNO_QUERY_THROW ); + xSet->getPropertyValue( aStrLocaleName ) >>= aLocale; + + sal_Int32 nPos; + const sal_Int32 nEndPos = aText.getLength(); + + if( nIterateType == TextAnimationType::BY_WORD ) + { + for( nPos = 0; nPos < nEndPos; nPos++ ) + { + nPos = xBI->getWordBoundary(aText, nPos, aLocale, i18n::WordType::ANY_WORD, sal_True).endPos; + nSubItems++; + } + break; + } + else + { + sal_Int32 nDone; + for( nPos = 0; nPos < nEndPos; nPos++ ) + { + nPos = xBI->nextCharacters(aText, nPos, aLocale, i18n::CharacterIteratorMode::SKIPCELL, 0, nDone); + nSubItems++; + } + } + } + + if( nPara == nOnlyPara ) + break; + + nPara++; + } + } + } + } + catch( Exception& e ) + { + (void)e; + nSubItems = 0; + DBG_ERROR( "sd::CustomAnimationEffect::getNumberOfSubitems(), exception cought!" ); + } + + return nSubItems; +} + +// -------------------------------------------------------------------- + +CustomAnimationEffect::~CustomAnimationEffect() +{ +} + +// -------------------------------------------------------------------- + +CustomAnimationEffectPtr CustomAnimationEffect::clone() const +{ + Reference< XCloneable > xCloneable( mxNode, UNO_QUERY_THROW ); + Reference< XAnimationNode > xNode( xCloneable->createClone(), UNO_QUERY_THROW ); + CustomAnimationEffectPtr pEffect( new CustomAnimationEffect( xNode ) ); + pEffect->setEffectSequence( getEffectSequence() ); + return pEffect; +} + +// -------------------------------------------------------------------- + +sal_Int32 CustomAnimationEffect::get_node_type( const Reference< XAnimationNode >& xNode ) +{ + sal_Int16 nNodeType = -1; + + if( xNode.is() ) + { + Sequence< NamedValue > aUserData( xNode->getUserData() ); + sal_Int32 nLength = aUserData.getLength(); + if( nLength ) + { + const NamedValue* p = aUserData.getConstArray(); + while( nLength-- ) + { + if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) ) + { + p->Value >>= nNodeType; + break; + } + p++; + } + } + } + + return nNodeType; +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setPresetClass( sal_Int16 nPresetClass ) +{ + if( mnPresetClass != nPresetClass ) + { + mnPresetClass = nPresetClass; + if( mxNode.is() ) + { + // first try to find a "preset-class" entry in the user data + // and change it + Sequence< NamedValue > aUserData( mxNode->getUserData() ); + sal_Int32 nLength = aUserData.getLength(); + bool bFound = false; + if( nLength ) + { + NamedValue* p = aUserData.getArray(); + while( nLength-- ) + { + if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-class" ) ) ) + { + p->Value <<= mnPresetClass; + bFound = true; + break; + } + p++; + } + } + + // no "node-type" entry inside user data, so add it + if( !bFound ) + { + nLength = aUserData.getLength(); + aUserData.realloc( nLength + 1); + aUserData[nLength].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "preset-class" ) ); + aUserData[nLength].Value <<= mnPresetClass; + } + + mxNode->setUserData( aUserData ); + } + } +} + +void CustomAnimationEffect::setNodeType( sal_Int16 nNodeType ) +{ + if( mnNodeType != nNodeType ) + { + mnNodeType = nNodeType; + if( mxNode.is() ) + { + // first try to find a "node-type" entry in the user data + // and change it + Sequence< NamedValue > aUserData( mxNode->getUserData() ); + sal_Int32 nLength = aUserData.getLength(); + bool bFound = false; + if( nLength ) + { + NamedValue* p = aUserData.getArray(); + while( nLength-- ) + { + if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "node-type" ) ) ) + { + p->Value <<= mnNodeType; + bFound = true; + break; + } + p++; + } + } + + // no "node-type" entry inside user data, so add it + if( !bFound ) + { + nLength = aUserData.getLength(); + aUserData.realloc( nLength + 1); + aUserData[nLength].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) ); + aUserData[nLength].Value <<= mnNodeType; + } + + mxNode->setUserData( aUserData ); + } + } +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setGroupId( sal_Int32 nGroupId ) +{ + mnGroupId = nGroupId; + if( mxNode.is() ) + { + // first try to find a "group-id" entry in the user data + // and change it + Sequence< NamedValue > aUserData( mxNode->getUserData() ); + sal_Int32 nLength = aUserData.getLength(); + bool bFound = false; + if( nLength ) + { + NamedValue* p = aUserData.getArray(); + while( nLength-- ) + { + if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "group-id" ) ) ) + { + p->Value <<= mnGroupId; + bFound = true; + break; + } + p++; + } + } + + // no "node-type" entry inside user data, so add it + if( !bFound ) + { + nLength = aUserData.getLength(); + aUserData.realloc( nLength + 1); + aUserData[nLength].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "group-id" ) ); + aUserData[nLength].Value <<= mnGroupId; + } + + mxNode->setUserData( aUserData ); + } +} + +// -------------------------------------------------------------------- + +/** checks if the text for this effect has changed and updates internal flags. + returns true if something changed. +*/ +bool CustomAnimationEffect::checkForText() +{ + bool bChange = false; + + Reference< XText > xText; + + if( maTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + { + // calc para depth + ParagraphTarget aParaTarget; + maTarget >>= aParaTarget; + + xText = Reference< XText >::query( aParaTarget.Shape ); + + // get paragraph + if( xText.is() ) + { + Reference< XEnumerationAccess > xEA( xText, UNO_QUERY ); + if( xEA.is() ) + { + Reference< XEnumeration > xEnumeration( xEA->createEnumeration(), UNO_QUERY ); + if( xEnumeration.is() ) + { + sal_Bool bHasText = xEnumeration->hasMoreElements(); + bChange |= bHasText != mbHasText; + mbHasText = bHasText; + + sal_Int32 nPara = aParaTarget.Paragraph; + + while( xEnumeration->hasMoreElements() && nPara-- ) + xEnumeration->nextElement(); + + if( xEnumeration->hasMoreElements() ) + { + Reference< XPropertySet > xParaSet; + xEnumeration->nextElement() >>= xParaSet; + if( xParaSet.is() ) + { + sal_Int32 nParaDepth = 0; + const OUString strNumberingLevel( RTL_CONSTASCII_USTRINGPARAM("NumberingLevel") ); + xParaSet->getPropertyValue( strNumberingLevel ) >>= nParaDepth; + bChange |= nParaDepth != mnParaDepth; + mnParaDepth = nParaDepth; + } + } + } + } + } + } + else + { + maTarget >>= xText; + sal_Bool bHasText = xText.is() && xText->getString().getLength(); + bChange |= bHasText != mbHasText; + mbHasText = bHasText; + } + + bChange |= calculateIterateDuration(); + return bChange; +} + +bool CustomAnimationEffect::calculateIterateDuration() +{ + bool bChange = false; + + // if we have an iteration, we must also calculate the + // 'true' container duration, that is + // ( ( is form animated ) ? [contained effects duration] : 0 ) + + // ( [number of animated children] - 1 ) * [interval-delay] + [contained effects duration] + Reference< XIterateContainer > xIter( mxNode, UNO_QUERY ); + if( xIter.is() ) + { + double fDuration = mfDuration; + const double fSubEffectDuration = mfDuration; + + if( mnTargetSubItem != ShapeAnimationSubType::ONLY_BACKGROUND ) // does not make sense for iterate container but better check + { + const sal_Int32 nSubItems = getNumberOfSubitems( maTarget, mnIterateType ); + if( nSubItems ) + { + const double f = (nSubItems-1) * mfIterateInterval; + fDuration += f; + } + } + + // if we also animate the form first, we have to add the + // sub effect duration to the whole effect duration + if( mnTargetSubItem == ShapeAnimationSubType::AS_WHOLE ) + fDuration += fSubEffectDuration; + + bChange |= fDuration != mfAbsoluteDuration; + mfAbsoluteDuration = fDuration; + } + + return bChange; +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setTarget( const ::com::sun::star::uno::Any& rTarget ) +{ + try + { + maTarget = rTarget; + + // first, check special case for random node + Reference< XInitialization > xInit( mxNode, UNO_QUERY ); + if( xInit.is() ) + { + const Sequence< Any > aArgs( &maTarget, 1 ); + xInit->initialize( aArgs ); + } + else + { + Reference< XIterateContainer > xIter( mxNode, UNO_QUERY ); + if( xIter.is() ) + { + xIter->setTarget(maTarget); + } + else + { + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY ); + if( xEnumerationAccess.is() ) + { + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY ); + if( xEnumeration.is() ) + { + while( xEnumeration->hasMoreElements() ) + { + const Any aElem( xEnumeration->nextElement() ); + Reference< XAnimate > xAnimate( aElem, UNO_QUERY ); + if( xAnimate.is() ) + xAnimate->setTarget( rTarget ); + else + { + Reference< XCommand > xCommand( aElem, UNO_QUERY ); + if( xCommand.is() ) + xCommand->setTarget( rTarget ); + } + } + } + } + } + } + checkForText(); + } + catch( Exception& ) + { + DBG_ERROR( "sd::CustomAnimationEffect::setTarget(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setTargetSubItem( sal_Int16 nSubItem ) +{ + try + { + mnTargetSubItem = nSubItem; + + Reference< XIterateContainer > xIter( mxNode, UNO_QUERY ); + if( xIter.is() ) + { + xIter->setSubItem(mnTargetSubItem); + } + else + { + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY ); + if( xEnumerationAccess.is() ) + { + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY ); + if( xEnumeration.is() ) + { + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimate > xAnimate( xEnumeration->nextElement(), UNO_QUERY ); + if( xAnimate.is() ) + xAnimate->setSubItem( mnTargetSubItem ); + } + } + } + } + } + catch( Exception& ) + { + DBG_ERROR( "sd::CustomAnimationEffect::setTargetSubItem(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setDuration( double fDuration ) +{ + if( (mfDuration != -1.0) && (mfDuration != fDuration) ) try + { + double fScale = fDuration / mfDuration; + mfDuration = fDuration; + mfAbsoluteDuration = mfDuration; + + // calculate effect duration and get target shape + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY ); + if( xEnumerationAccess.is() ) + { + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY ); + if( xEnumeration.is() ) + { + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY ); + if( !xChildNode.is() ) + continue; + + + double fChildBegin = 0.0; + xChildNode->getBegin() >>= fChildBegin; + if( fChildBegin != 0.0 ) + { + fChildBegin *= fScale; + xChildNode->setBegin( makeAny( fChildBegin ) ); + } + + double fChildDuration = 0.0; + xChildNode->getDuration() >>= fChildDuration; + if( fChildDuration != 0.0 ) + { + fChildDuration *= fScale; + xChildNode->setDuration( makeAny( fChildDuration ) ); + } + } + } + } + calculateIterateDuration(); + } + catch( Exception& ) + { + DBG_ERROR( "sd::CustomAnimationEffect::setDuration(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setBegin( double fBegin ) +{ + if( mxNode.is() ) try + { + mfBegin = fBegin; + mxNode->setBegin( makeAny( fBegin ) ); + } + catch( Exception& ) + { + DBG_ERROR( "sd::CustomAnimationEffect::setBegin(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setAcceleration( double fAcceleration ) +{ + if( mxNode.is() ) try + { + mfAcceleration = fAcceleration; + mxNode->setAcceleration( fAcceleration ); + } + catch( Exception& ) + { + DBG_ERROR( "sd::CustomAnimationEffect::setAcceleration(), exception cought!" ); + } +} +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setDecelerate( double fDecelerate ) +{ + if( mxNode.is() ) try + { + mfDecelerate = fDecelerate; + mxNode->setDecelerate( fDecelerate ); + } + catch( Exception& ) + { + DBG_ERROR( "sd::CustomAnimationEffect::setDecelerate(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setAutoReverse( sal_Bool bAutoReverse ) +{ + if( mxNode.is() ) try + { + mbAutoReverse = bAutoReverse; + mxNode->setAutoReverse( bAutoReverse ); + } + catch( Exception& ) + { + DBG_ERROR( "sd::CustomAnimationEffect::setAutoReverse(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::replaceNode( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) +{ + sal_Int16 nNodeType = mnNodeType; + Any aTarget = maTarget; + + double fBegin = mfBegin; + double fDuration = mfDuration; + double fAcceleration = mfAcceleration; + double fDecelerate = mfDecelerate ; + sal_Bool bAutoReverse = mbAutoReverse; + Reference< XAudio > xAudio( mxAudio ); + sal_Int16 nIterateType = mnIterateType; + double fIterateInterval = mfIterateInterval; + sal_Int16 nSubItem = mnTargetSubItem; + + setNode( xNode ); + + setAudio( xAudio ); + setNodeType( nNodeType ); + setTarget( aTarget ); + setTargetSubItem( nSubItem ); + setDuration( fDuration ); + setBegin( fBegin ); + + setAcceleration( fAcceleration ); + setDecelerate( fDecelerate ); + setAutoReverse( bAutoReverse ); + + if( nIterateType != mnIterateType ) + setIterateType( nIterateType ); + + if( mnIterateType && ( fIterateInterval != mfIterateInterval ) ) + setIterateInterval( fIterateInterval ); +} + +// -------------------------------------------------------------------- + +Reference< XShape > CustomAnimationEffect::getTargetShape() const +{ + Reference< XShape > xShape; + maTarget >>= xShape; + if( !xShape.is() ) + { + ParagraphTarget aParaTarget; + if( maTarget >>= aParaTarget ) + xShape = aParaTarget.Shape; + } + + return xShape; +} + +// -------------------------------------------------------------------- + +Any CustomAnimationEffect::getRepeatCount() const +{ + if( mxNode.is() ) + { + return mxNode->getRepeatCount(); + } + else + { + Any aAny; + return aAny; + } +} + +// -------------------------------------------------------------------- + +Any CustomAnimationEffect::getEnd() const +{ + if( mxNode.is() ) + { + return mxNode->getEnd(); + } + else + { + Any aAny; + return aAny; + } +} + +// -------------------------------------------------------------------- + +sal_Int16 CustomAnimationEffect::getFill() const +{ + if( mxNode.is() ) + return mxNode->getFill(); + else + return 0; +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setRepeatCount( const Any& rRepeatCount ) +{ + if( mxNode.is() ) + mxNode->setRepeatCount( rRepeatCount ); +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setEnd( const Any& rEnd ) +{ + if( mxNode.is() ) + mxNode->setEnd( rEnd ); +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setFill( sal_Int16 nFill ) +{ + if( mxNode.is() ) + mxNode->setFill( nFill ); +} + +// -------------------------------------------------------------------- + +Reference< XAnimationNode > CustomAnimationEffect::createAfterEffectNode() const throw (Exception) +{ + DBG_ASSERT( mbHasAfterEffect, "sd::CustomAnimationEffect::createAfterEffectNode(), this node has no after effect!" ); + + Reference< XMultiServiceFactory > xMsf( ::comphelper::getProcessServiceFactory() ); + + const char* pServiceName = maDimColor.hasValue() ? + "com.sun.star.animations.AnimateColor" : "com.sun.star.animations.AnimateSet"; + + Reference< XAnimate > xAnimate( xMsf->createInstance(OUString::createFromAscii(pServiceName) ), UNO_QUERY_THROW ); + + Any aTo; + OUString aAttributeName; + + if( maDimColor.hasValue() ) + { + aTo = maDimColor; + aAttributeName = OUString( RTL_CONSTASCII_USTRINGPARAM( "DimColor" ) ); + } + else + { + aTo = makeAny( (sal_Bool)sal_False ); + aAttributeName = OUString( RTL_CONSTASCII_USTRINGPARAM( "Visibility" ) ); + } + + Any aBegin; + if( !mbAfterEffectOnNextEffect ) // sameClick + { + Event aEvent; + + aEvent.Source <<= getNode(); + aEvent.Trigger = EventTrigger::END_EVENT; + aEvent.Repeat = 0; + + aBegin <<= aEvent; + } + else + { + aBegin <<= (double)0.0; + } + + xAnimate->setBegin( aBegin ); + xAnimate->setTo( aTo ); + xAnimate->setAttributeName( aAttributeName ); + + xAnimate->setDuration( makeAny( (double)0.001 ) ); + xAnimate->setFill( AnimationFill::HOLD ); + xAnimate->setTarget( maTarget ); + + return Reference< XAnimationNode >( xAnimate, UNO_QUERY_THROW ); +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setIterateType( sal_Int16 nIterateType ) +{ + if( mnIterateType != nIterateType ) try + { + // do we need to exchange the container node? + if( (mnIterateType == 0) || (nIterateType == 0) ) + { + sal_Int16 nTargetSubItem = mnTargetSubItem; + + Reference< XMultiServiceFactory > xMsf( ::comphelper::getProcessServiceFactory() ); + const char * pServiceName = + nIterateType ? "com.sun.star.animations.IterateContainer" : "com.sun.star.animations.ParallelTimeContainer"; + Reference< XTimeContainer > xNewContainer( + xMsf->createInstance( OUString::createFromAscii(pServiceName) ), UNO_QUERY_THROW ); + + Reference< XTimeContainer > xOldContainer( mxNode, UNO_QUERY_THROW ); + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW ); + xOldContainer->removeChild( xChildNode ); + xNewContainer->appendChild( xChildNode ); + } + + Reference< XAnimationNode > xNewNode( xNewContainer, UNO_QUERY_THROW ); + + xNewNode->setBegin( mxNode->getBegin() ); + xNewNode->setDuration( mxNode->getDuration() ); + xNewNode->setEnd( mxNode->getEnd() ); + xNewNode->setEndSync( mxNode->getEndSync() ); + xNewNode->setRepeatCount( mxNode->getRepeatCount() ); + xNewNode->setFill( mxNode->getFill() ); + xNewNode->setFillDefault( mxNode->getFillDefault() ); + xNewNode->setRestart( mxNode->getRestart() ); + xNewNode->setRestartDefault( mxNode->getRestartDefault() ); + xNewNode->setAcceleration( mxNode->getAcceleration() ); + xNewNode->setDecelerate( mxNode->getDecelerate() ); + xNewNode->setAutoReverse( mxNode->getAutoReverse() ); + xNewNode->setRepeatDuration( mxNode->getRepeatDuration() ); + xNewNode->setEndSync( mxNode->getEndSync() ); + xNewNode->setRepeatCount( mxNode->getRepeatCount() ); + xNewNode->setUserData( mxNode->getUserData() ); + + mxNode = xNewNode; + + Any aTarget; + if( nIterateType ) + { + Reference< XIterateContainer > xIter( mxNode, UNO_QUERY_THROW ); + xIter->setTarget(maTarget); + xIter->setSubItem( nTargetSubItem ); + } + else + { + aTarget = maTarget; + } + + Reference< XEnumerationAccess > xEA( mxNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xE( xEA->createEnumeration(), UNO_QUERY_THROW ); + while( xE->hasMoreElements() ) + { + Reference< XAnimate > xAnimate( xE->nextElement(), UNO_QUERY ); + if( xAnimate.is() ) + { + xAnimate->setTarget( aTarget ); + xAnimate->setSubItem( nTargetSubItem ); + } + } + } + + mnIterateType = nIterateType; + + // if we have an iteration container, we must set its type + if( mnIterateType ) + { + Reference< XIterateContainer > xIter( mxNode, UNO_QUERY_THROW ); + xIter->setIterateType( nIterateType ); + } + + checkForText(); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::CustomAnimationEffect::setIterateType(), Exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setIterateInterval( double fIterateInterval ) +{ + if( mfIterateInterval != fIterateInterval ) + { + Reference< XIterateContainer > xIter( mxNode, UNO_QUERY ); + + DBG_ASSERT( xIter.is(), "sd::CustomAnimationEffect::setIterateInterval(), not an iteration node" ); + if( xIter.is() ) + { + mfIterateInterval = fIterateInterval; + xIter->setIterateInterval( fIterateInterval ); + } + + calculateIterateDuration(); + } +} + +// -------------------------------------------------------------------- + +::rtl::OUString CustomAnimationEffect::getPath() const +{ + ::rtl::OUString aPath; + + if( mxNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimateMotion > xMotion( xEnumeration->nextElement(), UNO_QUERY ); + if( xMotion.is() ) + { + xMotion->getPath() >>= aPath; + break; + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::getPath(), exception cought!" ); + } + + return aPath; +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setPath( const ::rtl::OUString& rPath ) +{ + if( mxNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimateMotion > xMotion( xEnumeration->nextElement(), UNO_QUERY ); + if( xMotion.is() ) + { + + MainSequenceChangeGuard aGuard( mpEffectSequence ); + xMotion->setPath( Any( rPath ) ); + break; + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::setPath(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +Any CustomAnimationEffect::getProperty( sal_Int32 nNodeType, const OUString& rAttributeName, EValue eValue ) +{ + Any aProperty; + if( mxNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY ); + if( xEnumerationAccess.is() ) + { + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY ); + if( xEnumeration.is() ) + { + while( xEnumeration->hasMoreElements() && !aProperty.hasValue() ) + { + Reference< XAnimate > xAnimate( xEnumeration->nextElement(), UNO_QUERY ); + if( !xAnimate.is() ) + continue; + + if( xAnimate->getType() == nNodeType ) + { + if( xAnimate->getAttributeName() == rAttributeName ) + { + switch( eValue ) + { + case VALUE_FROM: aProperty = xAnimate->getFrom(); break; + case VALUE_TO: aProperty = xAnimate->getTo(); break; + case VALUE_BY: aProperty = xAnimate->getBy(); break; + case VALUE_FIRST: + case VALUE_LAST: + { + Sequence<Any> aValues( xAnimate->getValues() ); + if( aValues.hasElements() ) + aProperty = aValues[ eValue == VALUE_FIRST ? 0 : aValues.getLength() - 1 ]; + } + break; + } + } + } + } + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::getProperty(), exception cought!" ); + } + + return aProperty; +} + +// -------------------------------------------------------------------- + +bool CustomAnimationEffect::setProperty( sal_Int32 nNodeType, const OUString& rAttributeName, EValue eValue, const Any& rValue ) +{ + bool bChanged = false; + if( mxNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY ); + if( xEnumerationAccess.is() ) + { + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY ); + if( xEnumeration.is() ) + { + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimate > xAnimate( xEnumeration->nextElement(), UNO_QUERY ); + if( !xAnimate.is() ) + continue; + + if( xAnimate->getType() == nNodeType ) + { + if( xAnimate->getAttributeName() == rAttributeName ) + { + switch( eValue ) + { + case VALUE_FROM: + if( xAnimate->getFrom() != rValue ) + { + xAnimate->setFrom( rValue ); + bChanged = true; + } + break; + case VALUE_TO: + if( xAnimate->getTo() != rValue ) + { + xAnimate->setTo( rValue ); + bChanged = true; + } + break; + case VALUE_BY: + if( xAnimate->getTo() != rValue ) + { + xAnimate->setBy( rValue ); + bChanged = true; + } + break; + case VALUE_FIRST: + case VALUE_LAST: + { + Sequence<Any> aValues( xAnimate->getValues() ); + if( !aValues.hasElements() ) + aValues.realloc(1); + + sal_Int32 nIndex = eValue == VALUE_FIRST ? 0 : aValues.getLength() - 1; + + if( aValues[ nIndex ] != rValue ) + { + aValues[ nIndex ] = rValue; + xAnimate->setValues( aValues ); + bChanged = true; + } + } + } + } + } + } + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::setProperty(), exception cought!" ); + } + + return bChanged; +} + +// -------------------------------------------------------------------- + +static bool implIsColorAttribute( const OUString& rAttributeName ) +{ + return rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("FillColor") ) || + rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("LineColor") ) || + rAttributeName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CharColor") ); +} + +// -------------------------------------------------------------------- + +Any CustomAnimationEffect::getColor( sal_Int32 nIndex ) +{ + Any aColor; + if( mxNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY ); + if( xEnumerationAccess.is() ) + { + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY ); + if( xEnumeration.is() ) + { + while( xEnumeration->hasMoreElements() && !aColor.hasValue() ) + { + Reference< XAnimate > xAnimate( xEnumeration->nextElement(), UNO_QUERY ); + if( !xAnimate.is() ) + continue; + + switch( xAnimate->getType() ) + { + case AnimationNodeType::SET: + case AnimationNodeType::ANIMATE: + if( !implIsColorAttribute( xAnimate->getAttributeName() ) ) + break; + case AnimationNodeType::ANIMATECOLOR: + Sequence<Any> aValues( xAnimate->getValues() ); + if( aValues.hasElements() ) + { + if( aValues.getLength() > nIndex ) + aColor = aValues[nIndex]; + } + else if( nIndex == 0 ) + aColor = xAnimate->getFrom(); + else + aColor = xAnimate->getTo(); + } + } + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::getColor(), exception cought!" ); + } + + return aColor; +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setColor( sal_Int32 nIndex, const Any& rColor ) +{ + if( mxNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY ); + if( xEnumerationAccess.is() ) + { + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY ); + if( xEnumeration.is() ) + { + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimate > xAnimate( xEnumeration->nextElement(), UNO_QUERY ); + if( !xAnimate.is() ) + continue; + + switch( xAnimate->getType() ) + { + case AnimationNodeType::SET: + case AnimationNodeType::ANIMATE: + if( !implIsColorAttribute( xAnimate->getAttributeName() ) ) + break; + case AnimationNodeType::ANIMATECOLOR: + { + Sequence<Any> aValues( xAnimate->getValues() ); + if( aValues.hasElements() ) + { + if( aValues.getLength() > nIndex ) + { + aValues[nIndex] = rColor; + xAnimate->setValues( aValues ); + } + } + else if( (nIndex == 0) && xAnimate->getFrom().hasValue() ) + xAnimate->setFrom(rColor); + else if( (nIndex == 1) && xAnimate->getTo().hasValue() ) + xAnimate->setTo(rColor); + } + break; + + } + } + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::setColor(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +Any CustomAnimationEffect::getTransformationProperty( sal_Int32 nTransformType, EValue eValue ) +{ + Any aProperty; + if( mxNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY ); + if( xEnumerationAccess.is() ) + { + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY ); + if( xEnumeration.is() ) + { + while( xEnumeration->hasMoreElements() && !aProperty.hasValue() ) + { + Reference< XAnimateTransform > xTransform( xEnumeration->nextElement(), UNO_QUERY ); + if( !xTransform.is() ) + continue; + + if( xTransform->getTransformType() == nTransformType ) + { + switch( eValue ) + { + case VALUE_FROM: aProperty = xTransform->getFrom(); break; + case VALUE_TO: aProperty = xTransform->getTo(); break; + case VALUE_BY: aProperty = xTransform->getBy(); break; + case VALUE_FIRST: + case VALUE_LAST: + { + Sequence<Any> aValues( xTransform->getValues() ); + if( aValues.hasElements() ) + aProperty = aValues[ eValue == VALUE_FIRST ? 0 : aValues.getLength() - 1 ]; + } + break; + } + } + } + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::getTransformationProperty(), exception cought!" ); + } + + return aProperty; +} + +// -------------------------------------------------------------------- + +bool CustomAnimationEffect::setTransformationProperty( sal_Int32 nTransformType, EValue eValue, const Any& rValue ) +{ + bool bChanged = false; + if( mxNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( mxNode, UNO_QUERY ); + if( xEnumerationAccess.is() ) + { + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY ); + if( xEnumeration.is() ) + { + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimateTransform > xTransform( xEnumeration->nextElement(), UNO_QUERY ); + if( !xTransform.is() ) + continue; + + if( xTransform->getTransformType() == nTransformType ) + { + switch( eValue ) + { + case VALUE_FROM: + if( xTransform->getFrom() != rValue ) + { + xTransform->setFrom( rValue ); + bChanged = true; + } + break; + case VALUE_TO: + if( xTransform->getTo() != rValue ) + { + xTransform->setTo( rValue ); + bChanged = true; + } + break; + case VALUE_BY: + if( xTransform->getBy() != rValue ) + { + xTransform->setBy( rValue ); + bChanged = true; + } + break; + case VALUE_FIRST: + case VALUE_LAST: + { + Sequence<Any> aValues( xTransform->getValues() ); + if( !aValues.hasElements() ) + aValues.realloc(1); + + sal_Int32 nIndex = eValue == VALUE_FIRST ? 0 : aValues.getLength() - 1; + if( aValues[nIndex] != rValue ) + { + aValues[nIndex] = rValue; + xTransform->setValues( aValues ); + bChanged = true; + } + } + } + } + } + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::setTransformationProperty(), exception cought!" ); + } + + return bChanged; +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::createAudio( const ::com::sun::star::uno::Any& rSource, double fVolume /* = 1.0 */ ) +{ + DBG_ASSERT( !mxAudio.is(), "sd::CustomAnimationEffect::createAudio(), node already has an audio!" ); + + if( !mxAudio.is() ) try + { + Reference< XMultiServiceFactory > xMsf( ::comphelper::getProcessServiceFactory() ); + Reference< XAudio > xAudio( xMsf->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.Audio") ) ), UNO_QUERY_THROW ); + xAudio->setSource( rSource ); + xAudio->setVolume( fVolume ); + setAudio( xAudio ); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::createAudio(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +static Reference< XCommand > findCommandNode( const Reference< XAnimationNode >& xRootNode ) +{ + Reference< XCommand > xCommand; + + if( xRootNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( xRootNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( !xCommand.is() && xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xNode( xEnumeration->nextElement(), UNO_QUERY ); + if( xNode.is() && (xNode->getType() == AnimationNodeType::COMMAND) ) + xCommand.set( xNode, UNO_QUERY_THROW ); + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::findCommandNode(), exception caught!" ); + } + + return xCommand; +} + +void CustomAnimationEffect::removeAudio() +{ + try + { + Reference< XAnimationNode > xChild; + + if( mxAudio.is() ) + { + xChild.set( mxAudio, UNO_QUERY ); + mxAudio.clear(); + } + else if( mnCommand == EffectCommands::STOPAUDIO ) + { + xChild.set( findCommandNode( mxNode ), UNO_QUERY ); + mnCommand = 0; + } + + if( xChild.is() ) + { + Reference< XTimeContainer > xContainer( mxNode, UNO_QUERY ); + if( xContainer.is() ) + xContainer->removeChild( xChild ); + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::removeAudio(), exception caught!" ); + } + +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setAudio( const Reference< ::com::sun::star::animations::XAudio >& xAudio ) +{ + if( mxAudio != xAudio ) try + { + removeAudio(); + mxAudio = xAudio; + Reference< XTimeContainer > xContainer( mxNode, UNO_QUERY ); + Reference< XAnimationNode > xChild( mxAudio, UNO_QUERY ); + if( xContainer.is() && xChild.is() ) + xContainer->appendChild( xChild ); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::setAudio(), exception caught!" ); + } +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::setStopAudio() +{ + if( mnCommand != EffectCommands::STOPAUDIO ) try + { + if( mxAudio.is() ) + removeAudio(); + + Reference< XMultiServiceFactory > xMsf( ::comphelper::getProcessServiceFactory() ); + Reference< XCommand > xCommand( xMsf->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.Command") ) ), UNO_QUERY_THROW ); + + xCommand->setCommand( EffectCommands::STOPAUDIO ); + + Reference< XTimeContainer > xContainer( mxNode, UNO_QUERY_THROW ); + Reference< XAnimationNode > xChild( xCommand, UNO_QUERY_THROW ); + xContainer->appendChild( xChild ); + + mnCommand = EffectCommands::STOPAUDIO; + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::CustomAnimationEffect::setStopAudio(), exception caught!" ); + } +} + +// -------------------------------------------------------------------- + +bool CustomAnimationEffect::getStopAudio() const +{ + return mnCommand == EffectCommands::STOPAUDIO; +} + +// -------------------------------------------------------------------- + +SdrPathObj* CustomAnimationEffect::createSdrPathObjFromPath() +{ + SdrPathObj * pPathObj = new SdrPathObj( OBJ_PATHLINE ); + updateSdrPathObjFromPath( *pPathObj ); + return pPathObj; +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::updateSdrPathObjFromPath( SdrPathObj& rPathObj ) +{ + ::basegfx::B2DPolyPolygon xPolyPoly; + if( ::basegfx::tools::importFromSvgD( xPolyPoly, getPath() ) ) + { + SdrObject* pObj = GetSdrObjectFromXShape( getTargetShape() ); + if( pObj ) + { + SdrPage* pPage = pObj->GetPage(); + if( pPage ) + { + const Size aPageSize( pPage->GetSize() ); + xPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix((double)aPageSize.Width(), (double)aPageSize.Height())); + } + + const Rectangle aBoundRect( pObj->GetCurrentBoundRect() ); + const Point aCenter( aBoundRect.Center() ); + xPolyPoly.transform(basegfx::tools::createTranslateB2DHomMatrix(aCenter.X(), aCenter.Y())); + } + } + + rPathObj.SetPathPoly( xPolyPoly ); +} + +// -------------------------------------------------------------------- + +void CustomAnimationEffect::updatePathFromSdrPathObj( const SdrPathObj& rPathObj ) +{ + ::basegfx::B2DPolyPolygon xPolyPoly( rPathObj.GetPathPoly() ); + + SdrObject* pObj = GetSdrObjectFromXShape( getTargetShape() ); + if( pObj ) + { + const Rectangle aBoundRect( pObj->GetCurrentBoundRect() ); + const Point aCenter( aBoundRect.Center() ); + + xPolyPoly.transform(basegfx::tools::createTranslateB2DHomMatrix(-aCenter.X(), -aCenter.Y())); + + SdrPage* pPage = pObj->GetPage(); + if( pPage ) + { + const Size aPageSize( pPage->GetSize() ); + xPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix( + 1.0 / (double)aPageSize.Width(), 1.0 / (double)aPageSize.Height())); + } + } + + setPath( ::basegfx::tools::exportToSvgD( xPolyPoly ) ); +} + +// ==================================================================== + +EffectSequenceHelper::EffectSequenceHelper() +: mnSequenceType( EffectNodeType::DEFAULT ) +{ +} + +// -------------------------------------------------------------------- + +EffectSequenceHelper::EffectSequenceHelper( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XTimeContainer >& xSequenceRoot ) +: mxSequenceRoot( xSequenceRoot ), mnSequenceType( EffectNodeType::DEFAULT ) +{ + Reference< XAnimationNode > xNode( mxSequenceRoot, UNO_QUERY_THROW ); + create( xNode ); +} + +// -------------------------------------------------------------------- + +EffectSequenceHelper::~EffectSequenceHelper() +{ + reset(); +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::reset() +{ + EffectSequence::iterator aIter( maEffects.begin() ); + EffectSequence::iterator aEnd( maEffects.end() ); + if( aIter != aEnd ) + { + CustomAnimationEffectPtr pEffect = (*aIter++); + pEffect->setEffectSequence(0); + } + maEffects.clear(); +} + +Reference< XAnimationNode > EffectSequenceHelper::getRootNode() +{ + Reference< XAnimationNode > xRoot( mxSequenceRoot, UNO_QUERY ); + return xRoot; +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::append( const CustomAnimationEffectPtr& pEffect ) +{ + pEffect->setEffectSequence( this ); + maEffects.push_back(pEffect); + rebuild(); +} + +// -------------------------------------------------------------------- + +CustomAnimationEffectPtr EffectSequenceHelper::append( const CustomAnimationPresetPtr& pPreset, const Any& rTarget, double fDuration /* = -1.0 */ ) +{ + CustomAnimationEffectPtr pEffect; + + if( pPreset.get() ) + { + OUString strEmpty; + Reference< XAnimationNode > xNode( pPreset->create( strEmpty ) ); + if( xNode.is() ) + { + // first, filter all only ui relevant user data + std::vector< NamedValue > aNewUserData; + Sequence< NamedValue > aUserData( xNode->getUserData() ); + sal_Int32 nLength = aUserData.getLength(); + const NamedValue* p = aUserData.getConstArray(); + bool bFilter = false; + + while( nLength-- ) + { + if( !p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "text-only" ) ) && + !p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-property" ) ) ) + { + aNewUserData.push_back( *p ); + bFilter = true; + } + p++; + } + + if( bFilter ) + { + aUserData = ::comphelper::containerToSequence< NamedValue, std::vector< NamedValue > >( aNewUserData ); + xNode->setUserData( aUserData ); + } + + // check target, maybe we need to force it to text + Any aTarget( rTarget ); + sal_Int16 nSubItem = ShapeAnimationSubType::AS_WHOLE; + + if( aTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + { + nSubItem = ShapeAnimationSubType::ONLY_TEXT; + } + else if( pPreset->isTextOnly() ) + { + Reference< XShape > xShape; + aTarget >>= xShape; + if( xShape.is() ) + { + // thats bad, we target a shape here but the effect is only for text + // so change subitem + nSubItem = ShapeAnimationSubType::ONLY_TEXT; + } + } + + // now create effect from preset + pEffect.reset( new CustomAnimationEffect( xNode ) ); + pEffect->setEffectSequence( this ); + pEffect->setTarget( aTarget ); + pEffect->setTargetSubItem( nSubItem ); + if( fDuration != -1.0 ) + pEffect->setDuration( fDuration ); + + maEffects.push_back(pEffect); + + rebuild(); + } + } + + DBG_ASSERT( pEffect.get(), "sd::EffectSequenceHelper::append(), failed!" ); + return pEffect; +} + +// -------------------------------------------------------------------- + +CustomAnimationEffectPtr EffectSequenceHelper::append( const SdrPathObj& rPathObj, const Any& rTarget, double fDuration /* = -1.0 */ ) +{ + CustomAnimationEffectPtr pEffect; + + if( fDuration <= 0.0 ) + fDuration = 2.0; + + try + { + Reference< XTimeContainer > xEffectContainer( createParallelTimeContainer() ); + const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.animations.AnimateMotion" ) ); + Reference< XAnimationNode > xAnimateMotion( ::comphelper::getProcessServiceFactory()->createInstance(aServiceName), UNO_QUERY_THROW ); + + xAnimateMotion->setDuration( Any( fDuration ) ); + xAnimateMotion->setFill( AnimationFill::HOLD ); + xEffectContainer->appendChild( xAnimateMotion ); + + sal_Int16 nSubItem = ShapeAnimationSubType::AS_WHOLE; + + if( rTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + nSubItem = ShapeAnimationSubType::ONLY_TEXT; + + Reference< XAnimationNode > xEffectNode( xEffectContainer, UNO_QUERY_THROW ); + pEffect.reset( new CustomAnimationEffect( xEffectNode ) ); + pEffect->setEffectSequence( this ); + pEffect->setTarget( rTarget ); + pEffect->setTargetSubItem( nSubItem ); + pEffect->setNodeType( ::com::sun::star::presentation::EffectNodeType::ON_CLICK ); + pEffect->setPresetClass( ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH ); + pEffect->setAcceleration( 0.5 ); + pEffect->setDecelerate( 0.5 ); + pEffect->setFill( AnimationFill::HOLD ); + pEffect->setBegin( 0.0 ); + pEffect->updatePathFromSdrPathObj( rPathObj ); + if( fDuration != -1.0 ) + pEffect->setDuration( fDuration ); + + maEffects.push_back(pEffect); + + rebuild(); + } + catch( Exception& ) + { + DBG_ERROR( "sd::EffectSequenceHelper::append(), exception cought!" ); + } + + return pEffect; +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::replace( const CustomAnimationEffectPtr& pEffect, const CustomAnimationPresetPtr& pPreset, const OUString& rPresetSubType, double fDuration /* = -1.0 */ ) +{ + if( pEffect.get() && pPreset.get() ) try + { + Reference< XAnimationNode > xNewNode( pPreset->create( rPresetSubType ) ); + if( xNewNode.is() ) + { + pEffect->replaceNode( xNewNode ); + if( fDuration != -1.0 ) + pEffect->setDuration( fDuration ); + } + + rebuild(); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::EffectSequenceHelper::replace(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::replace( const CustomAnimationEffectPtr& pEffect, const CustomAnimationPresetPtr& pPreset, double fDuration /* = -1.0 */ ) +{ + OUString strEmpty; + replace( pEffect, pPreset, strEmpty, fDuration ); +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::remove( const CustomAnimationEffectPtr& pEffect ) +{ + if( pEffect.get() ) + { + pEffect->setEffectSequence( 0 ); + maEffects.remove( pEffect ); + } + + rebuild(); +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::rebuild() +{ + implRebuild(); +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::implRebuild() +{ + try + { + // first we delete all time containers on the first two levels + Reference< XEnumerationAccess > xEnumerationAccess( mxSequenceRoot, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW ); + Reference< XTimeContainer > xChildContainer( xChildNode, UNO_QUERY_THROW ); + + Reference< XEnumerationAccess > xChildEnumerationAccess( xChildNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xChildEnumeration( xChildEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( xChildEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xNode( xChildEnumeration->nextElement(), UNO_QUERY_THROW ); + xChildContainer->removeChild( xNode ); + } + + mxSequenceRoot->removeChild( xChildNode ); + } + + // second, rebuild main sequence + EffectSequence::iterator aIter( maEffects.begin() ); + EffectSequence::iterator aEnd( maEffects.end() ); + if( aIter != aEnd ) + { + AfterEffectNodeList aAfterEffects; + + CustomAnimationEffectPtr pEffect = (*aIter++); + + bool bFirst = true; + do + { + // create a par container for the next click node and all following with and after effects + Reference< XTimeContainer > xOnClickContainer( createParallelTimeContainer() ); + + Event aEvent; + if( mxEventSource.is() ) + { + aEvent.Source <<= mxEventSource; + aEvent.Trigger = EventTrigger::ON_CLICK; + } + else + { + aEvent.Trigger = EventTrigger::ON_NEXT; + } + aEvent.Repeat = 0; + + Any aBegin( makeAny( aEvent ) ); + if( bFirst ) + { + // if the first node is not a click action, this click container + // must not have INDEFINITE begin but start at 0s + bFirst = false; + if( pEffect->getNodeType() != EffectNodeType::ON_CLICK ) + aBegin <<= (double)0.0; + } + + xOnClickContainer->setBegin( aBegin ); + + Reference< XAnimationNode > xOnClickContainerNode( xOnClickContainer, UNO_QUERY_THROW ); + mxSequenceRoot->appendChild( xOnClickContainerNode ); + + double fBegin = 0.0; + + do + { + // create a par container for the current click or after effect node and all following with effects + Reference< XTimeContainer > xWithContainer( createParallelTimeContainer() ); + Reference< XAnimationNode > xWithContainerNode( xWithContainer, UNO_QUERY_THROW ); + xWithContainer->setBegin( makeAny( fBegin ) ); + xOnClickContainer->appendChild( xWithContainerNode ); + + double fDuration = 0.0; + do + { + Reference< XAnimationNode > xEffectNode( pEffect->getNode() ); + xWithContainer->appendChild( xEffectNode ); + + if( pEffect->hasAfterEffect() ) + { + Reference< XAnimationNode > xAfterEffect( pEffect->createAfterEffectNode() ); + AfterEffectNode a( xAfterEffect, xEffectNode, pEffect->IsAfterEffectOnNext() ); + aAfterEffects.push_back( a ); + } + + double fTemp = pEffect->getBegin() + pEffect->getAbsoluteDuration(); + if( fTemp > fDuration ) + fDuration = fTemp; + + if( aIter != aEnd ) + pEffect = (*aIter++); + else + pEffect.reset(); + } + while( pEffect.get() && (pEffect->getNodeType() == EffectNodeType::WITH_PREVIOUS) ); + + fBegin += fDuration; + } + while( pEffect.get() && (pEffect->getNodeType() != EffectNodeType::ON_CLICK) ); + } + while( pEffect.get() ); + + // process after effect nodes + std::for_each( aAfterEffects.begin(), aAfterEffects.end(), stl_process_after_effect_node_func ); + + updateTextGroups(); + + // reset duration, might have been altered (see below) + mxSequenceRoot->setDuration( Any() ); + } + else + { + // empty sequence, set duration to 0.0 explicitely + // (otherwise, this sequence will never end) + mxSequenceRoot->setDuration( makeAny((double)0.0) ); + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::EffectSequenceHelper::rebuild(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +Reference< XTimeContainer > EffectSequenceHelper::createParallelTimeContainer() const +{ + const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.animations.ParallelTimeContainer" ) ); + return Reference< XTimeContainer >( ::comphelper::getProcessServiceFactory()->createInstance(aServiceName), UNO_QUERY ); +} + +// -------------------------------------------------------------------- + +stl_CustomAnimationEffect_search_node_predict::stl_CustomAnimationEffect_search_node_predict( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xSearchNode ) +: mxSearchNode( xSearchNode ) +{ +} + +// -------------------------------------------------------------------- + +bool stl_CustomAnimationEffect_search_node_predict::operator()( CustomAnimationEffectPtr pEffect ) const +{ + return pEffect->getNode() == mxSearchNode; +} + +// -------------------------------------------------------------------- + +static bool implFindNextContainer( Reference< XTimeContainer >& xParent, Reference< XTimeContainer >& xCurrent, Reference< XTimeContainer >& xNext ) + throw(Exception) +{ + Reference< XEnumerationAccess > xEnumerationAccess( xParent, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration() ); + if( xEnumeration.is() ) + { + Reference< XInterface > x; + while( xEnumeration->hasMoreElements() && !xNext.is() ) + { + if( (xEnumeration->nextElement() >>= x) && (x == xCurrent) ) + { + if( xEnumeration->hasMoreElements() ) + xEnumeration->nextElement() >>= xNext; + } + } + } + return xNext.is(); +} + +// -------------------------------------------------------------------- + +void stl_process_after_effect_node_func(AfterEffectNode& rNode) +{ + try + { + if( rNode.mxNode.is() && rNode.mxMaster.is() ) + { + // set master node + Reference< XAnimationNode > xMasterNode( rNode.mxMaster, UNO_QUERY_THROW ); + Sequence< NamedValue > aUserData( rNode.mxNode->getUserData() ); + sal_Int32 nSize = aUserData.getLength(); + aUserData.realloc(nSize+1); + aUserData[nSize].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "master-element" ) ); + aUserData[nSize].Value <<= xMasterNode; + rNode.mxNode->setUserData( aUserData ); + + // insert after effect node into timeline + Reference< XTimeContainer > xContainer( rNode.mxMaster->getParent(), UNO_QUERY_THROW ); + + if( !rNode.mbOnNextEffect ) // sameClick + { + // insert the aftereffect after its effect is animated + xContainer->insertAfter( rNode.mxNode, rNode.mxMaster ); + } + else // nextClick + { + Reference< XMultiServiceFactory > xMsf( ::comphelper::getProcessServiceFactory() ); + // insert the aftereffect in the next group + + Reference< XTimeContainer > xClickContainer( xContainer->getParent(), UNO_QUERY_THROW ); + Reference< XTimeContainer > xSequenceContainer( xClickContainer->getParent(), UNO_QUERY_THROW ); + + Reference< XTimeContainer > xNextContainer; + + // first try if we have an after effect container + if( !implFindNextContainer( xClickContainer, xContainer, xNextContainer ) ) + { + Reference< XTimeContainer > xNextClickContainer; + // if not, try to find the next click effect container + if( implFindNextContainer( xSequenceContainer, xClickContainer, xNextClickContainer ) ) + { + Reference< XEnumerationAccess > xEnumerationAccess( xNextClickContainer, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + if( xEnumeration->hasMoreElements() ) + { + // the next container is the first child container + xEnumeration->nextElement() >>= xNextContainer; + } + else + { + // this does not yet have a child container, create one + const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.ParallelTimeContainer") ); + xNextContainer = Reference< XTimeContainer >::query( xMsf->createInstance(aServiceName) ); + + if( xNextContainer.is() ) + { + Reference< XAnimationNode > xNode( xNextContainer, UNO_QUERY_THROW ); + xNode->setBegin( makeAny( (double)0.0 ) ); + xNextClickContainer->appendChild( xNode ); + } + } + DBG_ASSERT( xNextContainer.is(), "ppt::stl_process_after_effect_node_func::operator(), could not find/create container!" ); + } + } + + // if we don't have a next container, we add one to the sequence container + if( !xNextContainer.is() ) + { + const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.ParallelTimeContainer") ); + Reference< XTimeContainer > xNewClickContainer( xMsf->createInstance(aServiceName), UNO_QUERY_THROW ); + + Reference< XAnimationNode > xNewClickNode( xNewClickContainer, UNO_QUERY_THROW ); + + Event aEvent; + aEvent.Trigger = EventTrigger::ON_NEXT; + aEvent.Repeat = 0; + xNewClickNode->setBegin( makeAny( aEvent ) ); + + Reference< XAnimationNode > xRefNode( xClickContainer, UNO_QUERY_THROW ); + xSequenceContainer->insertAfter( xNewClickNode, xRefNode ); + + xNextContainer = Reference< XTimeContainer >::query( xMsf->createInstance(aServiceName) ); + + DBG_ASSERT( xNextContainer.is(), "ppt::stl_process_after_effect_node_func::operator(), could not create container!" ); + if( xNextContainer.is() ) + { + Reference< XAnimationNode > xNode( xNextContainer, UNO_QUERY_THROW ); + xNode->setBegin( makeAny( (double)0.0 ) ); + xNewClickContainer->appendChild( xNode ); + } + } + + if( xNextContainer.is() ) + { + // find begin time of first element + Reference< XEnumerationAccess > xEnumerationAccess( xNextContainer, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + if( xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChild; + // the next container is the first child container + xEnumeration->nextElement() >>= xChild; + if( xChild.is() ) + { + Any aBegin( xChild->getBegin() ); + double fBegin = 0.0; + if( (aBegin >>= fBegin) && (fBegin >= 0.0)) + rNode.mxNode->setBegin( aBegin ); + } + } + + xNextContainer->appendChild( rNode.mxNode ); + } + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "ppt::stl_process_after_effect_node_func::operator(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +EffectSequence::iterator EffectSequenceHelper::find( const CustomAnimationEffectPtr& pEffect ) +{ + return std::find( maEffects.begin(), maEffects.end(), pEffect ); +} + +// -------------------------------------------------------------------- + +CustomAnimationEffectPtr EffectSequenceHelper::findEffect( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) const +{ + CustomAnimationEffectPtr pEffect; + + EffectSequence::const_iterator aIter( maEffects.begin() ); + for( ; aIter != maEffects.end(); aIter++ ) + { + if( (*aIter)->getNode() == xNode ) + { + pEffect = (*aIter); + break; + } + } + + return pEffect; +} + +// -------------------------------------------------------------------- + +sal_Int32 EffectSequenceHelper::getOffsetFromEffect( const CustomAnimationEffectPtr& xEffect ) const +{ + sal_Int32 nOffset = 0; + + EffectSequence::const_iterator aIter( maEffects.begin() ); + for( ; aIter != maEffects.end(); aIter++, nOffset++ ) + { + if( (*aIter) == xEffect ) + return nOffset; + } + + return -1; +} + +// -------------------------------------------------------------------- + +CustomAnimationEffectPtr EffectSequenceHelper::getEffectFromOffset( sal_Int32 nOffset ) const +{ + EffectSequence::const_iterator aIter( maEffects.begin() ); + while( nOffset-- && aIter != maEffects.end() ) + aIter++; + + CustomAnimationEffectPtr pEffect; + if( aIter != maEffects.end() ) + pEffect = (*aIter); + + return pEffect; +} + +// -------------------------------------------------------------------- + +bool EffectSequenceHelper::disposeShape( const Reference< XShape >& xShape ) +{ + bool bChanges = false; + + EffectSequence::iterator aIter( maEffects.begin() ); + while( aIter != maEffects.end() ) + { + if( (*aIter)->getTargetShape() == xShape ) + { + (*aIter)->setEffectSequence( 0 ); + bChanges = true; + aIter = maEffects.erase( aIter ); + } + else + { + aIter++; + } + } + + return bChanges; +} + +// -------------------------------------------------------------------- + +bool EffectSequenceHelper::hasEffect( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape ) +{ + EffectSequence::iterator aIter( maEffects.begin() ); + while( aIter != maEffects.end() ) + { + if( (*aIter)->getTargetShape() == xShape ) + return true; + aIter++; + } + + return false; +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::insertTextRange( const com::sun::star::uno::Any& aTarget ) +{ + bool bChanges = false; + + ParagraphTarget aParaTarget; + if( !(aTarget >>= aParaTarget ) ) + return; + + EffectSequence::iterator aIter( maEffects.begin() ); + while( aIter != maEffects.end() ) + { + if( (*aIter)->getTargetShape() == aParaTarget.Shape ) + bChanges |= (*aIter)->checkForText(); + aIter++; + } + + if( bChanges ) + rebuild(); +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::disposeTextRange( const com::sun::star::uno::Any& aTarget ) +{ + ParagraphTarget aParaTarget; + if( !(aTarget >>= aParaTarget ) ) + return; + + bool bChanges = false; + bool bErased = false; + + EffectSequence::iterator aIter( maEffects.begin() ); + while( aIter != maEffects.end() ) + { + Any aIterTarget( (*aIter)->getTarget() ); + if( aIterTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + { + ParagraphTarget aIterParaTarget; + if( (aIterTarget >>= aIterParaTarget) && (aIterParaTarget.Shape == aParaTarget.Shape) ) + { + if( aIterParaTarget.Paragraph == aParaTarget.Paragraph ) + { + // delete this effect if it targets the disposed paragraph directly + (*aIter)->setEffectSequence( 0 ); + aIter = maEffects.erase( aIter ); + bChanges = true; + bErased = true; + } + else + { + if( aIterParaTarget.Paragraph > aParaTarget.Paragraph ) + { + // shift all paragraphs after disposed paragraph + aIterParaTarget.Paragraph--; + (*aIter)->setTarget( makeAny( aIterParaTarget ) ); + } + } + } + } + else if( (*aIter)->getTargetShape() == aParaTarget.Shape ) + { + bChanges |= (*aIter)->checkForText(); + } + + if( bErased ) + bErased = false; + else + aIter++; + } + + if( bChanges ) + rebuild(); +} + +// -------------------------------------------------------------------- + +CustomAnimationTextGroup::CustomAnimationTextGroup( const Reference< XShape >& rTarget, sal_Int32 nGroupId ) +: maTarget( rTarget ), + mnGroupId( nGroupId ) +{ + reset(); +} + +// -------------------------------------------------------------------- + +void CustomAnimationTextGroup::reset() +{ + mnTextGrouping = -1; + mbAnimateForm = false; + mbTextReverse = false; + mfGroupingAuto = -1.0; + mnLastPara = -1; // used to check for TextReverse + + int i = 5; + while( i-- ) mnDepthFlags[i] = 0; + + maEffects.clear(); +} + +// -------------------------------------------------------------------- + +void CustomAnimationTextGroup::addEffect( CustomAnimationEffectPtr& pEffect ) +{ + maEffects.push_back( pEffect ); + + Any aTarget( pEffect->getTarget() ); + if( aTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + { + // now look at the paragraph + ParagraphTarget aParaTarget; + aTarget >>= aParaTarget; + + if( mnLastPara != -1 ) + mbTextReverse = mnLastPara > aParaTarget.Paragraph; + + mnLastPara = aParaTarget.Paragraph; + + const sal_Int32 nParaDepth = pEffect->getParaDepth(); + + // only look at the first 5 levels + if( nParaDepth < 5 ) + { + // our first paragraph with this level? + if( mnDepthFlags[nParaDepth] == 0 ) + { + // so set it to the first found + mnDepthFlags[nParaDepth] = (sal_Int8)pEffect->getNodeType(); + } + else if( mnDepthFlags[nParaDepth] != pEffect->getNodeType() ) + { + mnDepthFlags[nParaDepth] = -1; + } + + if( pEffect->getNodeType() == EffectNodeType::AFTER_PREVIOUS ) + mfGroupingAuto = pEffect->getBegin(); + + mnTextGrouping = 0; + while( (mnTextGrouping < 5) && (mnDepthFlags[mnTextGrouping] > 0) ) + mnTextGrouping++; + } + } + else + { + // if we have an effect with the shape as a target, we animate the background + mbAnimateForm = pEffect->getTargetSubItem() != ShapeAnimationSubType::ONLY_TEXT; + } +} + +// -------------------------------------------------------------------- + +class TextGroupMapImpl : public std::map< sal_Int32, CustomAnimationTextGroup* > +{ +public: + CustomAnimationTextGroup* findGroup( sal_Int32 nGroupId ); +}; + +// -------------------------------------------------------------------- + +CustomAnimationTextGroupPtr EffectSequenceHelper::findGroup( sal_Int32 nGroupId ) +{ + CustomAnimationTextGroupPtr aPtr; + + CustomAnimationTextGroupMap::iterator aIter( maGroupMap.find( nGroupId ) ); + if( aIter != maGroupMap.end() ) + aPtr = (*aIter).second; + + return aPtr; +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::updateTextGroups() +{ + maGroupMap.clear(); + + // first create all the groups + EffectSequence::iterator aIter( maEffects.begin() ); + const EffectSequence::iterator aEnd( maEffects.end() ); + while( aIter != aEnd ) + { + CustomAnimationEffectPtr pEffect( (*aIter++) ); + + const sal_Int32 nGroupId = pEffect->getGroupId(); + + if( nGroupId == -1 ) + continue; // trivial case, no group + + CustomAnimationTextGroupPtr pGroup = findGroup( nGroupId ); + if( !pGroup.get() ) + { + pGroup.reset( new CustomAnimationTextGroup( pEffect->getTargetShape(), nGroupId ) ); + maGroupMap[nGroupId] = pGroup; + } + + pGroup->addEffect( pEffect ); + } +} + +// -------------------------------------------------------------------- + +CustomAnimationTextGroupPtr EffectSequenceHelper::createTextGroup( CustomAnimationEffectPtr pEffect, sal_Int32 nTextGrouping, double fTextGroupingAuto, sal_Bool bAnimateForm, sal_Bool bTextReverse ) +{ + // first finde a free group-id + sal_Int32 nGroupId = 0; + + CustomAnimationTextGroupMap::iterator aIter( maGroupMap.begin() ); + const CustomAnimationTextGroupMap::iterator aEnd( maGroupMap.end() ); + while( aIter != aEnd ) + { + if( (*aIter).first == nGroupId ) + { + nGroupId++; + aIter = maGroupMap.begin(); + } + else + { + aIter++; + } + } + + Reference< XShape > xTarget( pEffect->getTargetShape() ); + + CustomAnimationTextGroupPtr pTextGroup( new CustomAnimationTextGroup( xTarget, nGroupId ) ); + maGroupMap[nGroupId] = pTextGroup; + + bool bUsed = false; + + // do we need to target the shape? + if( (nTextGrouping == 0) || bAnimateForm ) + { + sal_Int16 nSubItem; + if( nTextGrouping == 0) + nSubItem = bAnimateForm ? ShapeAnimationSubType::AS_WHOLE : ShapeAnimationSubType::ONLY_TEXT; + else + nSubItem = ShapeAnimationSubType::ONLY_BACKGROUND; + + pEffect->setTarget( makeAny( xTarget ) ); + pEffect->setTargetSubItem( nSubItem ); + pEffect->setEffectSequence( this ); + pEffect->setGroupId( nGroupId ); + + pTextGroup->addEffect( pEffect ); + bUsed = true; + } + + pTextGroup->mnTextGrouping = nTextGrouping; + pTextGroup->mfGroupingAuto = fTextGroupingAuto; + pTextGroup->mbTextReverse = bTextReverse; + + // now add an effect for each paragraph + createTextGroupParagraphEffects( pTextGroup, pEffect, bUsed ); + + notify_listeners(); + + return pTextGroup; +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::createTextGroupParagraphEffects( CustomAnimationTextGroupPtr pTextGroup, CustomAnimationEffectPtr pEffect, bool bUsed ) +{ + Reference< XShape > xTarget( pTextGroup->maTarget ); + + sal_Int32 nTextGrouping = pTextGroup->mnTextGrouping; + double fTextGroupingAuto = pTextGroup->mfGroupingAuto; + sal_Bool bTextReverse = pTextGroup->mbTextReverse; + + // now add an effect for each paragraph + if( nTextGrouping >= 0 ) try + { + EffectSequence::iterator aInsertIter( find( pEffect ) ); + + const OUString strNumberingLevel( RTL_CONSTASCII_USTRINGPARAM("NumberingLevel") ); + Reference< XEnumerationAccess > xText( xTarget, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xText->createEnumeration(), UNO_QUERY_THROW ); + + std::list< sal_Int16 > aParaList; + sal_Int16 nPara; + + // fill the list with all valid paragraphs + for( nPara = 0; xEnumeration->hasMoreElements(); nPara++ ) + { + Reference< XTextRange > xRange( xEnumeration->nextElement(), UNO_QUERY ); + if( xRange.is() && xRange->getString().getLength() ) + { + if( bTextReverse ) // sort them + aParaList.push_front( nPara ); + else + aParaList.push_back( nPara ); + } + } + + ParagraphTarget aTarget; + aTarget.Shape = xTarget; + + std::list< sal_Int16 >::iterator aIter( aParaList.begin() ); + std::list< sal_Int16 >::iterator aEnd( aParaList.end() ); + while( aIter != aEnd ) + { + aTarget.Paragraph = (*aIter++); + + CustomAnimationEffectPtr pNewEffect; + if( bUsed ) + { + // clone a new effect from first effect + pNewEffect = pEffect->clone(); + ++aInsertIter; + aInsertIter = maEffects.insert( aInsertIter, pNewEffect ); + } + else + { + // reuse first effect if its not yet used + pNewEffect = pEffect; + bUsed = true; + aInsertIter = find( pNewEffect ); + } + + // set target and group-id + pNewEffect->setTarget( makeAny( aTarget ) ); + pNewEffect->setTargetSubItem( ShapeAnimationSubType::ONLY_TEXT ); + pNewEffect->setGroupId( pTextGroup->mnGroupId ); + pNewEffect->setEffectSequence( this ); + + // set correct node type + if( pNewEffect->getParaDepth() < nTextGrouping ) + { + if( fTextGroupingAuto == -1.0 ) + { + pNewEffect->setNodeType( EffectNodeType::ON_CLICK ); + pNewEffect->setBegin( 0.0 ); + } + else + { + pNewEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS ); + pNewEffect->setBegin( fTextGroupingAuto ); + } + } + else + { + pNewEffect->setNodeType( EffectNodeType::WITH_PREVIOUS ); + pNewEffect->setBegin( 0.0 ); + } + + pTextGroup->addEffect( pNewEffect ); + } + notify_listeners(); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::EffectSequenceHelper::createTextGroup(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::setTextGrouping( CustomAnimationTextGroupPtr pTextGroup, sal_Int32 nTextGrouping ) +{ + if( pTextGroup->mnTextGrouping == nTextGrouping ) + { + // first case, trivial case, do nothing + } + else if( (pTextGroup->mnTextGrouping == -1) && (nTextGrouping >= 0) ) + { + // second case, we need to add new effects for each paragraph + + CustomAnimationEffectPtr pEffect( pTextGroup->maEffects.front() ); + + pTextGroup->mnTextGrouping = nTextGrouping; + createTextGroupParagraphEffects( pTextGroup, pEffect, true ); + notify_listeners(); + } + else if( (pTextGroup->mnTextGrouping >= 0) && (nTextGrouping == -1 ) ) + { + // third case, we need to remove effects for each paragraph + + EffectSequence aEffects( pTextGroup->maEffects ); + pTextGroup->reset(); + + EffectSequence::iterator aIter( aEffects.begin() ); + const EffectSequence::iterator aEnd( aEffects.end() ); + while( aIter != aEnd ) + { + CustomAnimationEffectPtr pEffect( (*aIter++) ); + + if( pEffect->getTarget().getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + remove( pEffect ); + else + pTextGroup->addEffect( pEffect ); + } + notify_listeners(); + } + else + { + // fourth case, we need to change the node types for the text nodes + double fTextGroupingAuto = pTextGroup->mfGroupingAuto; + + EffectSequence aEffects( pTextGroup->maEffects ); + pTextGroup->reset(); + + EffectSequence::iterator aIter( aEffects.begin() ); + const EffectSequence::iterator aEnd( aEffects.end() ); + while( aIter != aEnd ) + { + CustomAnimationEffectPtr pEffect( (*aIter++) ); + + if( pEffect->getTarget().getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + { + // set correct node type + if( pEffect->getParaDepth() < nTextGrouping ) + { + if( fTextGroupingAuto == -1.0 ) + { + pEffect->setNodeType( EffectNodeType::ON_CLICK ); + pEffect->setBegin( 0.0 ); + } + else + { + pEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS ); + pEffect->setBegin( fTextGroupingAuto ); + } + } + else + { + pEffect->setNodeType( EffectNodeType::WITH_PREVIOUS ); + pEffect->setBegin( 0.0 ); + } + } + + pTextGroup->addEffect( pEffect ); + + } + notify_listeners(); + } +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::setAnimateForm( CustomAnimationTextGroupPtr pTextGroup, sal_Bool bAnimateForm ) +{ + if( pTextGroup->mbAnimateForm == bAnimateForm ) + { + // trivial case, do nothing + } + else + { + EffectSequence aEffects( pTextGroup->maEffects ); + pTextGroup->reset(); + + EffectSequence::iterator aIter( aEffects.begin() ); + const EffectSequence::iterator aEnd( aEffects.end() ); + + // first insert if we have to + if( bAnimateForm ) + { + EffectSequence::iterator aInsertIter( find( (*aIter) ) ); + + CustomAnimationEffectPtr pEffect; + if( (aEffects.size() == 1) && ((*aIter)->getTarget().getValueType() != ::getCppuType((const ParagraphTarget*)0) ) ) + { + // special case, only one effect and that targets whole text, + // convert this to target whole shape + pEffect = (*aIter++); + pEffect->setTargetSubItem( ShapeAnimationSubType::AS_WHOLE ); + } + else + { + pEffect = (*aIter)->clone(); + pEffect->setTarget( makeAny( (*aIter)->getTargetShape() ) ); + pEffect->setTargetSubItem( ShapeAnimationSubType::ONLY_BACKGROUND ); + maEffects.insert( aInsertIter, pEffect ); + } + + pTextGroup->addEffect( pEffect ); + } + + if( !bAnimateForm && (aEffects.size() == 1) ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + pEffect->setTarget( makeAny( (*aIter)->getTargetShape() ) ); + pEffect->setTargetSubItem( ShapeAnimationSubType::ONLY_TEXT ); + pTextGroup->addEffect( pEffect ); + } + else + { + // readd the rest to the group again + while( aIter != aEnd ) + { + CustomAnimationEffectPtr pEffect( (*aIter++) ); + + if( pEffect->getTarget().getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + { + pTextGroup->addEffect( pEffect ); + } + else + { + DBG_ASSERT( !bAnimateForm, "sd::EffectSequenceHelper::setAnimateForm(), something is wrong here!" ); + remove( pEffect ); + } + } + } + notify_listeners(); + } +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::setTextGroupingAuto( CustomAnimationTextGroupPtr pTextGroup, double fTextGroupingAuto ) +{ + sal_Int32 nTextGrouping = pTextGroup->mnTextGrouping; + + EffectSequence aEffects( pTextGroup->maEffects ); + pTextGroup->reset(); + + EffectSequence::iterator aIter( aEffects.begin() ); + const EffectSequence::iterator aEnd( aEffects.end() ); + while( aIter != aEnd ) + { + CustomAnimationEffectPtr pEffect( (*aIter++) ); + + if( pEffect->getTarget().getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + { + // set correct node type + if( pEffect->getParaDepth() < nTextGrouping ) + { + if( fTextGroupingAuto == -1.0 ) + { + pEffect->setNodeType( EffectNodeType::ON_CLICK ); + pEffect->setBegin( 0.0 ); + } + else + { + pEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS ); + pEffect->setBegin( fTextGroupingAuto ); + } + } + else + { + pEffect->setNodeType( EffectNodeType::WITH_PREVIOUS ); + pEffect->setBegin( 0.0 ); + } + } + + pTextGroup->addEffect( pEffect ); + + } + notify_listeners(); +} + +// -------------------------------------------------------------------- + +struct ImplStlTextGroupSortHelper +{ + ImplStlTextGroupSortHelper( bool bReverse ) : mbReverse( bReverse ) {}; + bool operator()( const CustomAnimationEffectPtr& p1, const CustomAnimationEffectPtr& p2 ); + bool mbReverse; + sal_Int32 getTargetParagraph( const CustomAnimationEffectPtr& p1 ); +}; + +// -------------------------------------------------------------------- + +sal_Int32 ImplStlTextGroupSortHelper::getTargetParagraph( const CustomAnimationEffectPtr& p1 ) +{ + const Any aTarget(p1->getTarget()); + if( aTarget.hasValue() && aTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + { + ParagraphTarget aParaTarget; + aTarget >>= aParaTarget; + return aParaTarget.Paragraph; + } + else + { + return mbReverse ? 0x7fffffff : -1; + } +} + +// -------------------------------------------------------------------- + +bool ImplStlTextGroupSortHelper::operator()( const CustomAnimationEffectPtr& p1, const CustomAnimationEffectPtr& p2 ) +{ + if( mbReverse ) + { + return getTargetParagraph( p2 ) < getTargetParagraph( p1 ); + } + else + { + return getTargetParagraph( p1 ) < getTargetParagraph( p2 ); + } +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::setTextReverse( CustomAnimationTextGroupPtr pTextGroup, sal_Bool bTextReverse ) +{ + if( pTextGroup->mbTextReverse == bTextReverse ) + { + // do nothing + } + else + { + std::vector< CustomAnimationEffectPtr > aSortedVector(pTextGroup->maEffects.size()); + std::copy( pTextGroup->maEffects.begin(), pTextGroup->maEffects.end(), aSortedVector.begin() ); + ImplStlTextGroupSortHelper aSortHelper( bTextReverse ); + std::sort( aSortedVector.begin(), aSortedVector.end(), aSortHelper ); + + pTextGroup->reset(); + + std::vector< CustomAnimationEffectPtr >::iterator aIter( aSortedVector.begin() ); + const std::vector< CustomAnimationEffectPtr >::iterator aEnd( aSortedVector.end() ); + + if( aIter != aEnd ) + { + pTextGroup->addEffect( (*aIter ) ); + EffectSequence::iterator aInsertIter( find( (*aIter++) ) ); + while( aIter != aEnd ) + { + CustomAnimationEffectPtr pEffect( (*aIter++) ); + maEffects.erase( find( pEffect ) ); + aInsertIter = maEffects.insert( ++aInsertIter, pEffect ); + pTextGroup->addEffect( pEffect ); + } + } + notify_listeners(); + } +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::addListener( ISequenceListener* pListener ) +{ + if( std::find( maListeners.begin(), maListeners.end(), pListener ) == maListeners.end() ) + maListeners.push_back( pListener ); +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::removeListener( ISequenceListener* pListener ) +{ + maListeners.remove( pListener ); +} + +// -------------------------------------------------------------------- + +struct stl_notify_listeners_func : public std::unary_function<ISequenceListener*, void> +{ + stl_notify_listeners_func() {} + void operator()(ISequenceListener* pListener) { pListener->notify_change(); } +}; + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::notify_listeners() +{ + stl_notify_listeners_func aFunc; + std::for_each( maListeners.begin(), maListeners.end(), aFunc ); +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::create( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) +{ + DBG_ASSERT( xNode.is(), "sd::EffectSequenceHelper::create(), illegal argument" ); + + if( xNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW ); + createEffectsequence( xChildNode ); + } + } + catch( Exception& ) + { + DBG_ERROR( "sd::EffectSequenceHelper::create(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::createEffectsequence( const Reference< XAnimationNode >& xNode ) +{ + DBG_ASSERT( xNode.is(), "sd::EffectSequenceHelper::createEffectsequence(), illegal argument" ); + + if( xNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW ); + + createEffects( xChildNode ); + } + } + catch( Exception& ) + { + DBG_ERROR( "sd::EffectSequenceHelper::createEffectsequence(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::createEffects( const Reference< XAnimationNode >& xNode ) +{ + DBG_ASSERT( xNode.is(), "sd::EffectSequenceHelper::createEffects(), illegal argument" ); + + if( xNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW ); + + switch( xChildNode->getType() ) + { + // found an effect + case AnimationNodeType::PAR: + case AnimationNodeType::ITERATE: + { + CustomAnimationEffectPtr pEffect( new CustomAnimationEffect( xChildNode ) ); + + if( pEffect->mnNodeType != -1 ) + { + pEffect->setEffectSequence( this ); + maEffects.push_back(pEffect); + } + } + break; + + // found an after effect + case AnimationNodeType::SET: + case AnimationNodeType::ANIMATECOLOR: + { + processAfterEffect( xChildNode ); + } + break; + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::EffectSequenceHelper::createEffects(), exception cought!" ); + } +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::processAfterEffect( const Reference< XAnimationNode >& xNode ) +{ + try + { + Reference< XAnimationNode > xMaster; + + Sequence< NamedValue > aUserData( xNode->getUserData() ); + sal_Int32 nLength = aUserData.getLength(); + const NamedValue* p = aUserData.getConstArray(); + + while( nLength-- ) + { + if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "master-element" ) ) ) + { + p->Value >>= xMaster; + break; + } + p++; + } + + // only process if this is a valid after effect + if( xMaster.is() ) + { + CustomAnimationEffectPtr pMasterEffect; + + // find the master effect + stl_CustomAnimationEffect_search_node_predict aSearchPredict( xMaster ); + EffectSequence::iterator aIter( std::find_if( maEffects.begin(), maEffects.end(), aSearchPredict ) ); + if( aIter != maEffects.end() ) + pMasterEffect = (*aIter ); + + if( pMasterEffect.get() ) + { + pMasterEffect->setHasAfterEffect( true ); + + // find out what kind of after effect this is + if( xNode->getType() == AnimationNodeType::ANIMATECOLOR ) + { + // its a dim + Reference< XAnimate > xAnimate( xNode, UNO_QUERY_THROW ); + pMasterEffect->setDimColor( xAnimate->getTo() ); + pMasterEffect->setAfterEffectOnNext( true ); + } + else + { + // its a hide + Reference< XChild > xNodeChild( xNode, UNO_QUERY_THROW ); + Reference< XChild > xMasterChild( xMaster, UNO_QUERY_THROW ); + pMasterEffect->setAfterEffectOnNext( xNodeChild->getParent() != xMasterChild->getParent() ); + } + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::EffectSequenceHelper::processAfterEffect(), exception cought!" ); + } +} + +// ==================================================================== + +class AnimationChangeListener : public cppu::WeakImplHelper1< XChangesListener > +{ +public: + AnimationChangeListener( MainSequence* pMainSequence ) : mpMainSequence( pMainSequence ) {} + + virtual void SAL_CALL changesOccurred( const ::com::sun::star::util::ChangesEvent& Event ) throw (RuntimeException); + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (RuntimeException); +private: + MainSequence* mpMainSequence; +}; + +void SAL_CALL AnimationChangeListener::changesOccurred( const ::com::sun::star::util::ChangesEvent& ) throw (RuntimeException) +{ + if( mpMainSequence ) + mpMainSequence->startRecreateTimer(); +} + +void SAL_CALL AnimationChangeListener::disposing( const ::com::sun::star::lang::EventObject& ) throw (RuntimeException) +{ +} + +// ==================================================================== + +MainSequence::MainSequence() +: mxTimingRootNode( ::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.SequenceTimeContainer"))), UNO_QUERY ) +, mbRebuilding( false ) +, mnRebuildLockGuard( 0 ) +, mbPendingRebuildRequest( false ) +{ + if( mxTimingRootNode.is() ) + { + Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 ); + aUserData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) ); + aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE; + mxTimingRootNode->setUserData( aUserData ); + } + init(); +} + +// -------------------------------------------------------------------- + +MainSequence::MainSequence( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) +: mxTimingRootNode( xNode, UNO_QUERY ) +, mbRebuilding( false ) +, mnRebuildLockGuard( 0 ) +, mbPendingRebuildRequest( false ) +, mbIgnoreChanges( 0 ) +{ + init(); +} + +// -------------------------------------------------------------------- + +MainSequence::~MainSequence() +{ + reset(); +} + +// -------------------------------------------------------------------- + +void MainSequence::init() +{ + mnSequenceType = EffectNodeType::MAIN_SEQUENCE; + + maTimer.SetTimeoutHdl( LINK(this, MainSequence, onTimerHdl) ); + maTimer.SetTimeout(500); + + mxChangesListener.set( new AnimationChangeListener( this ) ); + + createMainSequence(); +} + +// -------------------------------------------------------------------- + +void MainSequence::reset( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xTimingRootNode ) +{ + reset(); + + mxTimingRootNode.set( xTimingRootNode, UNO_QUERY ); + + createMainSequence(); +} + +// -------------------------------------------------------------------- + +Reference< ::com::sun::star::animations::XAnimationNode > MainSequence::getRootNode() +{ + DBG_ASSERT( mnRebuildLockGuard == 0, "MainSequence::getRootNode(), rebuild is locked, ist this really what you want?" ); + + if( maTimer.IsActive() && mbTimerMode ) + { + // force a rebuild NOW if one is pending + maTimer.Stop(); + implRebuild(); + } + + return EffectSequenceHelper::getRootNode(); +} + +// -------------------------------------------------------------------- + +void MainSequence::createMainSequence() +{ + if( mxTimingRootNode.is() ) try + { + Reference< XEnumerationAccess > xEnumerationAccess( mxTimingRootNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW ); + sal_Int32 nNodeType = CustomAnimationEffect::get_node_type( xChildNode ); + if( nNodeType == EffectNodeType::MAIN_SEQUENCE ) + { + mxSequenceRoot.set( xChildNode, UNO_QUERY ); + EffectSequenceHelper::create( xChildNode ); + } + else if( nNodeType == EffectNodeType::INTERACTIVE_SEQUENCE ) + { + Reference< XTimeContainer > xInteractiveRoot( xChildNode, UNO_QUERY_THROW ); + InteractiveSequencePtr pIS( new InteractiveSequence( xInteractiveRoot, this ) ); + pIS->addListener( this ); + maInteractiveSequenceList.push_back( pIS ); + } + } + + // see if we have a mainsequence at all. if not, create one... + if( !mxSequenceRoot.is() ) + { + mxSequenceRoot = Reference< XTimeContainer >::query(::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.SequenceTimeContainer")))); + if( mxSequenceRoot.is() ) + { + uno::Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 ); + aUserData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) ); + aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::MAIN_SEQUENCE; + mxSequenceRoot->setUserData( aUserData ); + + // empty sequence until now, set duration to 0.0 + // explicitely (otherwise, this sequence will never + // end) + mxSequenceRoot->setDuration( makeAny((double)0.0) ); + + Reference< XAnimationNode > xMainSequenceNode( mxSequenceRoot, UNO_QUERY_THROW ); + mxTimingRootNode->appendChild( xMainSequenceNode ); + } + } + + updateTextGroups(); + + notify_listeners(); + + Reference< XChangesNotifier > xNotifier( mxTimingRootNode, UNO_QUERY ); + if( xNotifier.is() ) + xNotifier->addChangesListener( mxChangesListener ); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::MainSequence::create(), exception cought!" ); + return; + } + + DBG_ASSERT( mxSequenceRoot.is(), "sd::MainSequence::create(), found no main sequence!" ); +} + +// -------------------------------------------------------------------- + +void MainSequence::reset() +{ + EffectSequenceHelper::reset(); + + InteractiveSequenceList::iterator aIter; + for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); ++aIter ) + (*aIter)->reset(); + maInteractiveSequenceList.clear(); + + try + { + Reference< XChangesNotifier > xNotifier( mxTimingRootNode, UNO_QUERY ); + if( xNotifier.is() ) + xNotifier->removeChangesListener( mxChangesListener ); + } + catch( Exception& ) + { + // ... + } +} + +// -------------------------------------------------------------------- + +InteractiveSequencePtr MainSequence::createInteractiveSequence( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape ) +{ + InteractiveSequencePtr pIS; + + // create a new interactive sequence container + Reference< XTimeContainer > xISRoot( ::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.SequenceTimeContainer"))), UNO_QUERY ); + DBG_ASSERT( xISRoot.is(), "sd::MainSequence::createInteractiveSequence(), could not create \"com.sun.star.animations.SequenceTimeContainer\"!"); + if( xISRoot.is() ) + { + uno::Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 ); + aUserData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) ); + aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::INTERACTIVE_SEQUENCE ; + xISRoot->setUserData( aUserData ); + + Reference< XChild > xChild( mxSequenceRoot, UNO_QUERY_THROW ); + Reference< XAnimationNode > xISNode( xISRoot, UNO_QUERY_THROW ); + Reference< XTimeContainer > xParent( xChild->getParent(), UNO_QUERY_THROW ); + xParent->appendChild( xISNode ); + } + pIS.reset( new InteractiveSequence( xISRoot, this) ); + pIS->setTriggerShape( xShape ); + pIS->addListener( this ); + maInteractiveSequenceList.push_back( pIS ); + return pIS; +} + +// -------------------------------------------------------------------- + +CustomAnimationEffectPtr MainSequence::findEffect( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) const +{ + CustomAnimationEffectPtr pEffect = EffectSequenceHelper::findEffect( xNode ); + + if( pEffect.get() == 0 ) + { + InteractiveSequenceList::const_iterator aIter; + for( aIter = maInteractiveSequenceList.begin(); (aIter != maInteractiveSequenceList.end()) && (pEffect.get() == 0); ++aIter ) + { + pEffect = (*aIter)->findEffect( xNode ); + } + } + return pEffect; +} + +// -------------------------------------------------------------------- + +sal_Int32 MainSequence::getOffsetFromEffect( const CustomAnimationEffectPtr& pEffect ) const +{ + sal_Int32 nOffset = EffectSequenceHelper::getOffsetFromEffect( pEffect ); + + if( nOffset != -1 ) + return nOffset; + + nOffset = EffectSequenceHelper::getCount(); + + InteractiveSequenceList::const_iterator aIter; + for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); ++aIter ) + { + sal_Int32 nTemp = (*aIter)->getOffsetFromEffect( pEffect ); + if( nTemp != -1 ) + return nOffset + nTemp; + + nOffset += (*aIter)->getCount(); + } + + return -1; +} + +// -------------------------------------------------------------------- + +CustomAnimationEffectPtr MainSequence::getEffectFromOffset( sal_Int32 nOffset ) const +{ + if( nOffset >= 0 ) + { + if( nOffset < getCount() ) + return EffectSequenceHelper::getEffectFromOffset( nOffset ); + + nOffset -= getCount(); + + InteractiveSequenceList::const_iterator aIter( maInteractiveSequenceList.begin() ); + + while( (aIter != maInteractiveSequenceList.end()) && (nOffset > (*aIter)->getCount()) ) + nOffset -= (*aIter++)->getCount(); + + if( (aIter != maInteractiveSequenceList.end()) && (nOffset >= 0) ) + return (*aIter)->getEffectFromOffset( nOffset ); + } + + CustomAnimationEffectPtr pEffect; + return pEffect; +} + +// -------------------------------------------------------------------- + +bool MainSequence::disposeShape( const Reference< XShape >& xShape ) +{ + bool bChanges = EffectSequenceHelper::disposeShape( xShape ); + + InteractiveSequenceList::iterator aIter; + for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); ) + { + if( (*aIter)->getTriggerShape() == xShape ) + { + aIter = maInteractiveSequenceList.erase( aIter ); + bChanges = true; + } + else + { + bChanges |= (*aIter++)->disposeShape( xShape ); + } + } + + if( bChanges ) + startRebuildTimer(); + + return bChanges; +} + +// -------------------------------------------------------------------- + +bool MainSequence::hasEffect( const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xShape ) +{ + if( EffectSequenceHelper::hasEffect( xShape ) ) + return true; + + InteractiveSequenceList::iterator aIter; + for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); ) + { + if( (*aIter)->getTriggerShape() == xShape ) + return true; + + if( (*aIter++)->hasEffect( xShape ) ) + return true; + } + + return false; +} + +// -------------------------------------------------------------------- + +void MainSequence::insertTextRange( const com::sun::star::uno::Any& aTarget ) +{ + EffectSequenceHelper::insertTextRange( aTarget ); + + InteractiveSequenceList::iterator aIter; + for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); ++aIter ) + { + (*aIter)->insertTextRange( aTarget ); + } +} +// -------------------------------------------------------------------- + +void MainSequence::disposeTextRange( const com::sun::star::uno::Any& aTarget ) +{ + EffectSequenceHelper::disposeTextRange( aTarget ); + + InteractiveSequenceList::iterator aIter; + for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); ++aIter ) + { + (*aIter)->disposeTextRange( aTarget ); + } +} + +// -------------------------------------------------------------------- + +/** callback from the sd::View when an object just left text edit mode */ +void MainSequence::onTextChanged( const Reference< XShape >& xShape ) +{ + EffectSequenceHelper::onTextChanged( xShape ); + + InteractiveSequenceList::iterator aIter; + for( aIter = maInteractiveSequenceList.begin(); aIter != maInteractiveSequenceList.end(); ++aIter ) + { + (*aIter)->onTextChanged( xShape ); + } +} + +// -------------------------------------------------------------------- + +void EffectSequenceHelper::onTextChanged( const Reference< XShape >& xShape ) +{ + bool bChanges = false; + + EffectSequence::iterator aIter; + for( aIter = maEffects.begin(); aIter != maEffects.end(); ++aIter ) + { + if( (*aIter)->getTargetShape() == xShape ) + bChanges |= (*aIter)->checkForText(); + } + + if( bChanges ) + EffectSequenceHelper::implRebuild(); +} + +// -------------------------------------------------------------------- + +void MainSequence::rebuild() +{ + startRebuildTimer(); +} + +// -------------------------------------------------------------------- + +void MainSequence::lockRebuilds() +{ + mnRebuildLockGuard++; +} + +// -------------------------------------------------------------------- + +void MainSequence::unlockRebuilds() +{ + DBG_ASSERT( mnRebuildLockGuard, "sd::MainSequence::unlockRebuilds(), no corresponding lockRebuilds() call!" ); + if( mnRebuildLockGuard ) + mnRebuildLockGuard--; + + if( (mnRebuildLockGuard == 0) && mbPendingRebuildRequest ) + { + mbPendingRebuildRequest = false; + startRebuildTimer(); + } +} + +// -------------------------------------------------------------------- + +void MainSequence::implRebuild() +{ + if( mnRebuildLockGuard ) + { + mbPendingRebuildRequest = true; + return; + } + + mbRebuilding = true; + + EffectSequenceHelper::implRebuild(); + + InteractiveSequenceList::iterator aIter( maInteractiveSequenceList.begin() ); + const InteractiveSequenceList::iterator aEnd( maInteractiveSequenceList.end() ); + while( aIter != aEnd ) + { + InteractiveSequencePtr pIS( (*aIter) ); + if( pIS->maEffects.empty() ) + { + // remove empty interactive sequences + aIter = maInteractiveSequenceList.erase( aIter ); + + Reference< XChild > xChild( mxSequenceRoot, UNO_QUERY_THROW ); + Reference< XTimeContainer > xParent( xChild->getParent(), UNO_QUERY_THROW ); + Reference< XAnimationNode > xISNode( pIS->mxSequenceRoot, UNO_QUERY_THROW ); + xParent->removeChild( xISNode ); + } + else + { + pIS->implRebuild(); + aIter++; + } + } + + notify_listeners(); + mbRebuilding = false; +} + +// -------------------------------------------------------------------- + +void MainSequence::notify_change() +{ + notify_listeners(); +} + +// -------------------------------------------------------------------- + +bool MainSequence::setTrigger( const CustomAnimationEffectPtr& pEffect, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xTriggerShape ) +{ + EffectSequenceHelper* pOldSequence = pEffect->getEffectSequence(); + + EffectSequenceHelper* pNewSequence = 0; + if( xTriggerShape.is() ) + { + InteractiveSequenceList::iterator aIter( maInteractiveSequenceList.begin() ); + const InteractiveSequenceList::iterator aEnd( maInteractiveSequenceList.end() ); + while( aIter != aEnd ) + { + InteractiveSequencePtr pIS( (*aIter++) ); + if( pIS->getTriggerShape() == xTriggerShape ) + { + pNewSequence = pIS.get(); + break; + } + } + + if( !pNewSequence ) + pNewSequence = createInteractiveSequence( xTriggerShape ).get(); + } + else + { + pNewSequence = this; + } + + if( pOldSequence != pNewSequence ) + { + if( pOldSequence ) + pOldSequence->maEffects.remove( pEffect ); + if( pNewSequence ) + pNewSequence->maEffects.push_back( pEffect ); + pEffect->setEffectSequence( pNewSequence ); + return true; + } + else + { + return false; + } + +} + +// -------------------------------------------------------------------- + +IMPL_LINK( MainSequence, onTimerHdl, Timer *, EMPTYARG ) +{ + if( mbTimerMode ) + { + implRebuild(); + } + else + { + reset(); + createMainSequence(); + } + + return 0; +} + +// -------------------------------------------------------------------- + +/** starts a timer that recreates the internal structure from the API core after 1 second */ +void MainSequence::startRecreateTimer() +{ + if( !mbRebuilding && (mbIgnoreChanges == 0) ) + { + mbTimerMode = false; + maTimer.Start(); + } +} + +// -------------------------------------------------------------------- + +/** starts a timer that rebuilds the API core from the internal structure after 1 second */ +void MainSequence::startRebuildTimer() +{ + mbTimerMode = true; + maTimer.Start(); +} + +// ==================================================================== + +InteractiveSequence::InteractiveSequence( const Reference< XTimeContainer >& xSequenceRoot, MainSequence* pMainSequence ) +: EffectSequenceHelper( xSequenceRoot ), mpMainSequence( pMainSequence ) +{ + mnSequenceType = EffectNodeType::INTERACTIVE_SEQUENCE; + + try + { + if( mxSequenceRoot.is() ) + { + Reference< XEnumerationAccess > xEnumerationAccess( mxSequenceRoot, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + while( !mxEventSource.is() && xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW ); + + Event aEvent; + if( (xChildNode->getBegin() >>= aEvent) && (aEvent.Trigger == EventTrigger::ON_CLICK) ) + aEvent.Source >>= mxEventSource; + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::InteractiveSequence::InteractiveSequence(), exception cought!" ); + return; + } +} + +// -------------------------------------------------------------------- + +void InteractiveSequence::rebuild() +{ + mpMainSequence->rebuild(); +} + +void InteractiveSequence::implRebuild() +{ + EffectSequenceHelper::implRebuild(); +} + +// -------------------------------------------------------------------- + +MainSequenceRebuildGuard::MainSequenceRebuildGuard( const MainSequencePtr& pMainSequence ) +: mpMainSequence( pMainSequence ) +{ + if( mpMainSequence.get() ) + mpMainSequence->lockRebuilds(); +} + +MainSequenceRebuildGuard::~MainSequenceRebuildGuard() +{ + if( mpMainSequence.get() ) + mpMainSequence->unlockRebuilds(); +} + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/CustomAnimationPreset.cxx b/sd/source/core/CustomAnimationPreset.cxx new file mode 100644 index 000000000000..9926b708f0a6 --- /dev/null +++ b/sd/source/core/CustomAnimationPreset.cxx @@ -0,0 +1,673 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/util/XMacroExpander.hpp> +#include <com/sun/star/animations/XAnimationNodeSupplier.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/xml/sax/SAXParseException.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/presentation/EffectPresetClass.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <tools/urlobj.hxx> +#include <unotools/streamwrap.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/pathoptions.hxx> +#include <tools/stream.hxx> + +#include <tools/debug.hxx> +#include <rtl/uri.hxx> +#include <vcl/svapp.hxx> +#include <osl/mutex.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <CustomAnimationPreset.hxx> + +#include <algorithm> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; + +using ::rtl::OUString; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::io::XInputStream; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::util::XCloneable; +using ::com::sun::star::beans::NamedValue; + +namespace sd { + +static Reference< XNameAccess > getNodeAccess( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath ) +{ + Reference< XNameAccess > xConfigAccess; + + try + { + Sequence< Any > aArgs( 1 ); + PropertyValue aPropValue; + aPropValue.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" )); + aPropValue.Value <<= rNodePath; + aArgs[0] <<= aPropValue; + + xConfigAccess = Reference< XNameAccess >::query( + xConfigProvider->createInstanceWithArguments( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" )), + aArgs )); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::getNodeAccess(), Exception catched!" ); + } + + return xConfigAccess; +} + +void implImportLabels( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath, UStringMap& rStringMap ) +{ + try + { + Reference< XNameAccess > xConfigAccess( getNodeAccess( xConfigProvider, rNodePath ) ); + if( xConfigAccess.is() ) + { + OUString aLabel( RTL_CONSTASCII_USTRINGPARAM( "Label" ) ); + Reference< XNameAccess > xNameAccess; + Sequence< OUString > aNames( xConfigAccess->getElementNames() ); + const OUString* p = aNames.getConstArray(); + sal_Int32 n = aNames.getLength(); + while(n--) + { + xConfigAccess->getByName( *p ) >>= xNameAccess; + if( xNameAccess.is() ) + { + OUString aUIName; + xNameAccess->getByName( aLabel ) >>= aUIName; + if( aUIName.getLength() ) + { + rStringMap[ *p ] = aUIName; + } + } + + p++; + } + } + } + catch( lang::WrappedTargetException& e ) + { + (void)e; + DBG_ERROR( "sd::implImportLabels(), WrappedTargetException catched!" ); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::implImportLabels(), Exception catched!" ); + } +} + +CustomAnimationPreset::CustomAnimationPreset( CustomAnimationEffectPtr pEffect ) +{ + maPresetId = pEffect->getPresetId(); + maProperty = pEffect->getProperty(); + mnPresetClass = pEffect->getPresetClass(); + + add( pEffect ); + + mfDuration = pEffect->getDuration(); + maDefaultSubTyp = pEffect->getPresetSubType(); + + mbIsTextOnly = false; + + Sequence< NamedValue > aUserData( pEffect->getNode()->getUserData() ); + sal_Int32 nLength = aUserData.getLength(); + const NamedValue* p = aUserData.getConstArray(); + + while( nLength-- ) + { + if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "text-only" ) ) ) + { + mbIsTextOnly = true; + break; + } + p++; + } + +} + +void CustomAnimationPreset::add( CustomAnimationEffectPtr pEffect ) +{ + maSubTypes[ pEffect->getPresetSubType() ] = pEffect; +} + +UStringList CustomAnimationPreset::getSubTypes() +{ + UStringList aSubTypes; + + if( maSubTypes.size() > 1 ) + { + EffectsSubTypeMap::iterator aIter( maSubTypes.begin() ); + const EffectsSubTypeMap::iterator aEnd( maSubTypes.end() ); + while( aIter != aEnd ) + aSubTypes.push_back( (*aIter++).first ); + } + + return aSubTypes; +} + +Reference< XAnimationNode > CustomAnimationPreset::create( const rtl::OUString& rstrSubType ) +{ + try + { + OUString strSubType( rstrSubType ); + if( strSubType.getLength() == 0 ) + strSubType = maDefaultSubTyp; + + CustomAnimationEffectPtr pEffect = maSubTypes[strSubType]; + if( pEffect.get() ) + { + Reference< XCloneable > xCloneable( pEffect->getNode(), UNO_QUERY_THROW ); + Reference< XAnimationNode > xNode( xCloneable->createClone(), UNO_QUERY_THROW ); + return xNode; + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::CustomAnimationPresets::create(), exception catched!" ); + } + + Reference< XAnimationNode > xNode; + return xNode; +} + +UStringList CustomAnimationPreset::getProperties() const +{ + String aProperties( maProperty ); + USHORT nTokens = aProperties.GetTokenCount(); + USHORT nToken; + UStringList aPropertyList; + for( nToken = 0; nToken < nTokens; nToken++ ) + aPropertyList.push_back( aProperties.GetToken( nToken ) ); + + return aPropertyList; + +} + +bool CustomAnimationPreset::hasProperty( const OUString& rProperty )const +{ + String aProperties( maProperty ); + String aProperty( rProperty ); + USHORT nTokens = aProperties.GetTokenCount(); + USHORT nToken; + for( nToken = 0; nToken < nTokens; nToken++ ) + { + if( aProperties.GetToken( nToken ) == aProperty ) + return true; + } + + return false; +} + +CustomAnimationPresets::CustomAnimationPresets() +{ +} + +CustomAnimationPresets::~CustomAnimationPresets() +{ +} + +void CustomAnimationPresets::init() +{ + importResources(); +} + +Reference< XAnimationNode > implImportEffects( const Reference< XMultiServiceFactory >& xServiceFactory, const OUString& rPath ) +{ + Reference< XAnimationNode > xRootNode; + + try + { + // create stream + SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( rPath, STREAM_READ ); + Reference<XInputStream> xInputStream( new utl::OInputStreamWrapper( pIStm, sal_True ) ); + + // prepare ParserInputSrouce + xml::sax::InputSource aParserInput; + aParserInput.sSystemId = rPath; + aParserInput.aInputStream = xInputStream; + + // get parser + Reference< xml::sax::XParser > xParser( + xServiceFactory->createInstance( + OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.sax.Parser")) ), + UNO_QUERY ); + + DBG_ASSERT( xParser.is(), "Can't create parser" ); + if( !xParser.is() ) + return xRootNode; + + // get filter + Reference< xml::sax::XDocumentHandler > xFilter( + xServiceFactory->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Xmloff.AnimationsImport" ) ) ), UNO_QUERY ); + + DBG_ASSERT( xFilter.is(), "Can't instantiate filter component." ); + if( !xFilter.is() ) + return xRootNode; + + // connect parser and filter + xParser->setDocumentHandler( xFilter ); + + // finally, parser the stream + xParser->parseStream( aParserInput ); + + Reference< XAnimationNodeSupplier > xAnimationNodeSupplier( xFilter, UNO_QUERY ); + if( xAnimationNodeSupplier.is() ) + xRootNode = xAnimationNodeSupplier->getAnimationNode(); + } + catch( xml::sax::SAXParseException& r ) + { + (void)r; + DBG_ERROR( "sd::implImportEffects(), SAXParseException catched!" ); + } + catch( xml::sax::SAXException& r ) + { + (void)r; + DBG_ERROR( "sd::implImportEffects(), SAXException catched!" ); + } + catch( io::IOException& r ) + { + (void)r; + DBG_ERROR( "sd::implImportEffects(), IOException catched!" ); + } + catch( Exception& r ) + { + (void)r; + DBG_ERROR( "sd::importEffects(), Exception catched!" ); + } + + return xRootNode; +} + +#define EXPAND_PROTOCOL "vnd.sun.star.expand:" + +void CustomAnimationPresets::importEffects() +{ + try + { + // Get service factory + Reference< XMultiServiceFactory > xServiceFactory( comphelper::getProcessServiceFactory() ); + DBG_ASSERT( xServiceFactory.is(), "sd::CustomAnimationPresets::import(), got no service manager" ); + if( !xServiceFactory.is() ) + return; + + uno::Reference< beans::XPropertySet > xProps( xServiceFactory, UNO_QUERY ); + uno::Reference< uno::XComponentContext > xContext; + xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; + + uno::Reference< util::XMacroExpander > xMacroExpander; + if( xContext.is() ) + xMacroExpander.set( xContext->getValueByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.util.theMacroExpander"))), + UNO_QUERY ); + + Reference< XMultiServiceFactory > xConfigProvider( + xServiceFactory->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ))), + UNO_QUERY_THROW ); + + // read path to transition effects files from config + Any propValue = uno::makeAny( + beans::PropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" )), -1, + uno::makeAny( OUString( RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Impress/Misc") )), + beans::PropertyState_DIRECT_VALUE ) ); + + Reference<container::XNameAccess> xNameAccess( + xConfigProvider->createInstanceWithArguments( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")), + Sequence<Any>( &propValue, 1 ) ), UNO_QUERY_THROW ); + uno::Sequence< rtl::OUString > aFiles; + xNameAccess->getByName( + OUString( RTL_CONSTASCII_USTRINGPARAM("EffectFiles"))) >>= aFiles; + + for( sal_Int32 i=0; i<aFiles.getLength(); ++i ) + { + rtl::OUString aURL = aFiles[i]; + if( aURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( EXPAND_PROTOCOL )) == 0 ) + { + // cut protocol + rtl::OUString aMacro( aURL.copy( sizeof ( EXPAND_PROTOCOL ) -1 ) ); + // decode uric class chars + aMacro = rtl::Uri::decode( aMacro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + // expand macro string + aURL = xMacroExpander->expandMacros( aMacro ); + } + + mxRootNode = implImportEffects( xServiceFactory, aURL ); + + if( mxRootNode.is() ) + { + Reference< XTimeContainer > xRootContainer( mxRootNode, UNO_QUERY_THROW ); + EffectSequenceHelper aSequence( xRootContainer ); + + EffectSequence::iterator aIter( aSequence.getBegin() ); + const EffectSequence::iterator aEnd( aSequence.getEnd() ); + + while( aIter != aEnd ) + { + CustomAnimationEffectPtr pEffect = (*aIter); + + const OUString aPresetId( pEffect->getPresetId() ); + CustomAnimationPresetPtr pDescriptor = getEffectDescriptor( aPresetId ); + if( pDescriptor.get() ) + pDescriptor->add( pEffect ); + else + { + pDescriptor.reset( new CustomAnimationPreset( pEffect ) ); + pDescriptor->maLabel = getUINameForPresetId( pEffect->getPresetId() ); + maEffectDiscriptorMap[aPresetId] = pDescriptor; + } + + aIter++; + } + } + } + } + catch( xml::sax::SAXParseException& r ) + { + (void)r; + DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), SAXParseException catched!" ); + } + catch( xml::sax::SAXException& r ) + { + (void)r; + DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), SAXException catched!" ); + } + catch( io::IOException& r ) + { + (void)r; + DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), IOException catched!" ); + } + catch( Exception& r ) + { + (void)r; + DBG_ERROR( "sd::CustomAnimationPresets::importEffects(), Exception catched!" ); + } +} + +void CustomAnimationPresets::importResources() +{ + try + { + // Get service factory + Reference< XMultiServiceFactory > xServiceFactory( comphelper::getProcessServiceFactory() ); + DBG_ASSERT( xServiceFactory.is(), "sd::CustomAnimationPresets::import(), got no service manager" ); + if( !xServiceFactory.is() ) + return; + + Reference< XMultiServiceFactory > xConfigProvider( + xServiceFactory->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ))), + UNO_QUERY ); + + const OUString aPropertyPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/UserInterface/Properties" ) ); + implImportLabels( xConfigProvider, aPropertyPath, maPropertyNameMap ); + + const OUString aEffectsPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/UserInterface/Effects" ) ); + implImportLabels( xConfigProvider, aEffectsPath, maEffectNameMap ); + + importEffects(); + + const OUString aEntrancePath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Entrance" ) ); + importPresets( xConfigProvider, aEntrancePath, maEntrancePresets ); + + const OUString aEmphasisPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Emphasis" ) ); + importPresets( xConfigProvider, aEmphasisPath, maEmphasisPresets ); + + const OUString aExitPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Exit" ) ); + importPresets( xConfigProvider, aExitPath, maExitPresets ); + + const OUString aMotionPathsPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/MotionPaths" ) ); + importPresets( xConfigProvider, aMotionPathsPath, maMotionPathsPresets ); + + const OUString aMiscPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/Presets/Misc" ) ); + importPresets( xConfigProvider, aMiscPath, maMiscPresets ); + } + catch( lang::WrappedTargetException& e ) + { + (void)e; + DBG_ERROR( "sd::CustomAnimationPresets::importResources(), WrappedTargetException catched!" ); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::CustomAnimationPresets::importResources(), Exception catched!" ); + } +} + +void CustomAnimationPresets::importPresets( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath, PresetCategoryList& rPresetMap ) +{ +#ifdef DEBUG + String aMissedPresetIds; +#endif + + try + { + Reference< XNameAccess > xTypeAccess( getNodeAccess( xConfigProvider, rNodePath ) ); + if( xTypeAccess.is() ) + { + Reference< XNameAccess > xCategoryAccess; + const OUString aEffectsName( RTL_CONSTASCII_USTRINGPARAM( "Effects" ) ); + const OUString aLabelName( RTL_CONSTASCII_USTRINGPARAM( "Label" ) ); + + Sequence< OUString > aNames( xTypeAccess->getElementNames() ); + const OUString* p = aNames.getConstArray(); + sal_Int32 n = aNames.getLength(); + while(n--) + { + xTypeAccess->getByName( *p ) >>= xCategoryAccess; + + if( xCategoryAccess.is() && xCategoryAccess->hasByName( aLabelName ) && xCategoryAccess->hasByName( aEffectsName ) ) + { + OUString aLabel; + xCategoryAccess->getByName( aLabelName ) >>= aLabel; + + Sequence< OUString > aEffects; + xCategoryAccess->getByName( aEffectsName ) >>= aEffects; + + EffectDescriptorList aEffectsList; + + const OUString* pEffectNames = aEffects.getConstArray(); + sal_Int32 nEffectCount = aEffects.getLength(); + while( nEffectCount-- ) + { + CustomAnimationPresetPtr pEffect = getEffectDescriptor( *pEffectNames ); + if( pEffect.get() ) + { + aEffectsList.push_back( pEffect ); + } +#ifdef DEBUG + else + { + aMissedPresetIds += String(*pEffectNames); + aMissedPresetIds += String( RTL_CONSTASCII_USTRINGPARAM("\n") ); + } +#endif + pEffectNames++; + } + rPresetMap.push_back( PresetCategoryPtr( new PresetCategory( aLabel, aEffectsList ) ) ); + } + + p++; + } + } + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::CustomAnimationPresets::importPresets(), Exception catched!" ); + } + +#ifdef DEBUG + if( aMissedPresetIds.Len() ) + { + ByteString aTmp( "sd::CustomAnimationPresets::importPresets(), invalid preset id!\n" ); + aTmp += ByteString( aMissedPresetIds, RTL_TEXTENCODING_ASCII_US ); + DBG_ERROR( aTmp.GetBuffer() ); + } +#endif +} + +CustomAnimationPresetPtr CustomAnimationPresets::getEffectDescriptor( const rtl::OUString& rPresetId ) const +{ + EffectDescriptorMap::const_iterator aIter( maEffectDiscriptorMap.find( rPresetId ) ); + + if( aIter != maEffectDiscriptorMap.end() ) + { + return (*aIter).second; + } + else + { + return CustomAnimationPresetPtr((CustomAnimationPreset*)0); + } +} + +const rtl::OUString& CustomAnimationPresets::getUINameForPresetId( const rtl::OUString& rPresetId ) const +{ + return translateName( rPresetId, maEffectNameMap ); +} + +const rtl::OUString& CustomAnimationPresets::getUINameForProperty( const rtl::OUString& rPresetId ) const +{ + return translateName( rPresetId, maPropertyNameMap ); +} + +const rtl::OUString& CustomAnimationPresets::translateName( const rtl::OUString& rId, const UStringMap& rNameMap ) const +{ + UStringMap::const_iterator aIter( rNameMap.find( rId ) ); + + if( aIter != rNameMap.end() ) + { + return (*aIter).second; + } + else + { + return rId; + } +} +void CustomAnimationPresets::changePresetSubType( CustomAnimationEffectPtr pEffect, const rtl::OUString& rPresetSubType ) const +{ + if( pEffect.get() && pEffect->getPresetSubType() != rPresetSubType ) + { + CustomAnimationPresetPtr pDescriptor( getEffectDescriptor( pEffect->getPresetId() ) ); + + if( pDescriptor.get() ) + { + Reference< XAnimationNode > xNewNode( pDescriptor->create( rPresetSubType ) ); + if( xNewNode.is() ) + pEffect->replaceNode( xNewNode ); + } + } +} + +CustomAnimationPresets* CustomAnimationPresets::mpCustomAnimationPresets = 0; + +const CustomAnimationPresets& CustomAnimationPresets::getCustomAnimationPresets() +{ + if( !mpCustomAnimationPresets ) + { + SolarMutexGuard aGuard; + + if( !mpCustomAnimationPresets ) + { + mpCustomAnimationPresets = new sd::CustomAnimationPresets(); + mpCustomAnimationPresets->init(); + } + } + + return *mpCustomAnimationPresets; +} + +Reference< XAnimationNode > CustomAnimationPresets::getRandomPreset( sal_Int16 nPresetClass ) const +{ + Reference< XAnimationNode > xNode; + + const PresetCategoryList* pCategoryList = 0; + switch( nPresetClass ) + { + case EffectPresetClass::ENTRANCE: pCategoryList = &maEntrancePresets; break; + case EffectPresetClass::EXIT: pCategoryList = &maExitPresets; break; + case EffectPresetClass::EMPHASIS: pCategoryList = &maEmphasisPresets; break; + case EffectPresetClass::MOTIONPATH: pCategoryList = &maMotionPathsPresets; break; + default: + pCategoryList = 0; + } + + if( pCategoryList && pCategoryList->size() ) + { + sal_Int32 nCategory = (rand() * pCategoryList->size() / RAND_MAX); + + PresetCategoryPtr pCategory = (*pCategoryList)[nCategory]; + if( pCategory.get() && pCategory->maEffects.size() ) + { + sal_Int32 nDescriptor = (rand() * pCategory->maEffects.size() / RAND_MAX); + CustomAnimationPresetPtr pPreset = pCategory->maEffects[nDescriptor]; + if( pPreset.get() ) + { + UStringList aSubTypes = pPreset->getSubTypes(); + + OUString aSubType; + if( aSubTypes.size() ) + { + sal_Int32 nSubType = (rand() * aSubTypes.size() / RAND_MAX); + aSubType = aSubTypes[nSubType]; + } + xNode = pPreset->create( aSubType ); + } + } + } + + return xNode; +} + + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/EffectMigration.cxx b/sd/source/core/EffectMigration.cxx new file mode 100644 index 000000000000..2ae71a01522b --- /dev/null +++ b/sd/source/core/EffectMigration.cxx @@ -0,0 +1,1324 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <com/sun/star/presentation/EffectNodeType.hpp> +#include <com/sun/star/presentation/ShapeAnimationSubType.hpp> +#include <com/sun/star/presentation/TextAnimationType.hpp> +#include <com/sun/star/presentation/ParagraphTarget.hpp> +#include <svx/unoshape.hxx> +#include <svx/svdotext.hxx> +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include <CustomAnimationPreset.hxx> +#include <TransitionPreset.hxx> +#include <EffectMigration.hxx> +#include <anminfo.hxx> + +using namespace ::sd; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; + +using ::com::sun::star::drawing::XShape; +using ::rtl::OUString; + +struct deprecated_FadeEffect_conversion_table_entry +{ + FadeEffect meFadeEffect; + const sal_Char* mpPresetId; +} +deprecated_FadeEffect_conversion_table[] = +{ +// OOo 1.x transitions + { FadeEffect_FADE_FROM_LEFT, "wipe-right" }, + { FadeEffect_FADE_FROM_TOP, "wipe-down" }, + { FadeEffect_FADE_FROM_RIGHT, "wipe-left" }, + { FadeEffect_FADE_FROM_BOTTOM, "wipe-up" }, + + { FadeEffect_CLOCKWISE, "wheel-clockwise-1-spoke" }, + + { FadeEffect_UNCOVER_TO_LEFT, "uncover-left" }, + { FadeEffect_UNCOVER_TO_UPPERLEFT, "uncover-left-up" }, + { FadeEffect_UNCOVER_TO_TOP, "uncover-up" }, + { FadeEffect_UNCOVER_TO_UPPERRIGHT, "uncover-right-up" }, + { FadeEffect_UNCOVER_TO_RIGHT, "uncover-right" }, + { FadeEffect_UNCOVER_TO_LOWERRIGHT, "uncover-right-down" }, + { FadeEffect_UNCOVER_TO_BOTTOM, "uncover-down" }, + { FadeEffect_UNCOVER_TO_LOWERLEFT, "uncover-left-down" }, + + { FadeEffect_VERTICAL_LINES, "random-bars-vertical" }, + { FadeEffect_HORIZONTAL_LINES, "random-bars-horizontal" }, + + { FadeEffect_VERTICAL_CHECKERBOARD, "checkerboard-down" }, + { FadeEffect_HORIZONTAL_CHECKERBOARD, "checkerboard-across" }, + + { FadeEffect_FADE_TO_CENTER, "box-in" }, + { FadeEffect_FADE_FROM_CENTER, "box-out" }, + + { FadeEffect_VERTICAL_STRIPES, "venetian-blinds-vertical" }, + { FadeEffect_HORIZONTAL_STRIPES, "venetian-blinds-horizontal" }, + + { FadeEffect_MOVE_FROM_LEFT, "cover-right" }, + { FadeEffect_MOVE_FROM_TOP, "cover-down" }, + { FadeEffect_MOVE_FROM_RIGHT, "cover-left" }, + { FadeEffect_MOVE_FROM_BOTTOM, "cover-up" }, + { FadeEffect_MOVE_FROM_UPPERLEFT, "cover-right-down" }, + { FadeEffect_MOVE_FROM_UPPERRIGHT, "cover-left-down" }, + { FadeEffect_MOVE_FROM_LOWERRIGHT, "cover-left-up" }, + { FadeEffect_MOVE_FROM_LOWERLEFT, "cover-right-up" }, + + { FadeEffect_DISSOLVE, "dissolve" }, + + { FadeEffect_RANDOM, "random-transition" }, + + { FadeEffect_ROLL_FROM_LEFT, "push-right" }, + { FadeEffect_ROLL_FROM_TOP, "push-down" }, + { FadeEffect_ROLL_FROM_RIGHT, "push-left" }, + { FadeEffect_ROLL_FROM_BOTTOM, "push-up" }, + + { FadeEffect_CLOSE_VERTICAL, "split-horizontal-in" }, + { FadeEffect_CLOSE_HORIZONTAL, "split-vertical-in" }, + { FadeEffect_OPEN_VERTICAL, "split-horizontal-out" }, + { FadeEffect_OPEN_HORIZONTAL, "split-vertical-out" }, + + { FadeEffect_FADE_FROM_UPPERLEFT, "diagonal-squares-right-down" }, + { FadeEffect_FADE_FROM_UPPERRIGHT, "diagonal-squares-left-down" }, + { FadeEffect_FADE_FROM_LOWERLEFT, "diagonal-squares-right-up" }, + { FadeEffect_FADE_FROM_LOWERRIGHT, "diagonal-squares-left-up" }, + +// OOo 1.x transitions not in OOo 2.x + { FadeEffect_CLOCKWISE, "clock-wipe-twelve" }, + { FadeEffect_COUNTERCLOCKWISE, "reverse-clock-wipe-twelve" }, + { FadeEffect_SPIRALIN_LEFT, "spiral-wipe-top-left-clockwise" }, + { FadeEffect_SPIRALIN_RIGHT, "spiral-wipe-top-right-counter-clockwise" }, + { FadeEffect_SPIRALOUT_LEFT, "spiral-wipe-out-to-bottom-right-clockwise" }, + { FadeEffect_SPIRALOUT_RIGHT, "spiral-wipe-out-to-bottom-left-counter-clockwise" }, + { FadeEffect_WAVYLINE_FROM_LEFT, "snake-wipe-top-left-vertical" }, + { FadeEffect_WAVYLINE_FROM_TOP, "snake-wipe-top-left-horizontal" }, + { FadeEffect_WAVYLINE_FROM_RIGHT, "snake-wipe-bottom-right-vertical" }, + { FadeEffect_WAVYLINE_FROM_BOTTOM, "snake-wipe-bottom-right-horizontal" }, + { FadeEffect_STRETCH_FROM_LEFT, "wipe-right" }, // todo + { FadeEffect_STRETCH_FROM_TOP, "wipe-down" }, // todo + { FadeEffect_STRETCH_FROM_RIGHT, "wipe-left" }, // todo + { FadeEffect_STRETCH_FROM_BOTTOM, "wipe-up" }, // todo + +// OOo 1.x not available transitions + + { FadeEffect_CLOCKWISE, "wheel-clockwise-2-spokes" }, + { FadeEffect_CLOCKWISE, "wheel-clockwise-3-spokes" }, + { FadeEffect_CLOCKWISE, "wheel-clockwise-4-spokes" }, + { FadeEffect_CLOCKWISE, "wheel-clockwise-8-spokes" }, + + { FadeEffect_FADE_FROM_CENTER, "shape-circle" }, + { FadeEffect_FADE_FROM_CENTER, "shape-diamond" }, + { FadeEffect_FADE_FROM_CENTER, "shape-plus" }, + + { FadeEffect_CLOCKWISE, "wedge" }, + + { FadeEffect_DISSOLVE, "fade-through-black" }, + + { FadeEffect_CLOCKWISE, "zoom-rotate-in" }, + + { FadeEffect_HORIZONTAL_LINES, "comb-horizontal" }, + { FadeEffect_VERTICAL_LINES, "comb-vertical" }, + + { FadeEffect_DISSOLVE, "fade-smoothly" }, + + { FadeEffect_NONE, 0 } +}; + +/* todo +cut cut (same as NONE?) +cut-through-black cut toBlack +wedge wedge +*/ + +void EffectMigration::SetFadeEffect( SdPage* pPage, ::com::sun::star::presentation::FadeEffect eNewEffect) +{ + deprecated_FadeEffect_conversion_table_entry* pEntry = deprecated_FadeEffect_conversion_table; + while( (pEntry->meFadeEffect != FadeEffect_NONE) && (pEntry->meFadeEffect != eNewEffect) ) + pEntry++; + + if( pEntry->mpPresetId ) + { + const OUString aPresetId( OUString::createFromAscii( pEntry->mpPresetId ) ); + + const TransitionPresetList& rPresetList = TransitionPreset::getTransitionPresetList(); + + TransitionPresetList::const_iterator aIt( rPresetList.begin()); + const TransitionPresetList::const_iterator aEndIt( rPresetList.end()); + for( ; aIt != aEndIt; ++aIt ) + { + if( (*aIt)->getPresetId() == aPresetId) + { + pPage->setTransitionType( (*aIt)->getTransition() ); + pPage->setTransitionSubtype( (*aIt)->getSubtype() ); + pPage->setTransitionDirection( (*aIt)->getDirection() ); + pPage->setTransitionFadeColor( (*aIt)->getFadeColor() ); + break; + } + } + } + else + { + pPage->setTransitionType( 0 ); + pPage->setTransitionSubtype( 0 ); + pPage->setTransitionDirection( 0 ); + pPage->setTransitionFadeColor( 0 ); + } +} + +FadeEffect EffectMigration::GetFadeEffect( const SdPage* pPage ) +{ + const TransitionPresetList & rPresetList = TransitionPreset::getTransitionPresetList(); + TransitionPresetList::const_iterator aIt( rPresetList.begin()); + const TransitionPresetList::const_iterator aEndIt( rPresetList.end()); + for( ; aIt != aEndIt; ++aIt ) + { + if( ( (*aIt)->getTransition() == pPage->getTransitionType() ) && + ( (*aIt)->getSubtype() == pPage->getTransitionSubtype() ) && + ( (*aIt)->getDirection() == pPage->getTransitionDirection() ) && + ( (*aIt)->getFadeColor() == pPage->getTransitionFadeColor() ) ) + { + const OUString& aPresetId = (*aIt)->getPresetId(); + + deprecated_FadeEffect_conversion_table_entry* pEntry = deprecated_FadeEffect_conversion_table; + while( (pEntry->meFadeEffect != FadeEffect_NONE) && (!aPresetId.equalsAscii( pEntry->mpPresetId ) ) ) + pEntry++; + + return pEntry->meFadeEffect; + } + } + return FadeEffect_NONE; +} + +struct deprecated_AnimationEffect_conversion_table_entry +{ + AnimationEffect meEffect; + const sal_Char* mpPresetId; + const sal_Char* mpPresetSubType; +} +deprecated_AnimationEffect_conversion_table[] = +{ +// OOo 1.x entrance effects + { AnimationEffect_APPEAR, "ooo-entrance-appear",0 }, + + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-box","in" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-box","out" }, + + { AnimationEffect_VERTICAL_CHECKERBOARD, "ooo-entrance-checkerboard","downward" }, + { AnimationEffect_HORIZONTAL_CHECKERBOARD, "ooo-entrance-checkerboard","across" }, + + { AnimationEffect_FADE_FROM_UPPERLEFT, "ooo-entrance-diagonal-squares","right-to-bottom" }, + { AnimationEffect_FADE_FROM_UPPERRIGHT, "ooo-entrance-diagonal-squares","left-to-bottom" }, + { AnimationEffect_FADE_FROM_LOWERLEFT, "ooo-entrance-diagonal-squares","right-to-top" }, + { AnimationEffect_FADE_FROM_LOWERRIGHT, "ooo-entrance-diagonal-squares","left-to-top" }, + + { AnimationEffect_DISSOLVE, "ooo-entrance-dissolve-in",0 }, + + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-fly-in","from-left" }, + { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-fly-in","from-top" }, + { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-fly-in","from-right" }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-fly-in","from-bottom" }, + { AnimationEffect_MOVE_FROM_UPPERLEFT, "ooo-entrance-fly-in","from-top-left" }, + { AnimationEffect_MOVE_FROM_UPPERRIGHT, "ooo-entrance-fly-in","from-top-right" }, + { AnimationEffect_MOVE_FROM_LOWERRIGHT, "ooo-entrance-fly-in","from-bottom-right" }, + { AnimationEffect_MOVE_FROM_LOWERLEFT, "ooo-entrance-fly-in","from-bottom-left" }, + + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-fly-in-slow", "from-bottom" }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-fly-in-slow", "from-left" }, + { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-fly-in-slow", "from-right" }, + { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-fly-in-slow", "from-top" }, + + { AnimationEffect_MOVE_SHORT_FROM_LEFT, "ooo-entrance-peek-in","from-left" }, + { AnimationEffect_MOVE_SHORT_FROM_TOP, "ooo-entrance-peek-in","from-top" }, + { AnimationEffect_MOVE_SHORT_FROM_RIGHT, "ooo-entrance-peek-in","from-right" }, + { AnimationEffect_MOVE_SHORT_FROM_BOTTOM, "ooo-entrance-peek-in","from-bottom" }, + + { AnimationEffect_VERTICAL_LINES, "ooo-entrance-random-bars","horizontal" }, + { AnimationEffect_HORIZONTAL_LINES, "ooo-entrance-random-bars","vertical" }, + + { AnimationEffect_RANDOM, "ooo-entrance-random",0 }, + + { AnimationEffect_CLOSE_VERTICAL, "ooo-entrance-split","horizontal-in" }, + { AnimationEffect_CLOSE_HORIZONTAL, "ooo-entrance-split","vertical-in" }, + { AnimationEffect_OPEN_VERTICAL, "ooo-entrance-split","horizontal-out" }, + { AnimationEffect_OPEN_HORIZONTAL, "ooo-entrance-split","vertical-out" }, + + { AnimationEffect_VERTICAL_STRIPES, "ooo-entrance-venetian-blinds","horizontal" }, + { AnimationEffect_HORIZONTAL_STRIPES, "ooo-entrance-venetian-blinds","vertical" }, + + { AnimationEffect_FADE_FROM_LEFT, "ooo-entrance-wipe","from-left" }, + { AnimationEffect_FADE_FROM_TOP, "ooo-entrance-wipe","from-bottom" }, + { AnimationEffect_FADE_FROM_RIGHT, "ooo-entrance-wipe","from-right" }, + { AnimationEffect_FADE_FROM_BOTTOM, "ooo-entrance-wipe","from-top" }, + + { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-swivel","vertical" }, + { AnimationEffect_VERTICAL_ROTATE, "ooo-entrance-swivel","horizontal" }, + + { AnimationEffect_STRETCH_FROM_LEFT, "ooo-entrance-stretchy","from-left" }, + { AnimationEffect_STRETCH_FROM_UPPERLEFT, "ooo-entrance-stretchy","from-top-left" }, + { AnimationEffect_STRETCH_FROM_TOP, "ooo-entrance-stretchy","from-top" }, + { AnimationEffect_STRETCH_FROM_UPPERRIGHT, "ooo-entrance-stretchy","from-top-right" }, + { AnimationEffect_STRETCH_FROM_RIGHT, "ooo-entrance-stretchy","from-right" }, + { AnimationEffect_STRETCH_FROM_LOWERRIGHT, "ooo-entrance-stretchy","from-bottom-right" }, + { AnimationEffect_STRETCH_FROM_BOTTOM, "ooo-entrance-stretchy","from-bottom" }, + { AnimationEffect_STRETCH_FROM_LOWERLEFT, "ooo-entrance-stretchy","from-bottom-left" }, + + { AnimationEffect_HORIZONTAL_STRETCH, "ooo-entrance-expand", 0 }, + + { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel","1" }, + { AnimationEffect_COUNTERCLOCKWISE, "ooo-entrance-clock-wipe","counter-clockwise" }, + + { AnimationEffect_SPIRALIN_LEFT, "ooo-entrance-spiral-wipe", "from-top-left-clockwise" }, + { AnimationEffect_SPIRALIN_RIGHT, "ooo-entrance-spiral-wipe", "from-top-right-counter-clockwise" }, + { AnimationEffect_SPIRALOUT_LEFT, "ooo-entrance-spiral-wipe", "from-center-clockwise" }, + { AnimationEffect_SPIRALOUT_RIGHT, "ooo-entrance-spiral-wipe", "from-center-counter-clockwise" }, + + { AnimationEffect_WAVYLINE_FROM_LEFT, "ooo-entrance-snake-wipe","from-top-left-vertical" }, + { AnimationEffect_WAVYLINE_FROM_TOP, "ooo-entrance-snake-wipe","from-top-left-horizontal" }, + { AnimationEffect_WAVYLINE_FROM_RIGHT, "ooo-entrance-snake-wipe","from-bottom-right-vertical" }, + { AnimationEffect_WAVYLINE_FROM_BOTTOM, "ooo-entrance-snake-wipe","from-bottom-right-horizontal" }, + +// ooo 1.x exit effects + { AnimationEffect_HIDE, "ooo-exit-disappear",0 }, + { AnimationEffect_MOVE_TO_LEFT, "ooo-exit-fly-out", "from-right" }, + { AnimationEffect_MOVE_TO_TOP, "ooo-exit-fly-out", "from-bottom" }, + { AnimationEffect_MOVE_TO_RIGHT, "ooo-exit-fly-out", "from-left" }, + { AnimationEffect_MOVE_TO_BOTTOM, "ooo-exit-fly-out", "from-top" }, + { AnimationEffect_MOVE_TO_UPPERLEFT, "ooo-exit-fly-out", "from-top-right" }, + { AnimationEffect_MOVE_TO_UPPERRIGHT, "ooo-exit-fly-out", "from-top-left" }, + { AnimationEffect_MOVE_TO_LOWERRIGHT, "ooo-exit-fly-out", "from-bottom-left" }, + { AnimationEffect_MOVE_TO_LOWERLEFT, "ooo-exit-fly-out", "from-bottom-right" }, + { AnimationEffect_MOVE_SHORT_TO_LEFT, "ooo-exit-peek-out", "from-right" }, + { AnimationEffect_MOVE_SHORT_TO_UPPERLEFT, "ooo-exit-peek-out", "from-right" }, + { AnimationEffect_MOVE_SHORT_TO_TOP, "ooo-exit-peek-out", "from-bottom" }, + { AnimationEffect_MOVE_SHORT_TO_UPPERRIGHT, "ooo-exit-peek-out", "from-bottom" }, + { AnimationEffect_MOVE_SHORT_TO_RIGHT, "ooo-exit-peek-out", "from-left" }, + { AnimationEffect_MOVE_SHORT_TO_LOWERRIGHT, "ooo-exit-peek-out","from-left" }, + { AnimationEffect_MOVE_SHORT_TO_BOTTOM, "ooo-exit-peek-out", "from-top" }, + { AnimationEffect_MOVE_SHORT_TO_LOWERLEFT, "ooo-exit-peek-out", "from-top" }, + +// no matching in OOo 2.x + { AnimationEffect_MOVE_SHORT_FROM_UPPERLEFT, "ooo-entrance-peek-in","from-left" }, + { AnimationEffect_MOVE_SHORT_FROM_UPPERRIGHT, "ooo-entrance-peek-in","from-top" }, + { AnimationEffect_MOVE_SHORT_FROM_LOWERRIGHT, "ooo-entrance-peek-in","from-right" }, + { AnimationEffect_MOVE_SHORT_FROM_LOWERLEFT, "ooo-entrance-peek-in","from-bottom" }, + { AnimationEffect_LASER_FROM_LEFT, "ooo-entrance-fly-in","from-left" }, + { AnimationEffect_LASER_FROM_TOP, "ooo-entrance-fly-in","from-top" }, + { AnimationEffect_LASER_FROM_RIGHT, "ooo-entrance-fly-in","from-right" }, + { AnimationEffect_LASER_FROM_BOTTOM, "ooo-entrance-fly-in","from-bottom" }, + { AnimationEffect_LASER_FROM_UPPERLEFT, "ooo-entrance-fly-in","from-top-left" }, + { AnimationEffect_LASER_FROM_UPPERRIGHT, "ooo-entrance-fly-in","from-top-right" }, + { AnimationEffect_LASER_FROM_LOWERLEFT, "ooo-entrance-fly-in","from-bottom-left" }, + { AnimationEffect_LASER_FROM_LOWERRIGHT, "ooo-entrance-fly-in","from-bottom-right" }, + +// no matching in OOo 1.x + + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-circle", "in" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-circle", "out" }, + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-diamond", "in" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-diamond", "out" }, + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-plus", "in" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-plus", "out" }, + { AnimationEffect_CLOCKWISE, "ooo-entrance-wedge", 0 }, + { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "2" }, + { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "3" }, + { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "4" }, + { AnimationEffect_CLOCKWISE, "ooo-entrance-wheel", "8" }, + + { AnimationEffect_MOVE_FROM_RIGHT, "ooo-entrance-boomerang", 0 }, + { AnimationEffect_MOVE_FROM_UPPERRIGHT, "ooo-entrance-bounce", 0 }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-curve-up", 0 }, + { AnimationEffect_MOVE_FROM_TOP, "ooo-entrance-float", 0 }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-glide", 0 }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-magnify", 0 }, + { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-pinwheel", 0 }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-breaks", 0 }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-sling", 0 }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-spiral-in", 0 }, + { AnimationEffect_MOVE_FROM_LEFT, "ooo-entrance-thread", 0 }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-ascend", 0 }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-center-revolve", 0 }, + { AnimationEffect_APPEAR, "ooo-entrance-compress", 0 }, + { AnimationEffect_MOVE_SHORT_FROM_TOP, "ooo-entrance-descend", 0 }, + { AnimationEffect_MOVE_SHORT_FROM_LEFT, "ooo-entrance-ease-in", 0 }, + { AnimationEffect_MOVE_FROM_BOTTOM, "ooo-entrance-rise-up", 0 }, + { AnimationEffect_HORIZONTAL_ROTATE, "ooo-entrance-spin-in", 0 }, + { AnimationEffect_STRETCH_FROM_LEFT, "ooo-entrance-stretchy", "across" }, + { AnimationEffect_STRETCH_FROM_TOP, "ooo-entrance-stretchy", "downward" }, + + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in-slightly" }, + { AnimationEffect_FADE_FROM_CENTER, "ooo-entrance-zoom","in-from-screen-center" }, + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out" }, + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out-slightly" }, + { AnimationEffect_FADE_TO_CENTER, "ooo-entrance-zoom","out-from-screen-center" }, + + { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in", 0 }, + { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in-and-zoom", 0 }, + { AnimationEffect_DISSOLVE, "ooo-entrance-fade-in-and-swivel", 0 }, + + // still open (no matching effect: AnimationEffect_ZOOM_IN_FROM_*, + // AnimationEffect_ZOOM_OUT_FROM_*, AnimationEffect_PATH + + { AnimationEffect_NONE, 0, 0 } +}; + +EffectSequence::iterator ImplFindEffect( MainSequencePtr& pMainSequence, const Reference< XShape >& rShape, sal_Int16 nSubItem ) +{ + EffectSequence::iterator aIter; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( (pEffect->getTargetShape() == rShape) && (pEffect->getTargetSubItem() == nSubItem) ) + break; + } + + return aIter; +} + +static bool implIsInsideGroup( SdrObject* pObj ) +{ + return pObj && pObj->GetObjList() && pObj->GetObjList()->GetUpList(); +} + +void EffectMigration::SetAnimationEffect( SvxShape* pShape, AnimationEffect eEffect ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + OUString aPresetId; + OUString aPresetSubType; + + if( !ConvertAnimationEffect( eEffect, aPresetId, aPresetSubType ) ) + { + DBG_ERROR( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" ); + return; + } + + const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets(); + + CustomAnimationPresetPtr pPreset( rPresets.getEffectDescriptor( aPresetId ) ); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + if( pPreset.get() && pMainSequence.get() ) + { + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIterOnlyBackground( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) ); + EffectSequence::iterator aIterAsWhole( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::AS_WHOLE ) ); + const EffectSequence::iterator aEnd( pMainSequence->getEnd() ); + + bool bEffectCreated = false; + + if( (aIterOnlyBackground == aEnd) && (aIterAsWhole == aEnd) ) + { + // check if there is already an text effect for this shape + EffectSequence::iterator aIterOnlyText( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) ); + if( aIterOnlyText != aEnd ) + { + // check if this is an animation text group + sal_Int32 nGroupId = (*aIterOnlyText)->getGroupId(); + if( nGroupId >= 0 ) + { + CustomAnimationTextGroupPtr pGroup = pMainSequence->findGroup( nGroupId ); + if( pGroup.get() ) + { + // add an effect to animate the shape + pMainSequence->setAnimateForm( pGroup, true ); + + // find this effect + EffectSequence::iterator aIter( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) ); + + if( aIter != aEnd ) + { + if( ((*aIter)->getPresetId() != aPresetId) || + ((*aIter)->getPresetSubType() != aPresetSubType) ) + { + (*aIter)->replaceNode( pPreset->create( aPresetSubType ) ); + pMainSequence->rebuild(); + bEffectCreated = true; + } + } + } + } + } + + if( !bEffectCreated ) + { + // if there is not yet an effect that target this shape, we generate one + // we insert the shape effect before it + Reference< XAnimationNode > xNode( pPreset->create( aPresetSubType ) ); + DBG_ASSERT( xNode.is(), "EffectMigration::SetAnimationEffect(), could not create preset!" ); + if( xNode.is() ) + { + CustomAnimationEffectPtr pEffect( new CustomAnimationEffect( xNode ) ); + pEffect->setTarget( makeAny( xShape ) ); + SdPage* pPage = dynamic_cast< SdPage* >( pObj->GetPage() ); + const bool bManual = (pPage == 0) || (pPage->GetPresChange() == PRESCHANGE_MANUAL); + if( !bManual ) + pEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS ); + + pMainSequence->append( pEffect ); + + if( ( pObj->GetObjInventor() == SdrInventor ) && ( pObj->GetObjIdentifier() == OBJ_OUTLINETEXT ) ) + { + // special case for outline text, effects are always mapped to text group effect + pMainSequence-> + createTextGroup( pEffect, 10, bManual ? -1 : 0.0, sal_False, sal_False ); + } + } + } + } + else + { + // if there is already an effect targeting this shape + // just replace it + CustomAnimationEffectPtr pEffect; + if( aIterAsWhole != aEnd ) + { + pEffect = (*aIterAsWhole); + } + else + { + pEffect = (*aIterOnlyBackground); + } + + if( pEffect.get() ) + { + if( (pEffect->getPresetId() != aPresetId) || + (pEffect->getPresetSubType() != aPresetSubType) ) + { + pMainSequence->replace( pEffect, pPreset, aPresetSubType ); + } + } + } + } +} + +// -------------------------------------------------------------------- + +AnimationEffect EffectMigration::GetAnimationEffect( SvxShape* pShape ) +{ + OUString aPresetId; + OUString aPresetSubType; + + SdrObject* pObj = pShape->GetSdrObject(); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + if( pMainSequence.get() ) + { + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( pEffect->getTargetShape() == xShape ) + { + if( (pEffect->getTargetSubItem() == ShapeAnimationSubType::ONLY_BACKGROUND) || + (pEffect->getTargetSubItem() == ShapeAnimationSubType::AS_WHOLE)) + { + if( pEffect->getDuration() != 0.1 ) // ignore appear effects created from old text effect import + { + aPresetId = (*aIter)->getPresetId(); + aPresetSubType = (*aIter)->getPresetSubType(); + break; + } + } + } + } + } + + // now find old effect + AnimationEffect eEffect = AnimationEffect_NONE; + + if( !ConvertPreset( aPresetId, &aPresetSubType, eEffect ) ) + ConvertPreset( aPresetId, 0, eEffect ); + + return eEffect; +} + + +// -------------------------------------------------------------------- + +void EffectMigration::SetTextAnimationEffect( SvxShape* pShape, AnimationEffect eEffect ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + // first map the deprecated AnimationEffect to a preset and subtype + OUString aPresetId; + OUString aPresetSubType; + + if( !ConvertAnimationEffect( eEffect, aPresetId, aPresetSubType ) ) + { + DBG_ERROR( "sd::EffectMigration::SetAnimationEffect(), no mapping for given AnimationEffect value" ); + return; + } + + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( pObj ); + + // ignore old text effects on shape without text + if( (pTextObj == 0) || (!pTextObj->HasText()) ) + return; + + const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets(); + + // create an effect from this preset + CustomAnimationPresetPtr pPreset( rPresets.getEffectDescriptor( aPresetId ) ); + + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + if( pPreset.get() && pMainSequence.get() ) + { + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIterOnlyText( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) ); + const EffectSequence::iterator aEnd( pMainSequence->getEnd() ); + + CustomAnimationTextGroupPtr pGroup; + + // is there already an animation text group for this shape? + if( aIterOnlyText != aEnd ) + { + const sal_Int32 nGroupId = (*aIterOnlyText)->getGroupId(); + if( nGroupId >= 0 ) + pGroup = pMainSequence->findGroup( nGroupId ); + } + + // if there is not yet a group, create it + if( pGroup.get() == 0 ) + { + CustomAnimationEffectPtr pShapeEffect; + + EffectSequence::iterator aIterOnlyBackground( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_BACKGROUND ) ); + if( aIterOnlyBackground != aEnd ) + { + pShapeEffect = (*aIterOnlyBackground); + } + else + { + EffectSequence::iterator aIterAsWhole( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::AS_WHOLE ) ); + if( aIterAsWhole != aEnd ) + { + pShapeEffect = (*aIterAsWhole); + } + else + { + OUString aEmpty; + CustomAnimationPresetPtr pShapePreset( rPresets.getEffectDescriptor( OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo-entrance-appear" ) ) ) ); + + Reference< XAnimationNode > xNode( pPreset->create( aEmpty ) ); + DBG_ASSERT( xNode.is(), "EffectMigration::SetTextAnimationEffect(), could not create preset!" ); + if( xNode.is() ) + { + pShapeEffect.reset( new CustomAnimationEffect( xNode ) ); + pShapeEffect->setTarget( makeAny( xShape ) ); + pShapeEffect->setDuration( 0.1 ); + pMainSequence->append( pShapeEffect ); + + SdPage* pPage = dynamic_cast< SdPage* >( pObj->GetPage() ); + if( pPage && pPage->GetPresChange() != PRESCHANGE_MANUAL ) + pShapeEffect->setNodeType( EffectNodeType::AFTER_PREVIOUS ); + } + } + } + + if( pShapeEffect.get() ) + { + SdPage* pPage = dynamic_cast< SdPage* >( pObj->GetPage() ); + const bool bManual = (pPage == 0) || (pPage->GetPresChange() == PRESCHANGE_MANUAL); + + // now create effects for each paragraph + pGroup = + pMainSequence-> + createTextGroup( pShapeEffect, 10, bManual ? -1 : 0.0, sal_True, sal_False ); + } + } + + if( pGroup.get() != 0 ) + { + const bool bLaserEffect = (eEffect >= AnimationEffect_LASER_FROM_LEFT) && (eEffect <= AnimationEffect_LASER_FROM_LOWERRIGHT); + + // now we have a group, so check if all effects are same as we like to have them + const EffectSequence& rEffects = pGroup->getEffects(); + + EffectSequence::const_iterator aIter; + for( aIter = rEffects.begin(); aIter != rEffects.end(); ++aIter ) + { + // only work on paragraph targets + if( (*aIter)->getTarget().getValueType() == ::getCppuType((const ParagraphTarget*)0) ) + { + if( ((*aIter)->getPresetId() != aPresetId) || + ((*aIter)->getPresetSubType() != aPresetSubType) ) + { + (*aIter)->replaceNode( pPreset->create( aPresetSubType ) ); + } + + if( bLaserEffect ) + { + (*aIter)->setIterateType( TextAnimationType::BY_LETTER ); + (*aIter)->setIterateInterval( 0.5 );// TODO: + // Determine + // interval + // according + // to + // total + // effect + // duration + } + } + } + } + pMainSequence->rebuild(); + } +} + +// -------------------------------------------------------------------- + +AnimationEffect EffectMigration::GetTextAnimationEffect( SvxShape* pShape ) +{ + OUString aPresetId; + OUString aPresetSubType; + + SdrObject* pObj = pShape->GetSdrObject(); + if( pObj ) + { + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + if( pMainSequence.get() ) + { + const Reference< XShape > xShape( pShape ); + EffectSequence::iterator aIter( ImplFindEffect( pMainSequence, xShape, ShapeAnimationSubType::ONLY_TEXT ) ); + if( aIter != pMainSequence->getEnd() ) + { + aPresetId = (*aIter)->getPresetId(); + aPresetSubType = (*aIter)->getPresetSubType(); + } + } + } + + // now find old effect + AnimationEffect eEffect = AnimationEffect_NONE; + + if( !ConvertPreset( aPresetId, &aPresetSubType, eEffect ) ) + ConvertPreset( aPresetId, 0, eEffect ); + + return eEffect; +} + +// -------------------------------------------------------------------- + +bool EffectMigration::ConvertPreset( const OUString& rPresetId, const OUString* pPresetSubType, AnimationEffect& rEffect ) +{ + rEffect = AnimationEffect_NONE; + if( rPresetId.getLength() ) + { + // first try a match for preset id and subtype + deprecated_AnimationEffect_conversion_table_entry* p = deprecated_AnimationEffect_conversion_table; + while( p->mpPresetId ) + { + if( rPresetId.equalsAscii( p->mpPresetId ) && + (( p->mpPresetSubType == 0 ) || + ( pPresetSubType == 0) || + ( pPresetSubType->equalsAscii( p->mpPresetSubType )) ) ) + { + rEffect = p->meEffect; + return true; + } + p++; + } + return false; + } + else + { + // empty preset id means AnimationEffect_NONE + return true; + } +} + +// -------------------------------------------------------------------- + +bool EffectMigration::ConvertAnimationEffect( const AnimationEffect& rEffect, OUString& rPresetId, OUString& rPresetSubType ) +{ + deprecated_AnimationEffect_conversion_table_entry* p = deprecated_AnimationEffect_conversion_table; + while( p->mpPresetId ) + { + if( p->meEffect == rEffect ) + { + rPresetId = OUString::createFromAscii( p->mpPresetId ); + rPresetSubType = OUString::createFromAscii( p->mpPresetSubType ); + return true; + } + p++; + } + + return false; +} + +// -------------------------------------------------------------------- + +double EffectMigration::ConvertAnimationSpeed( AnimationSpeed eSpeed ) +{ + double fDuration; + switch( eSpeed ) + { + case AnimationSpeed_SLOW: fDuration = 2.0; break; + case AnimationSpeed_FAST: fDuration = 0.5; break; + default: + fDuration = 1.0; break; + } + return fDuration; +} +// -------------------------------------------------------------------- + +void EffectMigration::SetAnimationSpeed( SvxShape* pShape, AnimationSpeed eSpeed ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + double fDuration = ConvertAnimationSpeed( eSpeed ); + + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + bool bNeedRebuild = false; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( pEffect->getTargetShape() == xShape ) + { + if( pEffect->getDuration() != 0.1 ) + pEffect->setDuration( fDuration ); + bNeedRebuild = true; + } + } + + if( bNeedRebuild ) + pMainSequence->rebuild(); +} + +// -------------------------------------------------------------------- + +AnimationSpeed EffectMigration::GetAnimationSpeed( SvxShape* pShape ) +{ + SdrObject* pObj = pShape->GetSdrObject(); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + + double fDuration = 1.0; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( pEffect->getTargetShape() == xShape ) + { + if( pEffect->getDuration() != 0.1 ) + { + fDuration = pEffect->getDuration(); + break; + } + } + } + + return ConvertDuration( fDuration ); +} + +// -------------------------------------------------------------------- + +AnimationSpeed EffectMigration::ConvertDuration( double fDuration ) +{ + AnimationSpeed eSpeed; + + if( fDuration < 1.0 ) + eSpeed = AnimationSpeed_FAST; + else if( fDuration > 1.5 ) + eSpeed = AnimationSpeed_SLOW; + else + eSpeed = AnimationSpeed_MEDIUM; + + return eSpeed; +} + +// -------------------------------------------------------------------- + +void EffectMigration::SetDimColor( SvxShape* pShape, sal_Int32 nColor ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + bool bNeedRebuild = false; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( pEffect->getTargetShape() == xShape ) + { + pEffect->setHasAfterEffect( true ); + pEffect->setDimColor( makeAny( nColor ) ); + pEffect->setAfterEffectOnNext( true ); + bNeedRebuild = true; + } + } + + if( bNeedRebuild ) + pMainSequence->rebuild(); +} + +// -------------------------------------------------------------------- + +sal_Int32 EffectMigration::GetDimColor( SvxShape* pShape ) +{ + sal_Int32 nColor = 0; + if( pShape ) + { + SdrObject* pObj = pShape->GetSdrObject(); + if( pObj && pObj->GetPage() ) + { + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + EffectSequence::iterator aIter; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( (pEffect->getTargetShape() == xShape) && + pEffect->getDimColor().hasValue() && + pEffect->hasAfterEffect()) + { + pEffect->getDimColor() >>= nColor; + break; + } + } + } + } + + return nColor; +} + +// -------------------------------------------------------------------- + + +void EffectMigration::SetDimHide( SvxShape* pShape, sal_Bool bDimHide ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + Any aEmpty; + + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + bool bNeedRebuild = false; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( pEffect->getTargetShape() == xShape ) + { + pEffect->setHasAfterEffect( bDimHide ? true : false ); + if( bDimHide ) + pEffect->setDimColor( aEmpty ); + pEffect->setAfterEffectOnNext( false ); + bNeedRebuild = true; + } + } + + if( bNeedRebuild ) + pMainSequence->rebuild(); +} + +// -------------------------------------------------------------------- + +sal_Bool EffectMigration::GetDimHide( SvxShape* pShape ) +{ + sal_Bool bRet = sal_False; + if( pShape ) + { + SdrObject* pObj = pShape->GetSdrObject(); + if( pObj && pObj->GetPage() ) + { + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( pEffect->getTargetShape() == xShape ) + { + bRet = pEffect->hasAfterEffect() && + !pEffect->getDimColor().hasValue() && + (!pEffect->IsAfterEffectOnNext()); + break; + } + } + } + } + + return bRet; +} + +// -------------------------------------------------------------------- + +void EffectMigration::SetDimPrevious( SvxShape* pShape, sal_Bool bDimPrevious ) +{ + DBG_ASSERT( pShape && pShape->GetSdrObject() && pShape->GetSdrObject()->GetPage(), + "sd::EffectMigration::SetAnimationEffect(), invalid argument!" ); + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + if( implIsInsideGroup( pObj ) ) + return; + + Any aColor; + + if( bDimPrevious ) + aColor <<= (sal_Int32)COL_LIGHTGRAY; + + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + bool bNeedRebuild = false; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( pEffect->getTargetShape() == xShape ) + { + pEffect->setHasAfterEffect( bDimPrevious ); + if( !bDimPrevious || !pEffect->getDimColor().hasValue() ) + pEffect->setDimColor( aColor ); + pEffect->setAfterEffectOnNext( true ); + bNeedRebuild = true; + } + } + + if( bNeedRebuild ) + pMainSequence->rebuild(); +} + +// -------------------------------------------------------------------- + +sal_Bool EffectMigration::GetDimPrevious( SvxShape* pShape ) +{ + sal_Bool bRet = sal_False; + if( pShape ) + { + SdrObject* pObj = pShape->GetSdrObject(); + if( pObj && pObj->GetPage() ) + { + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( pEffect->getTargetShape() == xShape ) + { + bRet = pEffect->hasAfterEffect() && + pEffect->getDimColor().hasValue() && + pEffect->IsAfterEffectOnNext(); + break; + } + } + } + } + + return bRet; +} + +// -------------------------------------------------------------------- + +void EffectMigration::SetPresentationOrder( SvxShape* pShape, sal_Int32 nNewPos ) +{ + if( !pShape || !pShape->GetSdrObject() || !pShape->GetSdrObject()->GetPage() ) + return; + + SdrObject* pObj = pShape->GetSdrObject(); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + EffectSequence& rSequence = pMainSequence->getSequence(); + sal_Int32 nPos; + sal_Int32 nCurrentPos = -1; + std::vector< std::vector< EffectSequence::iterator > > aEffectVector(1); + + if( !rSequence.empty() ) + { + Reference< XShape > xThis( pShape ); + Reference< XShape > xCurrent; + + EffectSequence::iterator aIter( rSequence.begin() ); + EffectSequence::iterator aEnd( rSequence.end() ); + for( nPos = 0; aIter != aEnd; ++aIter ) + { + CustomAnimationEffectPtr pEffect = (*aIter); + + if( !xCurrent.is() ) + { + xCurrent = pEffect->getTargetShape(); + } + else if( pEffect->getTargetShape() != xCurrent ) + { + nPos++; + xCurrent = pEffect->getTargetShape(); + aEffectVector.resize( nPos+1 ); + } + + // is this the first effect for xThis shape? + if(( nCurrentPos == -1 ) && ( xCurrent == xThis ) ) + { + nCurrentPos = nPos; + } + + aEffectVector[nPos].push_back( aIter ); + } + } + + // check if there is at least one effect for xThis + if( nCurrentPos == -1 ) + { + DBG_ERROR("sd::EffectMigration::SetPresentationOrder() failed cause this shape has no effect" ); + return; + } + + // check trivial case + if( nCurrentPos != nNewPos ) + { + std::vector< CustomAnimationEffectPtr > aEffects; + + std::vector< EffectSequence::iterator >::iterator aIter( aEffectVector[nCurrentPos].begin() ); + std::vector< EffectSequence::iterator >::iterator aEnd( aEffectVector[nCurrentPos].end() ); + while( aIter != aEnd ) + { + aEffects.push_back( (*(*aIter)) ); + rSequence.erase( (*aIter++) ); + } + + if( nNewPos > nCurrentPos ) + nNewPos++; + + std::vector< CustomAnimationEffectPtr >::iterator aTempIter( aEffects.begin() ); + std::vector< CustomAnimationEffectPtr >::iterator aTempEnd( aEffects.end() ); + + if( nNewPos == (sal_Int32)aEffectVector.size() ) + { + while( aTempIter != aTempEnd ) + { + rSequence.push_back( (*aTempIter++) ); + } + } + else + { + EffectSequence::iterator aPos( aEffectVector[nNewPos][0] ); + while( aTempIter != aTempEnd ) + { + rSequence.insert( aPos, (*aTempIter++) ); + } + } + } +} + +// -------------------------------------------------------------------- + +/** Returns the position of the given SdrObject in the Presentation order. + * This function returns -1 if the SdrObject is not in the Presentation order + * or if its the path-object. + */ +sal_Int32 EffectMigration::GetPresentationOrder( SvxShape* pShape ) +{ + sal_Int32 nPos = -1, nFound = -1; + + SdrObject* pObj = pShape->GetSdrObject(); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + EffectSequence& rSequence = pMainSequence->getSequence(); + + Reference< XShape > xThis( pShape ); + Reference< XShape > xCurrent; + + EffectSequence::iterator aIter( rSequence.begin() ); + EffectSequence::iterator aEnd( rSequence.end() ); + for( ; aIter != aEnd; ++aIter ) + { + CustomAnimationEffectPtr pEffect = (*aIter); + + if( !xCurrent.is() || pEffect->getTargetShape() != xCurrent ) + { + nPos++; + xCurrent = pEffect->getTargetShape(); + + // is this the first effect for xThis shape? + if( xCurrent == xThis ) + { + nFound = nPos; + break; + } + } + } + + return nFound; +} + +// -------------------------------------------------------------------- + +void EffectMigration::UpdateSoundEffect( SvxShape* pShape, SdAnimationInfo* pInfo ) +{ + if( pInfo ) + { + SdrObject* pObj = pShape->GetSdrObject(); + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + bool bNeedRebuild = false; + + OUString aSoundFile; + if( pInfo->mbSoundOn ) + aSoundFile = pInfo->maSoundFile; + + for( aIter = pMainSequence->getBegin(); aIter != pMainSequence->getEnd(); ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( pEffect->getTargetShape() == xShape ) + { + if( aSoundFile.getLength() ) + { + pEffect->createAudio( makeAny( aSoundFile ) ); + } + else + { + pEffect->removeAudio(); + } + bNeedRebuild = true; + } + } + + if( bNeedRebuild ) + pMainSequence->rebuild(); + } +} + +// -------------------------------------------------------------------- + +OUString EffectMigration::GetSoundFile( SvxShape* pShape ) +{ + OUString aSoundFile; + + if( pShape ) + { + SdrObject* pObj = pShape->GetSdrObject(); + if( pObj && pObj->GetPage() ) + { + sd::MainSequencePtr pMainSequence = static_cast<SdPage*>(pObj->GetPage())->getMainSequence(); + + const Reference< XShape > xShape( pShape ); + + EffectSequence::iterator aIter; + + for( aIter = pMainSequence->getBegin(); + (aSoundFile.getLength() == 0) && (aIter != pMainSequence->getEnd()); + ++aIter ) + { + CustomAnimationEffectPtr pEffect( (*aIter) ); + if( pEffect->getTargetShape() == xShape ) + { + if( pEffect->getAudio().is() ) + pEffect->getAudio()->getSource() >>= aSoundFile; + } + } + } + } + return aSoundFile; +} + +// -------------------------------------------------------------------- + +sal_Bool EffectMigration::GetSoundOn( SvxShape* pShape ) +{ + return GetSoundFile( pShape ).getLength() != 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/PageListWatcher.cxx b/sd/source/core/PageListWatcher.cxx new file mode 100644 index 000000000000..7e77b408a66f --- /dev/null +++ b/sd/source/core/PageListWatcher.cxx @@ -0,0 +1,224 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include "PageListWatcher.hxx" + +#include "sdpage.hxx" +#include <tools/debug.hxx> +#include <svx/svdmodel.hxx> + +////////////////////////////////////////////////////////////////////////////// +// #109538# + +void ImpPageListWatcher::ImpRecreateSortedPageListOnDemand() +{ + // clear vectors + maPageVectorStandard.clear(); + maPageVectorNotes.clear(); + mpHandoutPage = 0L; + + // build up vectors again + const sal_uInt32 nPageCount(ImpGetPageCount()); + + for(sal_uInt32 a(0L); a < nPageCount; a++) + { + SdPage* pCandidate = ImpGetPage(a); + DBG_ASSERT(pCandidate, "ImpPageListWatcher::ImpRecreateSortedPageListOnDemand: Invalid PageList in Model (!)"); + + switch(pCandidate->GetPageKind()) + { + case PK_STANDARD: + { + maPageVectorStandard.push_back(pCandidate); + break; + } + case PK_NOTES: + { + maPageVectorNotes.push_back(pCandidate); + break; + } + case PK_HANDOUT: + { + DBG_ASSERT(!mpHandoutPage, "ImpPageListWatcher::ImpRecreateSortedPageListOnDemand: Two Handout pages in PageList of Model (!)"); + mpHandoutPage = pCandidate; + break; + } + } + } + + // set to valid + mbPageListValid = sal_True; +} + +ImpPageListWatcher::ImpPageListWatcher(const SdrModel& rModel) +: mrModel(rModel), + mpHandoutPage(0L), + mbPageListValid(sal_False) +{ +} + +ImpPageListWatcher::~ImpPageListWatcher() +{ +} + +SdPage* ImpPageListWatcher::GetSdPage(PageKind ePgKind, sal_uInt32 nPgNum) +{ + SdPage* pRetval(0L); + + if(!mbPageListValid) + { + ImpRecreateSortedPageListOnDemand(); + } + + switch(ePgKind) + { + case PK_STANDARD: + { + if( nPgNum < (sal_uInt32)maPageVectorStandard.size() ) + pRetval = maPageVectorStandard[nPgNum]; + else + { + DBG_ASSERT(nPgNum <= maPageVectorStandard.size(), + "ImpPageListWatcher::GetSdPage(PK_STANDARD): access out of range"); + DBG_WARNING2 (" %d > %d", + nPgNum, nPgNum<maPageVectorStandard.size()); + } + break; + } + case PK_NOTES: + { + if( nPgNum < (sal_uInt32)maPageVectorNotes.size() ) + pRetval = maPageVectorNotes[nPgNum]; + else + { + DBG_ASSERT(nPgNum <= maPageVectorNotes.size(), + "ImpPageListWatcher::GetSdPage(PK_NOTES): access out of range"); + DBG_WARNING2(" %d > %d", + nPgNum, nPgNum<maPageVectorNotes.size()); + } + break; + } + case PK_HANDOUT: + { +// #11420# for models used to transfer drawing shapes via clipboard its ok to not have a handout page + DBG_ASSERT(nPgNum == 0L, "ImpPageListWatcher::GetSdPage: access to non existing handout page (!)"); + if (nPgNum == 0) + pRetval = mpHandoutPage; + else + { + DBG_ASSERT(nPgNum == 0L, + "ImpPageListWatcher::GetSdPage: access to non existing handout page (!)"); + } + break; + } + } + + return pRetval; +} + +sal_uInt32 ImpPageListWatcher::GetSdPageCount(PageKind ePgKind) +{ + sal_uInt32 nRetval(0L); + + if(!mbPageListValid) + { + ImpRecreateSortedPageListOnDemand(); + } + + switch(ePgKind) + { + case PK_STANDARD: + { + nRetval = maPageVectorStandard.size(); + break; + } + case PK_NOTES: + { + nRetval = maPageVectorNotes.size(); + break; + } + case PK_HANDOUT: + { + if(mpHandoutPage) + { + nRetval = 1L; + } + + break; + } + } + + return nRetval; +} + +////////////////////////////////////////////////////////////////////////////// + +sal_uInt32 ImpDrawPageListWatcher::ImpGetPageCount() const +{ + return (sal_uInt32)mrModel.GetPageCount(); +} + +SdPage* ImpDrawPageListWatcher::ImpGetPage(sal_uInt32 nIndex) const +{ + return (SdPage*)mrModel.GetPage((sal_uInt16)nIndex); +} + +ImpDrawPageListWatcher::ImpDrawPageListWatcher(const SdrModel& rModel) +: ImpPageListWatcher(rModel) +{ +} + +ImpDrawPageListWatcher::~ImpDrawPageListWatcher() +{ +} + +////////////////////////////////////////////////////////////////////////////// + +sal_uInt32 ImpMasterPageListWatcher::ImpGetPageCount() const +{ + return (sal_uInt32)mrModel.GetMasterPageCount(); +} + +SdPage* ImpMasterPageListWatcher::ImpGetPage(sal_uInt32 nIndex) const +{ + return (SdPage*)mrModel.GetMasterPage((sal_uInt16)nIndex); +} + +ImpMasterPageListWatcher::ImpMasterPageListWatcher(const SdrModel& rModel) +: ImpPageListWatcher(rModel) +{ +} + +ImpMasterPageListWatcher::~ImpMasterPageListWatcher() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/PageListWatcher.hxx b/sd/source/core/PageListWatcher.hxx new file mode 100644 index 000000000000..ae6b1235abd9 --- /dev/null +++ b/sd/source/core/PageListWatcher.hxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef PAGE_LIST_WATCHER_HXX +#define PAGE_LIST_WATCHER_HXX + +#include "pres.hxx" +#include <sal/types.h> +#include <vector> + +class SdPage; +class SdrModel; + +/** Maintain a map of page indices to page objects for faster access that + remains valid during deletions and insertions of pages (#109538#). +*/ +class ImpPageListWatcher +{ +protected: + // typedefs for a vector of SdPages + typedef ::std::vector< SdPage* > SdPageVector; + + const SdrModel& mrModel; + + SdPageVector maPageVectorStandard; + SdPageVector maPageVectorNotes; + SdPage* mpHandoutPage; + + sal_Bool mbPageListValid; + + void ImpRecreateSortedPageListOnDemand(); + virtual sal_uInt32 ImpGetPageCount() const = 0; + + /** Return the page with the given index. + @param nIndex + When given an invalid index then NULL is returned. + */ + virtual SdPage* ImpGetPage (sal_uInt32 nIndex) const = 0; + +public: + ImpPageListWatcher(const SdrModel& rModel); + virtual ~ImpPageListWatcher(); + + void Invalidate() { mbPageListValid = sal_False; } + SdPage* GetSdPage(PageKind ePgKind, sal_uInt32 nPgNum = 0L); + sal_uInt32 GetSdPageCount(PageKind ePgKind); +}; + +////////////////////////////////////////////////////////////////////////////// + +class ImpDrawPageListWatcher : public ImpPageListWatcher +{ +protected: + virtual sal_uInt32 ImpGetPageCount() const; + virtual SdPage* ImpGetPage(sal_uInt32 nIndex) const; + +public: + ImpDrawPageListWatcher(const SdrModel& rModel); + virtual ~ImpDrawPageListWatcher(); +}; + +////////////////////////////////////////////////////////////////////////////// + +class ImpMasterPageListWatcher : public ImpPageListWatcher +{ +protected: + virtual sal_uInt32 ImpGetPageCount() const; + virtual SdPage* ImpGetPage(sal_uInt32 nIndex) const; + +public: + ImpMasterPageListWatcher(const SdrModel& rModel); + virtual ~ImpMasterPageListWatcher(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/TransitionPreset.cxx b/sd/source/core/TransitionPreset.cxx new file mode 100644 index 000000000000..9e01646ccee7 --- /dev/null +++ b/sd/source/core/TransitionPreset.cxx @@ -0,0 +1,258 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <com/sun/star/animations/XTimeContainer.hpp> +#include <com/sun/star/animations/XTransitionFilter.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/util/XMacroExpander.hpp> +#include <com/sun/star/animations/AnimationNodeType.hpp> +#include <vcl/svapp.hxx> +#include <osl/mutex.hxx> +#include <tools/urlobj.hxx> +#include <unotools/streamwrap.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/pathoptions.hxx> +#include <tools/stream.hxx> + +#include <rtl/uri.hxx> +#include <tools/debug.hxx> + +#include <TransitionPreset.hxx> +#include <unotools/ucbstreamhelper.hxx> + +#include <algorithm> + +#include "sdpage.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::animations; + +using ::rtl::OUString; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::container::XEnumerationAccess; +using ::com::sun::star::container::XEnumeration; +using ::com::sun::star::beans::NamedValue; + +namespace sd { + +extern Reference< XAnimationNode > implImportEffects( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rPath ); +extern void implImportLabels( const Reference< XMultiServiceFactory >& xConfigProvider, const OUString& rNodePath, UStringMap& rStringMap ); + +TransitionPreset::TransitionPreset( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) +{ + // first locate preset id + Sequence< NamedValue > aUserData( xNode->getUserData() ); + sal_Int32 nLength = aUserData.getLength(); + const NamedValue* p = aUserData.getConstArray(); + while( nLength-- ) + { + if( p->Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "preset-id" ) ) ) + { + p->Value >>= maPresetId; + break; + } + } + + // second, locate transition filter element + Reference< XEnumerationAccess > xEnumerationAccess( xNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + Reference< XTransitionFilter > xTransition( xEnumeration->nextElement(), UNO_QUERY_THROW ); + + mnTransition = xTransition->getTransition(); + mnSubtype = xTransition->getSubtype(); + mbDirection = xTransition->getDirection(); + mnFadeColor = xTransition->getFadeColor(); +} + +bool TransitionPreset::importTransitionsFile( TransitionPresetList& rList, + Reference< XMultiServiceFactory >& xServiceFactory, + UStringMap& rTransitionNameMape, + String aURL ) +{ + // import transition presets + Reference< XAnimationNode > xAnimationNode; + + try { + xAnimationNode = implImportEffects( xServiceFactory, aURL ); + Reference< XEnumerationAccess > xEnumerationAccess( xAnimationNode, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_QUERY_THROW ); + + while( xEnumeration->hasMoreElements() ) + { + Reference< XAnimationNode > xChildNode( xEnumeration->nextElement(), UNO_QUERY_THROW ); + if( xChildNode->getType() == AnimationNodeType::PAR ) + { + // create it + TransitionPresetPtr pPreset( new TransitionPreset( xChildNode ) ); + + // name it + OUString aPresetId( pPreset->getPresetId() ); + if( aPresetId.getLength() ) + { + UStringMap::const_iterator aIter( rTransitionNameMape.find( aPresetId ) ); + if( aIter != rTransitionNameMape.end() ) + pPreset->maUIName = (*aIter).second; + + // add it + rList.push_back( pPreset ); + } + } + else + { + DBG_ERROR( "sd::TransitionPreset::importTransitionPresetList(), missformed xml configuration file, giving up!" ); + break; + } + } + } catch( Exception& ) { + return false; + } + + return true; +} + +#define EXPAND_PROTOCOL "vnd.sun.star.expand:" + +bool TransitionPreset::importTransitionPresetList( TransitionPresetList& rList ) +{ + bool bRet = false; + + try + { + // Get service factory + Reference< XMultiServiceFactory > xServiceFactory( comphelper::getProcessServiceFactory() ); + DBG_ASSERT( xServiceFactory.is(), "sd::CustomAnimationPresets::import(), got no service manager" ); + if( !xServiceFactory.is() ) + return false; + + uno::Reference< beans::XPropertySet > xProps( xServiceFactory, UNO_QUERY ); + uno::Reference< uno::XComponentContext > xContext; + xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))) >>= xContext; + + uno::Reference< util::XMacroExpander > xMacroExpander; + if( xContext.is() ) + xMacroExpander.set( xContext->getValueByName( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/singletons/com.sun.star.util.theMacroExpander"))), + UNO_QUERY ); + + // import ui strings + Reference< XMultiServiceFactory > xConfigProvider( + xServiceFactory->createInstance( + OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ))), + UNO_QUERY_THROW ); + + UStringMap aTransitionNameMape; + const OUString aTransitionPath( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.UI.Effects/UserInterface/Transitions" ) ); + implImportLabels( xConfigProvider, aTransitionPath, aTransitionNameMape ); + + // read path to transition effects files from config + Any propValue = uno::makeAny( + beans::PropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("nodepath")), -1, + uno::makeAny( OUString( RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.Impress/Misc"))), + beans::PropertyState_DIRECT_VALUE ) ); + + Reference<container::XNameAccess> xNameAccess( + xConfigProvider->createInstanceWithArguments( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")), + Sequence<Any>( &propValue, 1 ) ), UNO_QUERY_THROW ); + uno::Sequence< rtl::OUString > aFiles; + xNameAccess->getByName( + OUString( RTL_CONSTASCII_USTRINGPARAM("TransitionFiles"))) >>= aFiles; + + for( sal_Int32 i=0; i<aFiles.getLength(); ++i ) + { + rtl::OUString aURL = aFiles[i]; + if( aURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( EXPAND_PROTOCOL )) == 0 ) + { + // cut protocol + rtl::OUString aMacro( aURL.copy( sizeof ( EXPAND_PROTOCOL ) -1 ) ); + // decode uric class chars + aMacro = rtl::Uri::decode( aMacro, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 ); + // expand macro string + aURL = xMacroExpander->expandMacros( aMacro ); + } + + bRet |= importTransitionsFile( rList, + xServiceFactory, + aTransitionNameMape, + aURL ); + } + + return bRet; + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR( "sd::TransitionPreset::importResources(), Exception cought!" ); + } + + return bRet; +} + +TransitionPresetList* TransitionPreset::mpTransitionPresetList = 0; + +const TransitionPresetList& TransitionPreset::getTransitionPresetList() +{ + if( !mpTransitionPresetList ) + { + SolarMutexGuard aGuard; + if( !mpTransitionPresetList ) + { + mpTransitionPresetList = new sd::TransitionPresetList(); + sd::TransitionPreset::importTransitionPresetList( *mpTransitionPresetList ); + } + } + + return *mpTransitionPresetList; +} + +void TransitionPreset::apply( SdPage* pSlide ) const +{ + if( pSlide ) + { + pSlide->setTransitionType( mnTransition ); + pSlide->setTransitionSubtype( mnSubtype ); + pSlide->setTransitionDirection( mbDirection ); + pSlide->setTransitionFadeColor( mnFadeColor ); + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/anminfo.cxx b/sd/source/core/anminfo.cxx new file mode 100644 index 000000000000..f8398cc695ae --- /dev/null +++ b/sd/source/core/anminfo.cxx @@ -0,0 +1,154 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <tools/urlobj.hxx> +#include <svl/smplhint.hxx> +#include "svx/xtable.hxx" +#include <svx/svdopath.hxx> +#include <svl/urihelper.hxx> +#include <editeng/flditem.hxx> +#include <editeng/eeitem.hxx> + +#include "anminfo.hxx" +#include "glob.hxx" +#include "sdiocmpt.hxx" +#include "drawdoc.hxx" + +// #90477# +#include <tools/tenccvt.hxx> + +using namespace ::com::sun::star; + +SdAnimationInfo::SdAnimationInfo(SdrObject& rObject) + : SdrObjUserData(SdUDInventor, SD_ANIMATIONINFO_ID, 0), + mePresObjKind (PRESOBJ_NONE), + meEffect (presentation::AnimationEffect_NONE), + meTextEffect (presentation::AnimationEffect_NONE), + meSpeed (presentation::AnimationSpeed_SLOW), + mbActive (TRUE), + mbDimPrevious (FALSE), + mbIsMovie (FALSE), + mbDimHide (FALSE), + mbSoundOn (FALSE), + mbPlayFull (FALSE), + mpPathObj (NULL), + meClickAction (presentation::ClickAction_NONE), + meSecondEffect (presentation::AnimationEffect_NONE), + meSecondSpeed (presentation::AnimationSpeed_SLOW), + mbSecondSoundOn (FALSE), + mbSecondPlayFull (FALSE), + mnVerb (0), + mnPresOrder (LIST_APPEND), + mrObject (rObject) +{ + maBlueScreen = RGB_Color(COL_LIGHTMAGENTA); + maDimColor = RGB_Color(COL_LIGHTGRAY); +} + +SdAnimationInfo::SdAnimationInfo(const SdAnimationInfo& rAnmInfo, SdrObject& rObject) + : SdrObjUserData (rAnmInfo), + mePresObjKind (PRESOBJ_NONE), + meEffect (rAnmInfo.meEffect), + meTextEffect (rAnmInfo.meTextEffect), + meSpeed (rAnmInfo.meSpeed), + mbActive (rAnmInfo.mbActive), + mbDimPrevious (rAnmInfo.mbDimPrevious), + mbIsMovie (rAnmInfo.mbIsMovie), + mbDimHide (rAnmInfo.mbDimHide), + maBlueScreen (rAnmInfo.maBlueScreen), + maDimColor (rAnmInfo.maDimColor), + maSoundFile (rAnmInfo.maSoundFile), + mbSoundOn (rAnmInfo.mbSoundOn), + mbPlayFull (rAnmInfo.mbPlayFull), + mpPathObj (NULL), + meClickAction (rAnmInfo.meClickAction), + meSecondEffect (rAnmInfo.meSecondEffect), + meSecondSpeed (rAnmInfo.meSecondSpeed), + maSecondSoundFile (rAnmInfo.maSecondSoundFile), + mbSecondSoundOn (rAnmInfo.mbSecondSoundOn), + mbSecondPlayFull (rAnmInfo.mbSecondPlayFull), + mnVerb (rAnmInfo.mnVerb), + mnPresOrder (LIST_APPEND), + mrObject (rObject) +{ + // can not be copied + if(meEffect == presentation::AnimationEffect_PATH) + meEffect = presentation::AnimationEffect_NONE; +} + + +SdAnimationInfo::~SdAnimationInfo() +{ +} + +SdrObjUserData* SdAnimationInfo::Clone(SdrObject* pObject) const +{ + DBG_ASSERT( pObject, "SdAnimationInfo::Clone(), pObject must not be null!" ); + if( pObject == 0 ) + pObject = &mrObject; + + return new SdAnimationInfo(*this, *pObject ); +} + +void SdAnimationInfo::SetBookmark( const String& rBookmark ) +{ + if( meClickAction == ::com::sun::star::presentation::ClickAction_BOOKMARK ) + { + String sURL( '#' ); + sURL += rBookmark; + SvxFieldItem aURLItem( SvxURLField( sURL, sURL ), EE_FEATURE_FIELD ); + mrObject.SetMergedItem( aURLItem ); + } + else + { + SvxFieldItem aURLItem( SvxURLField( rBookmark, rBookmark ), EE_FEATURE_FIELD ); + mrObject.SetMergedItem( aURLItem ); + } +} + +String SdAnimationInfo::GetBookmark() +{ + String sBookmark; + + const SvxFieldItem* pFldItem = dynamic_cast< const SvxFieldItem* >( &mrObject.GetMergedItem( EE_FEATURE_FIELD ) ); + if( pFldItem ) + { + SvxURLField* pURLField = const_cast< SvxURLField* >( dynamic_cast<const SvxURLField*>( pFldItem->GetField() ) ); + if( pURLField ) + sBookmark = pURLField->GetURL(); + } + + if( (meClickAction == ::com::sun::star::presentation::ClickAction_BOOKMARK) && sBookmark.Len() && (sBookmark.GetChar(0) == '#') ) + sBookmark = sBookmark.Copy( 1 ); + + return sBookmark; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/annotations/Annotation.cxx b/sd/source/core/annotations/Annotation.cxx new file mode 100644 index 000000000000..1e91289db32e --- /dev/null +++ b/sd/source/core/annotations/Annotation.cxx @@ -0,0 +1,447 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include "osl/time.h" +#include "sal/config.h" + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/office/XAnnotation.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> + +#include <comphelper/processfactory.hxx> +#include <cppuhelper/propertysetmixin.hxx> +#include <cppuhelper/compbase1.hxx> +#include <cppuhelper/basemutex.hxx> + +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include "textapi.hxx" + +using ::rtl::OUString; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::office; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::geometry; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star; + +extern void NotifyDocumentEvent( SdDrawDocument* pDocument, const rtl::OUString& rEventName, const Reference< XInterface >& xSource ); + +namespace sd { + +class Annotation : private ::cppu::BaseMutex, + public ::cppu::WeakComponentImplHelper1< XAnnotation>, + public ::cppu::PropertySetMixin< XAnnotation > +{ +public: + explicit Annotation( const Reference< XComponentContext >& context, SdPage* pPage ); + + SdPage* GetPage() const { return mpPage; } + SdrModel* GetModel() { return (mpPage != 0) ? mpPage->GetModel() : 0; } + + // XInterface: + virtual Any SAL_CALL queryInterface(Type const & type) throw (RuntimeException); + virtual void SAL_CALL acquire() throw () { ::cppu::WeakComponentImplHelper1< XAnnotation >::acquire(); } + virtual void SAL_CALL release() throw () { ::cppu::WeakComponentImplHelper1< XAnnotation >::release(); } + + // ::com::sun::star::beans::XPropertySet: + virtual Reference< XPropertySetInfo > SAL_CALL getPropertySetInfo() throw (RuntimeException); + virtual void SAL_CALL setPropertyValue(const OUString & aPropertyName, const Any & aValue) throw (RuntimeException, UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException); + virtual Any SAL_CALL getPropertyValue(const OUString & PropertyName) throw (RuntimeException, UnknownPropertyException, WrappedTargetException); + virtual void SAL_CALL addPropertyChangeListener(const OUString & aPropertyName, const Reference< XPropertyChangeListener > & xListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException); + virtual void SAL_CALL removePropertyChangeListener(const OUString & aPropertyName, const Reference< XPropertyChangeListener > & aListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException); + virtual void SAL_CALL addVetoableChangeListener(const OUString & PropertyName, const Reference< XVetoableChangeListener > & aListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException); + virtual void SAL_CALL removeVetoableChangeListener(const OUString & PropertyName, const Reference< XVetoableChangeListener > & aListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException); + + // ::com::sun::star::office::XAnnotation: + virtual ::com::sun::star::uno::Any SAL_CALL getAnchor() throw (::com::sun::star::uno::RuntimeException); + virtual RealPoint2D SAL_CALL getPosition() throw (RuntimeException); + virtual void SAL_CALL setPosition(const RealPoint2D & the_value) throw (RuntimeException); + virtual ::com::sun::star::geometry::RealSize2D SAL_CALL getSize() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setSize( const ::com::sun::star::geometry::RealSize2D& _size ) throw (::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getAuthor() throw (RuntimeException); + virtual void SAL_CALL setAuthor(const OUString & the_value) throw (RuntimeException); + virtual util::DateTime SAL_CALL getDateTime() throw (RuntimeException); + virtual void SAL_CALL setDateTime(const util::DateTime & the_value) throw (RuntimeException); + virtual Reference< XText > SAL_CALL getTextRange() throw (RuntimeException); + +private: + Annotation(const Annotation &); // not defined + Annotation& operator=(const Annotation &); // not defined + + // destructor is private and will be called indirectly by the release call virtual ~Annotation() {} + + void createChangeUndo(); + + // overload WeakComponentImplHelperBase::disposing() + // This function is called upon disposing the component, + // if your component needs special work when it becomes + // disposed, do it here. + virtual void SAL_CALL disposing(); + + SdPage* mpPage; + Reference< XComponentContext > m_xContext; + mutable ::osl::Mutex m_aMutex; + RealPoint2D m_Position; + RealSize2D m_Size; + OUString m_Author; + util::DateTime m_DateTime; + rtl::Reference< TextApiObject > m_TextRange; +}; + +class UndoInsertOrRemoveAnnotation : public SdrUndoAction +{ +public: + UndoInsertOrRemoveAnnotation( Annotation& rAnnotation, bool bInsert ); + + virtual void Undo(); + virtual void Redo(); + +protected: + rtl::Reference< Annotation > mxAnnotation; + bool mbInsert; + int mnIndex; +}; + +struct AnnotationData +{ + RealPoint2D m_Position; + RealSize2D m_Size; + OUString m_Author; + util::DateTime m_DateTime; + + void get( const rtl::Reference< Annotation >& xAnnotation ) + { + m_Position = xAnnotation->getPosition(); + m_Size = xAnnotation->getSize(); + m_Author = xAnnotation->getAuthor(); + m_DateTime = xAnnotation->getDateTime(); + } + + void set( const rtl::Reference< Annotation >& xAnnotation ) + { + xAnnotation->setPosition(m_Position); + xAnnotation->setSize(m_Size); + xAnnotation->setAuthor(m_Author); + xAnnotation->setDateTime(m_DateTime); + } +}; + +class UndoAnnotation : public SdrUndoAction +{ +public: + UndoAnnotation( Annotation& rAnnotation ); + + virtual void Undo(); + virtual void Redo(); + +protected: + rtl::Reference< Annotation > mxAnnotation; + AnnotationData maUndoData; + AnnotationData maRedoData; +}; + +void createAnnotation( Reference< XAnnotation >& xAnnotation, SdPage* pPage ) +{ + Reference<XComponentContext> xContext (comphelper_getProcessComponentContext()); + xAnnotation.set( new Annotation(xContext, pPage) ); + pPage->addAnnotation(xAnnotation); +} + +Annotation::Annotation( const Reference< XComponentContext >& context, SdPage* pPage ) +: ::cppu::WeakComponentImplHelper1< XAnnotation >(m_aMutex) +, ::cppu::PropertySetMixin< XAnnotation >(context, static_cast< Implements >(IMPLEMENTS_PROPERTY_SET), Sequence< ::rtl::OUString >()) +, mpPage( pPage ) +{ +} + +// overload WeakComponentImplHelperBase::disposing() +// This function is called upon disposing the component, +// if your component needs special work when it becomes +// disposed, do it here. +void SAL_CALL Annotation::disposing() +{ + mpPage = 0; + if( m_TextRange.is() ) + { + m_TextRange->dispose(); + m_TextRange.clear(); + } +} + +Any Annotation::queryInterface(Type const & type) throw (RuntimeException) +{ + return ::cppu::WeakComponentImplHelper1< XAnnotation>::queryInterface(type); +} + +// com.sun.star.beans.XPropertySet: +Reference< XPropertySetInfo > SAL_CALL Annotation::getPropertySetInfo() throw (RuntimeException) +{ + return ::cppu::PropertySetMixin< XAnnotation >::getPropertySetInfo(); +} + +void SAL_CALL Annotation::setPropertyValue(const OUString & aPropertyName, const Any & aValue) throw (RuntimeException, UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException) +{ + ::cppu::PropertySetMixin< XAnnotation >::setPropertyValue(aPropertyName, aValue); +} + +Any SAL_CALL Annotation::getPropertyValue(const OUString & aPropertyName) throw (RuntimeException, UnknownPropertyException, WrappedTargetException) +{ + return ::cppu::PropertySetMixin< XAnnotation >::getPropertyValue(aPropertyName); +} + +void SAL_CALL Annotation::addPropertyChangeListener(const OUString & aPropertyName, const Reference< XPropertyChangeListener > & xListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException) +{ + ::cppu::PropertySetMixin< XAnnotation >::addPropertyChangeListener(aPropertyName, xListener); +} + +void SAL_CALL Annotation::removePropertyChangeListener(const OUString & aPropertyName, const Reference< XPropertyChangeListener > & xListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException) +{ + ::cppu::PropertySetMixin< XAnnotation >::removePropertyChangeListener(aPropertyName, xListener); +} + +void SAL_CALL Annotation::addVetoableChangeListener(const OUString & aPropertyName, const Reference< XVetoableChangeListener > & xListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException) +{ + ::cppu::PropertySetMixin< XAnnotation >::addVetoableChangeListener(aPropertyName, xListener); +} + +void SAL_CALL Annotation::removeVetoableChangeListener(const OUString & aPropertyName, const Reference< XVetoableChangeListener > & xListener) throw (RuntimeException, UnknownPropertyException, WrappedTargetException) +{ + ::cppu::PropertySetMixin< XAnnotation >::removeVetoableChangeListener(aPropertyName, xListener); +} + +Any SAL_CALL Annotation::getAnchor() throw (RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + Any aRet; + if( mpPage ) + { + Reference< XDrawPage > xPage( mpPage->getUnoPage(), UNO_QUERY ); + aRet <<= xPage; + } + return aRet; +} + +// ::com::sun::star::office::XAnnotation: +RealPoint2D SAL_CALL Annotation::getPosition() throw (RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_Position; +} + +void SAL_CALL Annotation::setPosition(const RealPoint2D & the_value) throw (RuntimeException) +{ + prepareSet( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Position")), + Any(), Any(), 0); + { + osl::MutexGuard g(m_aMutex); + createChangeUndo(); + m_Position = the_value; + } +} + +// ::com::sun::star::office::XAnnotation: +RealSize2D SAL_CALL Annotation::getSize() throw (RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_Size; +} + +void SAL_CALL Annotation::setSize(const RealSize2D & the_value) throw (RuntimeException) +{ + prepareSet( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Size")), + Any(), Any(), 0); + { + osl::MutexGuard g(m_aMutex); + createChangeUndo(); + m_Size = the_value; + } +} + +OUString SAL_CALL Annotation::getAuthor() throw (RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_Author; +} + +void SAL_CALL Annotation::setAuthor(const OUString & the_value) throw (RuntimeException) +{ + prepareSet( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Author")), + Any(), Any(), 0); + { + osl::MutexGuard g(m_aMutex); + createChangeUndo(); + m_Author = the_value; + } +} + +util::DateTime SAL_CALL Annotation::getDateTime() throw (RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + return m_DateTime; +} + +void SAL_CALL Annotation::setDateTime(const util::DateTime & the_value) throw (RuntimeException) +{ + prepareSet( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DateTime")), + Any(), Any(), 0); + { + osl::MutexGuard g(m_aMutex); + createChangeUndo(); + m_DateTime = the_value; + } +} + +void Annotation::createChangeUndo() +{ + SdrModel* pModel = GetModel(); + if( pModel && pModel->IsUndoEnabled() ) + pModel->AddUndo( new UndoAnnotation( *this ) ); + + if( pModel ) + { + pModel->SetChanged(); + Reference< XInterface > xSource( static_cast<uno::XWeak*>( this ) ); + NotifyDocumentEvent( static_cast< SdDrawDocument* >( pModel ), OUString( RTL_CONSTASCII_USTRINGPARAM("OnAnnotationChanged") ), xSource ); + } +} + +Reference< XText > SAL_CALL Annotation::getTextRange() throw (RuntimeException) +{ + osl::MutexGuard g(m_aMutex); + if( !m_TextRange.is() && (mpPage != 0) ) + { + m_TextRange = TextApiObject::create( static_cast< SdDrawDocument* >( mpPage->GetModel() ) ); + } + return Reference< XText >( m_TextRange.get() ); +} + +SdrUndoAction* CreateUndoInsertOrRemoveAnnotation( const Reference< XAnnotation >& xAnnotation, bool bInsert ) +{ + Annotation* pAnnotation = dynamic_cast< Annotation* >( xAnnotation.get() ); + if( pAnnotation ) + { + return new UndoInsertOrRemoveAnnotation( *pAnnotation, bInsert ); + } + else + { + return 0; + } +} + +UndoInsertOrRemoveAnnotation::UndoInsertOrRemoveAnnotation( Annotation& rAnnotation, bool bInsert ) +: SdrUndoAction( *rAnnotation.GetModel() ) +, mxAnnotation( &rAnnotation ) +, mbInsert( bInsert ) +, mnIndex( 0 ) +{ + SdPage* pPage = rAnnotation.GetPage(); + if( pPage ) + { + Reference< XAnnotation > xAnnotation( &rAnnotation ); + + const AnnotationVector& rVec = pPage->getAnnotations(); + for( AnnotationVector::const_iterator iter = rVec.begin(); iter != rVec.end(); ++iter ) + { + if( (*iter) == xAnnotation ) + break; + + mnIndex++; + } + } +} + +void UndoInsertOrRemoveAnnotation::Undo() +{ + SdPage* pPage = mxAnnotation->GetPage(); + SdrModel* pModel = mxAnnotation->GetModel(); + if( pPage && pModel ) + { + Reference< XAnnotation > xAnnotation( mxAnnotation.get() ); + if( mbInsert ) + { + pPage->removeAnnotation( xAnnotation ); + } + else + { + pPage->addAnnotation( xAnnotation, mnIndex ); + } + } +} + +void UndoInsertOrRemoveAnnotation::Redo() +{ + SdPage* pPage = mxAnnotation->GetPage(); + SdrModel* pModel = mxAnnotation->GetModel(); + if( pPage && pModel ) + { + Reference< XAnnotation > xAnnotation( mxAnnotation.get() ); + + if( mbInsert ) + { + pPage->addAnnotation( xAnnotation, mnIndex ); + } + else + { + pPage->removeAnnotation( xAnnotation ); + } + } +} + +UndoAnnotation::UndoAnnotation( Annotation& rAnnotation ) +: SdrUndoAction( *rAnnotation.GetModel() ) +, mxAnnotation( &rAnnotation ) +{ + maUndoData.get( mxAnnotation ); +} + +void UndoAnnotation::Undo() +{ + maRedoData.get( mxAnnotation ); + maUndoData.set( mxAnnotation ); +} + +void UndoAnnotation::Redo() +{ + maUndoData.get( mxAnnotation ); + maRedoData.set( mxAnnotation ); +} + +} // namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/annotations/AnnotationAccess.cxx b/sd/source/core/annotations/AnnotationAccess.cxx new file mode 100644 index 000000000000..c873289772d6 --- /dev/null +++ b/sd/source/core/annotations/AnnotationAccess.cxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "sal/config.h" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "cppuhelper/implbase1.hxx" +#include "com/sun/star/office/XAnnotationAccess.hpp" + +namespace css = ::com::sun::star; + +class AnnotationAccess: + public ::cppu::WeakImplHelper1< + css::office::XAnnotationAccess> +{ +public: + explicit AnnotationAccess(css::uno::Reference< css::uno::XComponentContext > const & context); + + // ::com::sun::star::office::XAnnotationAccess: + virtual css::uno::Reference< css::office::XAnnotation > SAL_CALL createAndInsertAnnotation() throw (css::uno::RuntimeException); + virtual void SAL_CALL removeAnnotation(const css::uno::Reference< css::office::XAnnotation > & annotation) throw (css::uno::RuntimeException, css::lang::IllegalArgumentException); + virtual css::uno::Reference< css::office::XAnnotationEnumeration > SAL_CALL createAnnotationEnumeration() throw (css::uno::RuntimeException); + +private: + AnnotationAccess(const AnnotationAccess &); // not defined + AnnotationAccess& operator=(const AnnotationAccess &); // not defined + + // destructor is private and will be called indirectly by the release call virtual ~AnnotationAccess() {} + + css::uno::Reference< css::uno::XComponentContext > m_xContext; +}; + +AnnotationAccess::AnnotationAccess(css::uno::Reference< css::uno::XComponentContext > const & context) : + m_xContext(context) +{} + +// ::com::sun::star::office::XAnnotationAccess: +css::uno::Reference< css::office::XAnnotation > SAL_CALL AnnotationAccess::createAndInsertAnnotation() throw (css::uno::RuntimeException) +{ + // TODO: Exchange the default return implementation for "createAndInsertAnnotation" !!! + // Exchange the default return implementation. + // NOTE: Default initialized polymorphic structs can cause problems because of + // missing default initialization of primitive types of some C++ compilers or + // different Any initialization in Java and C++ polymorphic structs. + return css::uno::Reference< css::office::XAnnotation >(); +} + +void SAL_CALL AnnotationAccess::removeAnnotation(const css::uno::Reference< css::office::XAnnotation > & annotation) throw (css::uno::RuntimeException, css::lang::IllegalArgumentException) +{ + // TODO: Insert your implementation for "removeAnnotation" here. +} + +css::uno::Reference< css::office::XAnnotationEnumeration > SAL_CALL AnnotationAccess::createAnnotationEnumeration() throw (css::uno::RuntimeException) +{ + // TODO: Exchange the default return implementation for "createAnnotationEnumeration" !!! + // Exchange the default return implementation. + // NOTE: Default initialized polymorphic structs can cause problems because of + // missing default initialization of primitive types of some C++ compilers or + // different Any initialization in Java and C++ polymorphic structs. + return css::uno::Reference< css::office::XAnnotationEnumeration >(); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/annotations/AnnotationEnumeration.cxx b/sd/source/core/annotations/AnnotationEnumeration.cxx new file mode 100644 index 000000000000..e270987dc083 --- /dev/null +++ b/sd/source/core/annotations/AnnotationEnumeration.cxx @@ -0,0 +1,95 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include "sal/config.h" + +#include "cppuhelper/implbase1.hxx" + +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/office/XAnnotationEnumeration.hpp" + +#include "sdpage.hxx" +namespace css = ::com::sun::star; + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::office; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +namespace sd { + +class AnnotationEnumeration: public ::cppu::WeakImplHelper1< css::office::XAnnotationEnumeration > +{ +public: + AnnotationEnumeration( const AnnotationVector& rAnnotations ); + + // ::com::sun::star::office::XAnnotationEnumeration: + virtual ::sal_Bool SAL_CALL hasMoreElements() throw (css::uno::RuntimeException); + virtual css::uno::Reference< css::office::XAnnotation > SAL_CALL nextElement() throw (css::uno::RuntimeException, css::container::NoSuchElementException); + +private: + AnnotationEnumeration(const AnnotationEnumeration &); // not defined + AnnotationEnumeration& operator=(const AnnotationEnumeration &); // not defined + + // destructor is private and will be called indirectly by the release call virtual ~AnnotationEnumeration() {} + + AnnotationVector maAnnotations; + AnnotationVector::iterator maIter; +}; + +Reference< XAnnotationEnumeration > createAnnotationEnumeration( const sd::AnnotationVector& rAnnotations ) +{ + return new AnnotationEnumeration( rAnnotations ); +} + +AnnotationEnumeration::AnnotationEnumeration( const AnnotationVector& rAnnotations ) +: maAnnotations(rAnnotations) +{ + maIter = maAnnotations.begin(); +} + +// ::com::sun::star::office::XAnnotationEnumeration: +::sal_Bool SAL_CALL AnnotationEnumeration::hasMoreElements() throw (css::uno::RuntimeException) +{ + return maIter != maAnnotations.end() ? sal_True : sal_False; +} + +css::uno::Reference< css::office::XAnnotation > SAL_CALL AnnotationEnumeration::nextElement() throw (css::uno::RuntimeException, css::container::NoSuchElementException) +{ + if( maIter == maAnnotations.end() ) + throw css::container::NoSuchElementException(); + + return (*maIter++); +} + +} // namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/annotations/makefile.mk b/sd/source/core/annotations/makefile.mk new file mode 100644 index 000000000000..7f5258a5e474 --- /dev/null +++ b/sd/source/core/annotations/makefile.mk @@ -0,0 +1,49 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PROJECTPCH=sd +PROJECTPCHSOURCE=$(PRJ)$/util$/sd +PRJNAME=sd +TARGET=annotations +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = $(SLO)$/Annotation.obj \ + $(SLO)$/AnnotationEnumeration.obj + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sd/source/core/cusshow.cxx b/sd/source/core/cusshow.cxx new file mode 100644 index 000000000000..02daee172dee --- /dev/null +++ b/sd/source/core/cusshow.cxx @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + + +#include <com/sun/star/lang/XComponent.hpp> + +#include "sdiocmpt.hxx" +#include "cusshow.hxx" +#include "sdpage.hxx" +#include "drawdoc.hxx" + +// #90477# +#include <tools/tenccvt.hxx> + +using namespace ::com::sun::star; + +/************************************************************************* +|* +|* Ctor +|* +\************************************************************************/ +SdCustomShow::SdCustomShow(SdDrawDocument* pDrawDoc) + : List(), + pDoc(pDrawDoc) +{ +} + +/************************************************************************* +|* +|* Copy-Ctor +|* +\************************************************************************/ +SdCustomShow::SdCustomShow( const SdCustomShow& rShow ) + : List( rShow ) +{ + aName = rShow.GetName(); + pDoc = rShow.GetDoc(); +} + +SdCustomShow::SdCustomShow(SdDrawDocument* pDrawDoc, ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xShow ) + : List(), + pDoc(pDrawDoc), + mxUnoCustomShow( xShow ) +{ +} + +/************************************************************************* +|* +|* Dtor +|* +\************************************************************************/ +SdCustomShow::~SdCustomShow() +{ + uno::Reference< uno::XInterface > xShow( mxUnoCustomShow ); + uno::Reference< lang::XComponent > xComponent( xShow, uno::UNO_QUERY ); + if( xComponent.is() ) + xComponent->dispose(); +} + +extern uno::Reference< uno::XInterface > createUnoCustomShow( SdCustomShow* pShow ); + +uno::Reference< uno::XInterface > SdCustomShow::getUnoCustomShow() +{ + // try weak reference first + uno::Reference< uno::XInterface > xShow( mxUnoCustomShow ); + + if( !xShow.is() ) + { + xShow = createUnoCustomShow( this ); + } + + return xShow; +} + +void SdCustomShow::ReplacePage( const SdPage* pOldPage, const SdPage* pNewPage ) +{ + if( !pNewPage ) + { + RemovePage( pOldPage ); + } + else + { + ULONG nPos; + while( (nPos = GetPos( (void*)pOldPage )) != CONTAINER_ENTRY_NOTFOUND ) + { + Replace( (void*)pNewPage, nPos ); + } + } +} + +void SdCustomShow::RemovePage( const SdPage* pPage ) +{ + ULONG nPos; + while( (nPos = GetPos( (void*)pPage )) != CONTAINER_ENTRY_NOTFOUND ) + { + Remove( nPos ); + } +} + +void SdCustomShow::SetName(const String& rName) +{ + aName = rName; +} + +String SdCustomShow::GetName() const +{ + return aName; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/drawdoc.cxx b/sd/source/core/drawdoc.cxx new file mode 100644 index 000000000000..4971725be29c --- /dev/null +++ b/sd/source/core/drawdoc.cxx @@ -0,0 +1,1062 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include "PageListWatcher.hxx" +#include <com/sun/star/text/WritingMode.hpp> +#include <com/sun/star/document/PrinterIndependentLayout.hpp> +#include <com/sun/star/i18n/ScriptType.hpp> +#include <editeng/forbiddencharacterstable.hxx> + +#include <svx/svxids.hrc> +#include <svl/srchitem.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/scriptspaceitem.hxx> + +#include <unotools/useroptions.hxx> + +#include <sfx2/printer.hxx> +#include <sfx2/app.hxx> +#include <sfx2/linkmgr.hxx> +#include <svx/dialogs.hrc> +#include "Outliner.hxx" +#include "app.hxx" +#include <editeng/eeitem.hxx> +#include <editeng/editstat.hxx> +#include <editeng/fontitem.hxx> +#include <svl/flagitem.hxx> +#include <svx/svdoattr.hxx> +#include <svx/svdotext.hxx> +#include <editeng/bulitem.hxx> +#include <editeng/numitem.hxx> +#include <svx/svditer.hxx> +#include <editeng/unolingu.hxx> +#include <svl/itempool.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <svx/xtable.hxx> +#include <com/sun/star/linguistic2/XHyphenator.hpp> +#include <com/sun/star/linguistic2/XSpellChecker1.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <editeng/outlobj.hxx> +#include <unotools/saveopt.hxx> +#include <comphelper/extract.hxx> +#include <i18npool/mslangid.hxx> +#include <unotools/charclass.hxx> +#include <comphelper/processfactory.hxx> +#include <unotools/pathoptions.hxx> +#include <unotools/lingucfg.hxx> +#include <unotools/linguprops.hxx> + +#include "eetext.hxx" +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include "pglink.hxx" +#include "sdattr.hxx" +#include "glob.hrc" +#include "glob.hxx" +#include "stlpool.hxx" +#include "sdiocmpt.hxx" +#include "sdresid.hxx" +#include "cusshow.hxx" +#include "../ui/inc/DrawDocShell.hxx" +#include "../ui/inc/GraphicDocShell.hxx" +#include "../ui/inc/sdxfer.hxx" +#include "../ui/inc/ViewShell.hxx" +#include "../ui/inc/optsitem.hxx" +#include "../ui/inc/FrameView.hxx" + +// #90477# +#include <tools/tenccvt.hxx> + +using ::rtl::OUString; +using namespace ::sd; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::linguistic2; + +////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1( SdDrawDocument, FmFormModel ); + +SdDrawDocument* SdDrawDocument::pDocLockedInsertingLinks = NULL; + +////////////////////////////////////////////////////////////////////////////// + +PresentationSettings::PresentationSettings() +: mbAll( true ), + mbEndless( false ), + mbCustomShow(false), + mbManual( false ), + mbMouseVisible( false ), + mbMouseAsPen( false ), + mbLockedPages( false ), + mbAlwaysOnTop( false ), + mbFullScreen( true ), + mbAnimationAllowed( true ), + mnPauseTimeout( 10 ), + mbShowPauseLogo( false ), + mbStartWithNavigator(false) +{ +} + +// --------------------------------------------------------------------------- + +PresentationSettings::PresentationSettings( const PresentationSettings& r ) +: maPresPage( r.maPresPage ), + mbAll( r.mbAll ), + mbEndless( r.mbEndless ), + mbCustomShow( r.mbCustomShow ), + mbManual( r.mbManual ), + mbMouseVisible( r.mbMouseVisible ), + mbMouseAsPen( r.mbMouseAsPen ), + mbLockedPages( r.mbLockedPages ), + mbAlwaysOnTop( r.mbAlwaysOnTop ), + mbFullScreen( r.mbFullScreen ), + mbAnimationAllowed( r.mbAnimationAllowed ), + mnPauseTimeout( r.mnPauseTimeout ), + mbShowPauseLogo( r.mbShowPauseLogo ), + mbStartWithNavigator( r.mbStartWithNavigator ) +{ +} + +// --------------------------------------------------------------------------- + +SdDrawDocument::SdDrawDocument(DocumentType eType, SfxObjectShell* pDrDocSh) +: FmFormModel( SvtPathOptions().GetPalettePath(), NULL, pDrDocSh ) +, mpOutliner(NULL) +, mpInternalOutliner(NULL) +, mpWorkStartupTimer(NULL) +, mpOnlineSpellingTimer(NULL) +, mpOnlineSpellingList(NULL) +, mpOnlineSearchItem(NULL) +, mpFrameViewList( new List() ) +, mpCustomShowList(NULL) +, mpDocSh(static_cast< ::sd::DrawDocShell*>(pDrDocSh)) +, mpCreatingTransferable( NULL ) +, mbHasOnlineSpellErrors(FALSE) +, mbInitialOnlineSpellingEnabled(TRUE) +, mbNewOrLoadCompleted(FALSE) +, mbStartWithPresentation( false ) +, meLanguage( LANGUAGE_SYSTEM ) +, meLanguageCJK( LANGUAGE_SYSTEM ) +, meLanguageCTL( LANGUAGE_SYSTEM ) +, mePageNumType(SVX_ARABIC) +, mbAllocDocSh(FALSE) +, meDocType(eType) +, mpCharClass(NULL) +, mpLocale(NULL) +, mpDrawPageListWatcher(0) +, mpMasterPageListWatcher(0) +{ + // #109538# + mpDrawPageListWatcher = ::std::auto_ptr<ImpDrawPageListWatcher>( + new ImpDrawPageListWatcher(*this)); + mpMasterPageListWatcher = ::std::auto_ptr<ImpMasterPageListWatcher>( + new ImpMasterPageListWatcher(*this)); + + SetObjectShell(pDrDocSh); // fuer das VCDrawModel + + if (mpDocSh) + { + SetSwapGraphics(TRUE); + } + + // Masseinheit (von App) und Massstab (von SdMod) setzen + INT32 nX, nY; + SdOptions* pOptions = SD_MOD()->GetSdOptions(meDocType); + pOptions->GetScale( nX, nY ); + + // #92067# Allow UI scale only for draw documents. + if( eType == DOCUMENT_TYPE_DRAW ) + SetUIUnit( (FieldUnit)pOptions->GetMetric(), Fraction( nX, nY ) ); // user-defined + else + SetUIUnit( (FieldUnit)pOptions->GetMetric(), Fraction( 1, 1 ) ); // default + + SetScaleUnit(MAP_100TH_MM); + SetScaleFraction(Fraction(1, 1)); + SetDefaultFontHeight(847); // 24p + + pItemPool->SetDefaultMetric(SFX_MAPUNIT_100TH_MM); + pItemPool->FreezeIdRanges(); + SetTextDefaults(); + + // die DrawingEngine muss auch wissen, wo er ist + FmFormModel::SetStyleSheetPool( new SdStyleSheetPool( GetPool(), this ) ); + + // Dem DrawOutliner den StyleSheetPool setzen, damit Textobjekte richtig + // eingelesen werden koennen. Der Link zum StyleRequest-Handler des + // Dokuments wird erst in NewOrLoadCompleted gesetzt, da erst dann alle + // Vorlagen existieren. + SdrOutliner& rOutliner = GetDrawOutliner(); + rOutliner.SetStyleSheetPool((SfxStyleSheetPool*)GetStyleSheetPool()); + SetCalcFieldValueHdl( &rOutliner ); + + // set linguistic options + { + const SvtLinguConfig aLinguConfig; + SvtLinguOptions aOptions; + aLinguConfig.GetOptions( aOptions ); + + SetLanguage( MsLangId::resolveSystemLanguageByScriptType(aOptions.nDefaultLanguage, + ::com::sun::star::i18n::ScriptType::LATIN), EE_CHAR_LANGUAGE ); + SetLanguage( MsLangId::resolveSystemLanguageByScriptType(aOptions.nDefaultLanguage_CJK, + ::com::sun::star::i18n::ScriptType::ASIAN), EE_CHAR_LANGUAGE_CJK ); + SetLanguage( MsLangId::resolveSystemLanguageByScriptType(aOptions.nDefaultLanguage_CTL, + ::com::sun::star::i18n::ScriptType::COMPLEX), EE_CHAR_LANGUAGE_CTL ); + + mbOnlineSpell = aOptions.bIsSpellAuto; + } + + LanguageType eRealLanguage = MsLangId::getRealLanguage( meLanguage ); + mpLocale = new ::com::sun::star::lang::Locale( MsLangId::convertLanguageToLocale( eRealLanguage )); + mpCharClass = new CharClass( *mpLocale ); + + // If the current application language is a language that uses right-to-left text... + LanguageType eRealCTLLanguage = Application::GetSettings().GetLanguage(); + if( MsLangId::isRightToLeft( eRealCTLLanguage ) ) + { + // ... then we have to set this as a default + SetDefaultWritingMode( ::com::sun::star::text::WritingMode_RL_TB ); + } + + // for korean and japanese languages we have a different default for apply spacing between asian, latin and ctl text + if( ( LANGUAGE_KOREAN == eRealCTLLanguage ) || ( LANGUAGE_KOREAN_JOHAB == eRealCTLLanguage ) || ( LANGUAGE_JAPANESE == eRealCTLLanguage ) ) + { + GetPool().GetSecondaryPool()->SetPoolDefaultItem( SvxScriptSpaceItem( FALSE, EE_PARA_ASIANCJKSPACING ) ); + } + + // DefTab und SpellOptions setzen + // Jetzt am Modul (SD) + USHORT nDefTab = pOptions->GetDefTab(); + SetDefaultTabulator( nDefTab ); + + try + { + Reference< XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() ); + if ( xSpellChecker.is() ) + rOutliner.SetSpeller( xSpellChecker ); + + Reference< XHyphenator > xHyphenator( LinguMgr::GetHyphenator() ); + if( xHyphenator.is() ) + rOutliner.SetHyphenator( xHyphenator ); + + SetForbiddenCharsTable( new SvxForbiddenCharactersTable( ::comphelper::getProcessServiceFactory() ) ); + } + catch(...) + { + DBG_ERROR("Can't get SpellChecker"); + } + + rOutliner.SetDefaultLanguage( Application::GetSettings().GetLanguage() ); + + if (mpDocSh) + { + SetLinkManager( new sfx2::LinkManager(mpDocSh) ); + } + + ULONG nCntrl = rOutliner.GetControlWord(); + nCntrl |= EE_CNTRL_ALLOWBIGOBJS; + nCntrl |= EE_CNTRL_URLSFXEXECUTE; + + if (mbOnlineSpell) + nCntrl |= EE_CNTRL_ONLINESPELLING; + else + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + + nCntrl &= ~ EE_CNTRL_ULSPACESUMMATION; + if ( meDocType != DOCUMENT_TYPE_IMPRESS ) + SetSummationOfParagraphs( sal_False ); + else + { + SetSummationOfParagraphs( pOptions->IsSummationOfParagraphs() ); + if ( pOptions->IsSummationOfParagraphs() ) + nCntrl |= EE_CNTRL_ULSPACESUMMATION; + } + rOutliner.SetControlWord(nCntrl); + + // Initialize the printer independent layout mode. + SetPrinterIndependentLayout (pOptions->GetPrinterIndependentLayout()); + + // Dem HitTestOutliner den StyleSheetPool setzen. + // Der Link zum StyleRequest-Handler des + // Dokuments wird erst in NewOrLoadCompleted gesetzt, da erst dann alle + // Vorlagen existieren. + SfxItemSet aSet2( pHitTestOutliner->GetEmptyItemSet() ); + pHitTestOutliner->SetStyleSheetPool( (SfxStyleSheetPool*)GetStyleSheetPool() ); + + SetCalcFieldValueHdl( pHitTestOutliner ); + + try + { + Reference< XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() ); + if ( xSpellChecker.is() ) + pHitTestOutliner->SetSpeller( xSpellChecker ); + + Reference< XHyphenator > xHyphenator( LinguMgr::GetHyphenator() ); + if( xHyphenator.is() ) + pHitTestOutliner->SetHyphenator( xHyphenator ); + } + catch(...) + { + DBG_ERROR("Can't get SpellChecker"); + } + + pHitTestOutliner->SetDefaultLanguage( Application::GetSettings().GetLanguage() ); + + ULONG nCntrl2 = pHitTestOutliner->GetControlWord(); + nCntrl2 |= EE_CNTRL_ALLOWBIGOBJS; + nCntrl2 |= EE_CNTRL_URLSFXEXECUTE; + nCntrl2 &= ~EE_CNTRL_ONLINESPELLING; + + nCntrl2 &= ~ EE_CNTRL_ULSPACESUMMATION; + if ( pOptions->IsSummationOfParagraphs() ) + nCntrl2 |= EE_CNTRL_ULSPACESUMMATION; + + pHitTestOutliner->SetControlWord( nCntrl2 ); + + /************************************************************************** + * Layer anlegen + * + * Es werden auf Pages und MasterPages folgende Default-Layer angelegt: + * + * Layer STR_LAYOUT : Standardlayer fr alle Zeichenobjekte + * + * Layer STR_BCKGRND : Hintergrund der MasterPage + * (auf normalen Pages z.Z. keine Verwendung) + * + * Layer STR_BCKGRNDOBJ: Objekte auf dem Hintergrund der MasterPage + * (auf normalen Pages z.Z. keine Verwendung) + * + * Layer STR_CONTROLS : Standardlayer fr Controls + * + **************************************************************************/ + { + String aControlLayerName( SdResId(STR_LAYER_CONTROLS) ); + + SdrLayerAdmin& rLayerAdmin = GetLayerAdmin(); + rLayerAdmin.NewLayer( String(SdResId(STR_LAYER_LAYOUT)) ); + rLayerAdmin.NewLayer( String(SdResId(STR_LAYER_BCKGRND)) ); + rLayerAdmin.NewLayer( String(SdResId(STR_LAYER_BCKGRNDOBJ)) ); + rLayerAdmin.NewLayer( aControlLayerName ); + rLayerAdmin.NewLayer( String(SdResId(STR_LAYER_MEASURELINES)) ); + + rLayerAdmin.SetControlLayerName(aControlLayerName); + } + + +} + +/************************************************************************* +|* +|* Destruktor +|* +\************************************************************************/ + +SdDrawDocument::~SdDrawDocument() +{ + Broadcast(SdrHint(HINT_MODELCLEARED)); + + if (mpWorkStartupTimer) + { + if ( mpWorkStartupTimer->IsActive() ) + mpWorkStartupTimer->Stop(); + + delete mpWorkStartupTimer; + mpWorkStartupTimer = NULL; + } + + StopOnlineSpelling(); + delete mpOnlineSearchItem; + mpOnlineSearchItem = NULL; + + CloseBookmarkDoc(); + SetAllocDocSh(FALSE); + + // #116168# + ClearModel(sal_True); + + if (pLinkManager) + { + // BaseLinks freigeben + if ( pLinkManager->GetLinks().Count() ) + { + pLinkManager->Remove( 0, pLinkManager->GetLinks().Count() ); + } + + delete pLinkManager; + pLinkManager = NULL; + } + + ::sd::FrameView* pFrameView = NULL; + + for (ULONG i = 0; i < mpFrameViewList->Count(); i++) + { + // Ggf. FrameViews loeschen + pFrameView = + static_cast< ::sd::FrameView*>(mpFrameViewList->GetObject(i)); + + if (pFrameView) + delete pFrameView; + } + + delete mpFrameViewList; + mpFrameViewList = NULL; + + if (mpCustomShowList) + { + for (ULONG j = 0; j < mpCustomShowList->Count(); j++) + { + // Ggf. CustomShows loeschen + SdCustomShow* pCustomShow = (SdCustomShow*) mpCustomShowList->GetObject(j); + delete pCustomShow; + } + + delete mpCustomShowList; + mpCustomShowList = NULL; + } + + delete mpOutliner; + mpOutliner = NULL; + + delete mpInternalOutliner; + mpInternalOutliner = NULL; + + delete mpLocale; + mpLocale = NULL; + + delete mpCharClass; + mpCharClass = NULL; +} + +/************************************************************************* +|* +|* Diese Methode erzeugt ein neues Dokument (SdDrawDocument) und gibt einen +|* Zeiger darauf zurueck. Die Drawing Engine benutzt diese Methode um das +|* Dokument oder Teile davon ins Clipboard/DragServer stellen zu koennen. +|* +\************************************************************************/ + +SdrModel* SdDrawDocument::AllocModel() const +{ + SdDrawDocument* pNewModel = NULL; + + if( mpCreatingTransferable ) + { + // Dokument wird fuer Drag&Drop/Clipboard erzeugt, dafuer muss dem Dokument eine DocShell (SvPersist) bekannt sein + SfxObjectShell* pObj = NULL; + ::sd::DrawDocShell* pNewDocSh = NULL; + + if( meDocType == DOCUMENT_TYPE_IMPRESS ) + mpCreatingTransferable->SetDocShell( new ::sd::DrawDocShell( + SFX_CREATE_MODE_EMBEDDED, TRUE, meDocType ) ); + else + mpCreatingTransferable->SetDocShell( new ::sd::GraphicDocShell( + SFX_CREATE_MODE_EMBEDDED, TRUE, meDocType ) ); + + pNewDocSh = static_cast< ::sd::DrawDocShell*>( pObj = mpCreatingTransferable->GetDocShell() ); + pNewDocSh->DoInitNew( NULL ); + pNewModel = pNewDocSh->GetDoc(); + + // Nur fuer Clipboard notwendig, + // fuer Drag&Drop erfolgt dieses im DragServer + SdStyleSheetPool* pOldStylePool = (SdStyleSheetPool*) GetStyleSheetPool(); + SdStyleSheetPool* pNewStylePool = (SdStyleSheetPool*) pNewModel->GetStyleSheetPool(); + + pNewStylePool->CopyGraphicSheets(*pOldStylePool); + pNewStylePool->CopyCellSheets(*pOldStylePool); + pNewStylePool->CopyTableStyles(*pOldStylePool); + + + for (USHORT i = 0; i < GetMasterSdPageCount(PK_STANDARD); i++) + { + // Alle Layouts der MasterPage mitnehmen + String aOldLayoutName(((SdDrawDocument*) this)->GetMasterSdPage(i, PK_STANDARD)->GetLayoutName()); + aOldLayoutName.Erase( aOldLayoutName.SearchAscii( SD_LT_SEPARATOR ) ); + SdStyleSheetVector aCreatedSheets; + pNewStylePool->CopyLayoutSheets(aOldLayoutName, *pOldStylePool, aCreatedSheets ); + } + + pNewModel->NewOrLoadCompleted( DOC_LOADED ); // loaded from source document + } + else if( mbAllocDocSh ) + { + // Es wird eine DocShell erzeugt, welche mit GetAllocedDocSh() zurueckgegeben wird + SdDrawDocument* pDoc = (SdDrawDocument*) this; + pDoc->SetAllocDocSh(FALSE); + pDoc->mxAllocedDocShRef = new ::sd::DrawDocShell( + SFX_CREATE_MODE_EMBEDDED, TRUE, meDocType); + pDoc->mxAllocedDocShRef->DoInitNew(NULL); + pNewModel = pDoc->mxAllocedDocShRef->GetDoc(); + } + else + { + pNewModel = new SdDrawDocument(meDocType, NULL); + } + + return pNewModel; +} + +/************************************************************************* +|* +|* Diese Methode erzeugt eine neue Seite (SdPage) und gibt einen Zeiger +|* darauf zurueck. Die Drawing Engine benutzt diese Methode beim Laden +|* zur Erzeugung von Seiten (deren Typ sie ja nicht kennt, da es ABLEITUNGEN +|* der SdrPage sind). +|* +\************************************************************************/ + +SdrPage* SdDrawDocument::AllocPage(bool bMasterPage) +{ + return new SdPage(*this, NULL, bMasterPage); +} + +/************************************************************************* +|* +|* SetChanged(), das Model wurde geaendert +|* +\************************************************************************/ + +void SdDrawDocument::SetChanged(sal_Bool bFlag) +{ + if (mpDocSh) + { + if (mbNewOrLoadCompleted && mpDocSh->IsEnableSetModified()) + { + // weitergeben an Basisklasse + FmFormModel::SetChanged(bFlag); + + // an ObjectShell weiterleiten + mpDocSh->SetModified(bFlag); + } + } + else + { + // weitergeben an Basisklasse + FmFormModel::SetChanged(bFlag); + } +} + +/************************************************************************* +|* +|* NbcSetChanged(), the model changed, don't call anybody else +|* +\************************************************************************/ + +void SdDrawDocument::NbcSetChanged(sal_Bool bFlag) +{ + // #100237# forward to baseclass + FmFormModel::SetChanged(bFlag); +} + +/************************************************************************* +|* +|* NewOrLoadCompleted +|* +|* Wird gerufen, wenn das Dokument geladen wurde bzw. feststeht, dass es +|* nicht mehr geladen wird. +|* +\************************************************************************/ + +void SdDrawDocument::NewOrLoadCompleted(DocCreationMode eMode) +{ + if (eMode == NEW_DOC) + { + // Neues Dokument: + // Praesentations- und Standardvorlagen erzeugen, + // Pool fuer virtuelle Controls erzeugen + CreateLayoutTemplates(); + CreateDefaultCellStyles(); + + static_cast< SdStyleSheetPool* >( mxStyleSheetPool.get() )->CreatePseudosIfNecessary(); + } + else if (eMode == DOC_LOADED) + { + // Dokument wurde geladen: + + CheckMasterPages(); + + if ( GetMasterSdPageCount(PK_STANDARD) > 1 ) + RemoveUnnecessaryMasterPages( NULL, TRUE, FALSE ); + + for ( USHORT i = 0; i < GetPageCount(); i++ ) + { + // Check for correct layout names + SdPage* pPage = (SdPage*) GetPage( i ); + + if(pPage->TRG_HasMasterPage()) + { + SdPage& rMaster = (SdPage&)pPage->TRG_GetMasterPage(); + + if(rMaster.GetLayoutName() != pPage->GetLayoutName()) + { + pPage->SetLayoutName(rMaster.GetLayoutName()); + } + } + } + + for ( USHORT nPage = 0; nPage < GetMasterPageCount(); nPage++) + { + // LayoutName and PageName must be the same + SdPage* pPage = (SdPage*) GetMasterPage( nPage ); + + String aName( pPage->GetLayoutName() ); + aName.Erase( aName.SearchAscii( SD_LT_SEPARATOR ) ); + + if( aName != pPage->GetName() ) + pPage->SetName( aName ); + } + + // Sprachabhaengige Namen der StandardLayer erzeugen + RestoreLayerNames(); + + // Sprachabhaengige Namen der Vorlagen setzen + static_cast<SdStyleSheetPool*>(mxStyleSheetPool.get())->UpdateStdNames(); + + // Ggf. fehlende Vorlagen erzeugen (es gab z.B. frueher keinen Subtitle) + static_cast<SdStyleSheetPool*>(mxStyleSheetPool.get())->CreatePseudosIfNecessary(); + } + + // Standardvorlage an der Drawing Engine setzen + String aName( SdResId(STR_STANDARD_STYLESHEET_NAME)); + SetDefaultStyleSheet(static_cast<SfxStyleSheet*>(mxStyleSheetPool->Find(aName, SD_STYLE_FAMILY_GRAPHICS))); + + // Draw-Outliner und Dokument Outliner initialisieren, + // aber nicht den globalen Outliner, den der ist ja nicht + // dokumentspezifisch wie StyleSheetPool und StyleRequestHandler + ::Outliner& rDrawOutliner = GetDrawOutliner(); + rDrawOutliner.SetStyleSheetPool((SfxStyleSheetPool*)GetStyleSheetPool()); + ULONG nCntrl = rDrawOutliner.GetControlWord(); + if (mbOnlineSpell) + nCntrl |= EE_CNTRL_ONLINESPELLING; + else + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + rDrawOutliner.SetControlWord(nCntrl); + + // HitTest-Outliner und Dokument Outliner initialisieren, + // aber nicht den globalen Outliner, den der ist ja nicht + // dokumentspezifisch wie StyleSheetPool und StyleRequestHandler + pHitTestOutliner->SetStyleSheetPool((SfxStyleSheetPool*)GetStyleSheetPool()); + + if(mpOutliner) + { + mpOutliner->SetStyleSheetPool((SfxStyleSheetPool*)GetStyleSheetPool()); + } + if(mpInternalOutliner) + { + mpInternalOutliner->SetStyleSheetPool((SfxStyleSheetPool*)GetStyleSheetPool()); + } + + if ( eMode == DOC_LOADED ) + { + // Praesentationsobjekte muessen wieder Listener der entsprechenden + // Vorlagen werden + SdStyleSheetPool* pSPool = (SdStyleSheetPool*) GetStyleSheetPool(); + USHORT nPage, nPageCount; + + // #96323# create missing layout style sheets for broken documents + // that where created with the 5.2 + nPageCount = GetMasterSdPageCount( PK_STANDARD ); + for (nPage = 0; nPage < nPageCount; nPage++) + { + SdPage* pPage = GetMasterSdPage(nPage, PK_STANDARD); + pSPool->CreateLayoutStyleSheets( pPage->GetName(), sal_True ); + } + + // Standard- und Notizseiten: + for (nPage = 0; nPage < GetPageCount(); nPage++) + { + SdPage* pPage = (SdPage*)GetPage(nPage); + NewOrLoadCompleted( pPage, pSPool ); + } + + // Masterpages: + for (nPage = 0; nPage < GetMasterPageCount(); nPage++) + { + SdPage* pPage = (SdPage*)GetMasterPage(nPage); + + NewOrLoadCompleted( pPage, pSPool ); + } + } + + mbNewOrLoadCompleted = TRUE; + + /************************************************************************** + * Alle gelinkten Pages aktualisieren + **************************************************************************/ + SdPage* pPage = NULL; + USHORT nMaxSdPages = GetSdPageCount(PK_STANDARD); + + for (USHORT nSdPage=0; nSdPage < nMaxSdPages; nSdPage++) + { + pPage = (SdPage*) GetSdPage(nSdPage, PK_STANDARD); + + if (pPage && pPage->GetFileName().Len() && pPage->GetBookmarkName().Len()) + { + pPage->SetModel(this); + } + } + + UpdateAllLinks(); + + SetChanged( FALSE ); +} + +/** updates all links, only links in this document should by resolved */ +void SdDrawDocument::UpdateAllLinks() +{ + if ( !pDocLockedInsertingLinks && pLinkManager && pLinkManager->GetLinks().Count() ) + { + pDocLockedInsertingLinks = this; // lock inserting links. only links in this document should by resolved + + pLinkManager->UpdateAllLinks(); // query box: update all links? + + if( pDocLockedInsertingLinks == this ) + pDocLockedInsertingLinks = NULL; // unlock inserting links + } +} + +/** this loops over the presentation objectes of a page and repairs some new settings + from old binary files and resets all default strings for empty presentation objects. +*/ +void SdDrawDocument::NewOrLoadCompleted( SdPage* pPage, SdStyleSheetPool* pSPool ) +{ + const sd::ShapeList& rPresentationShapes( pPage->GetPresentationShapeList() ); + if(!rPresentationShapes.isEmpty()) + { + // Listen mit Titel- und Gliederungsvorlagen erstellen + String aName = pPage->GetLayoutName(); + aName.Erase( aName.SearchAscii( SD_LT_SEPARATOR )); + + List* pOutlineList = pSPool->CreateOutlineSheetList(aName); + SfxStyleSheet* pTitleSheet = (SfxStyleSheet*) + pSPool->GetTitleSheet(aName); + + SdrObject* pObj = rPresentationShapes.getNextShape(0); + + // jetzt nach Titel- und Gliederungstextobjekten suchen und + // Objekte zu Listenern machen + while(pObj) + { + if (pObj->GetObjInventor() == SdrInventor) + { + OutlinerParaObject* pOPO = pObj->GetOutlinerParaObject(); + UINT16 nId = pObj->GetObjIdentifier(); + + if (nId == OBJ_TITLETEXT) + { + if( pOPO && pOPO->GetOutlinerMode() == OUTLINERMODE_DONTKNOW ) + pOPO->SetOutlinerMode( OUTLINERMODE_TITLEOBJECT ); + + // TRUE: harte Attribute dabei nicht loeschen + if (pTitleSheet) + pObj->SetStyleSheet(pTitleSheet, TRUE); + } + else if (nId == OBJ_OUTLINETEXT) + { + if( pOPO && pOPO->GetOutlinerMode() == OUTLINERMODE_DONTKNOW ) + pOPO->SetOutlinerMode( OUTLINERMODE_OUTLINEOBJECT ); + + for (USHORT nSheet = 0; nSheet < 10; nSheet++) + { + SfxStyleSheet* pSheet = (SfxStyleSheet*)pOutlineList->GetObject(nSheet); + if (pSheet) + { + pObj->StartListening(*pSheet); + + if( nSheet == 0) + // Textrahmen hoert auf StyleSheet der Ebene1 + pObj->NbcSetStyleSheet(pSheet, TRUE); + } + } + } + + if (pObj->ISA(SdrTextObj) && pObj->IsEmptyPresObj() && pPage) + { + PresObjKind ePresObjKind = pPage->GetPresObjKind(pObj); + String aString( pPage->GetPresObjText(ePresObjKind) ); + + if (aString.Len()) + { + sd::Outliner* pInternalOutl = GetInternalOutliner(TRUE); + pPage->SetObjText( (SdrTextObj*) pObj, pInternalOutl, ePresObjKind, aString ); + pObj->NbcSetStyleSheet( pPage->GetStyleSheetForPresObj( ePresObjKind ), TRUE ); + pInternalOutl->Clear(); + } + } + } + + pObj = rPresentationShapes.getNextShape(pObj); + } + + delete pOutlineList; + } +} + +/************************************************************************* +|* +|* Lokaler Outliner, welcher fuer den Gliederungsmodus verwendet wird +|* In diesen Outliner werden ggf. OutlinerViews inserted! +|* +\************************************************************************/ + +::sd::Outliner* SdDrawDocument::GetOutliner(BOOL bCreateOutliner) +{ + if (!mpOutliner && bCreateOutliner) + { + mpOutliner = new ::sd::Outliner( this, OUTLINERMODE_TEXTOBJECT ); + + if (mpDocSh) + mpOutliner->SetRefDevice( SD_MOD()->GetRefDevice( *mpDocSh ) ); + + mpOutliner->SetDefTab( nDefaultTabulator ); + mpOutliner->SetStyleSheetPool((SfxStyleSheetPool*)GetStyleSheetPool()); + } + + return(mpOutliner); +} + + +/************************************************************************* +|* +|* Interner Outliner, welcher fuer die Erzeugung von Textobjekten +|* verwendet wird. +|* In diesen Outliner werden keine OutlinerViews inserted! +|* +\************************************************************************/ + +::sd::Outliner* SdDrawDocument::GetInternalOutliner(BOOL bCreateOutliner) +{ + if ( !mpInternalOutliner && bCreateOutliner ) + { + mpInternalOutliner = new ::sd::Outliner( this, OUTLINERMODE_TEXTOBJECT ); + // MT: + // Dieser Outliner wird nur fuer das Erzeugen spezieller Textobjekte + // verwendet. Da in diesen Textobjekten keine Portion-Informationen + // gespeichert werden muessen, kann/soll der Update-Mode immer FALSE bleiben. + mpInternalOutliner->SetUpdateMode( FALSE ); + mpInternalOutliner->EnableUndo( FALSE ); + + if (mpDocSh) + mpInternalOutliner->SetRefDevice( SD_MOD()->GetRefDevice( *mpDocSh ) ); + + mpInternalOutliner->SetDefTab( nDefaultTabulator ); + mpInternalOutliner->SetStyleSheetPool((SfxStyleSheetPool*)GetStyleSheetPool()); + } + + DBG_ASSERT( !mpInternalOutliner || ( mpInternalOutliner->GetUpdateMode() == FALSE ) , "InternalOutliner: UpdateMode = TRUE !" ); + DBG_ASSERT( !mpInternalOutliner || ( mpInternalOutliner->IsUndoEnabled() == FALSE ), "InternalOutliner: Undo = TRUE !" ); + + // MT: Wer ihn vollmuellt, macht ihn auch gleich wieder leer: + // Vorteile: + // a) Keine unnoetigen Clear-Aufrufe + // b) Kein Muell im Speicher. + DBG_ASSERT( !mpInternalOutliner || ( ( mpInternalOutliner->GetParagraphCount() == 1 ) && ( mpInternalOutliner->GetText( mpInternalOutliner->GetParagraph( 0 ) ).Len() == 0 ) ), "InternalOutliner: Nicht leer!" ); + + return mpInternalOutliner; +} + +/************************************************************************* +|* +|* OnlineSpelling ein/aus +|* +\************************************************************************/ + +void SdDrawDocument::SetOnlineSpell(BOOL bIn) +{ + mbOnlineSpell = bIn; + ULONG nCntrl = 0; + + if(mpOutliner) + { + nCntrl = mpOutliner->GetControlWord(); + + if(mbOnlineSpell) + nCntrl |= EE_CNTRL_ONLINESPELLING; + else + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + + mpOutliner->SetControlWord(nCntrl); + } + + if (mpInternalOutliner) + { + nCntrl = mpInternalOutliner->GetControlWord(); + + if (mbOnlineSpell) + nCntrl |= EE_CNTRL_ONLINESPELLING; + else + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + + mpInternalOutliner->SetControlWord(nCntrl); + } + + ::Outliner& rOutliner = GetDrawOutliner(); + + nCntrl = rOutliner.GetControlWord(); + + if (mbOnlineSpell) + nCntrl |= EE_CNTRL_ONLINESPELLING; + else + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + + rOutliner.SetControlWord(nCntrl); + + if (mbOnlineSpell) + { + StartOnlineSpelling(); + } + else + { + StopOnlineSpelling(); + } +} + + +/************************************************************************* +|* +|* OnlineSpelling: Markierung ein/aus +|* +\************************************************************************/ + +uno::Reference< uno::XInterface > SdDrawDocument::createUnoModel() +{ + uno::Reference< uno::XInterface > xModel; + + try + { + if ( mpDocSh ) + xModel = mpDocSh->GetModel(); + } + catch( uno::RuntimeException& ) + { + } + + return xModel; +} + +SvxNumType SdDrawDocument::GetPageNumType() const +{ + return mePageNumType; +} + + + + +void SdDrawDocument::SetPrinterIndependentLayout (sal_Int32 nMode) +{ + // #108104# + + switch (nMode) + { + case ::com::sun::star::document::PrinterIndependentLayout::DISABLED: + case ::com::sun::star::document::PrinterIndependentLayout::ENABLED: + // Just store supported modes and inform the doc shell. + mnPrinterIndependentLayout = nMode; + + // #108104# + // Since it is possible that a SdDrawDocument is constructed without a + // SdDrawDocShell the pointer member mpDocSh needs to be tested + // before the call is executed. This is e.-g. used for copy/paste. + if(mpDocSh) + { + mpDocSh->UpdateRefDevice (); + } + + break; + + default: + // Ignore unknown values. + break; + } +} + +sal_Int32 SdDrawDocument::GetPrinterIndependentLayout (void) +{ + return mnPrinterIndependentLayout; +} + +bool SdDrawDocument::IsStartWithPresentation() const +{ + return mbStartWithPresentation; +} + +void SdDrawDocument::SetStartWithPresentation( bool bStartWithPresentation ) +{ + mbStartWithPresentation = bStartWithPresentation; +} + +// #109538# +void SdDrawDocument::PageListChanged() +{ + mpDrawPageListWatcher->Invalidate(); +} + +// #109538# +void SdDrawDocument::MasterPageListChanged() +{ + mpMasterPageListWatcher->Invalidate(); +} + +void SdDrawDocument::SetCalcFieldValueHdl(::Outliner* pOutliner) +{ + pOutliner->SetCalcFieldValueHdl(LINK(SD_MOD(), SdModule, CalcFieldValueHdl)); +} + +sal_uInt16 SdDrawDocument::GetAnnotationAuthorIndex( const rtl::OUString& rAuthor ) +{ + // force current user to have first color + if( maAnnotationAuthors.empty() ) + { + SvtUserOptions aUserOptions; + maAnnotationAuthors.push_back( aUserOptions.GetFullName() ); + } + + sal_uInt16 idx = 0; + for( std::vector< OUString >::iterator iter( maAnnotationAuthors.begin() ); iter != maAnnotationAuthors.end(); iter++ ) + { + if( (*iter) == rAuthor ) + { + break; + } + idx++; + } + + if( idx == maAnnotationAuthors.size() ) + { + maAnnotationAuthors.push_back( rAuthor ); + } + + return idx; +} + +// eof + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/drawdoc2.cxx b/sd/source/core/drawdoc2.cxx new file mode 100644 index 000000000000..05aa502d67d6 --- /dev/null +++ b/sd/source/core/drawdoc2.cxx @@ -0,0 +1,1585 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + + +#include <com/sun/star/embed/XVisualObject.hpp> +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> +#include <vcl/wrkwin.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/app.hxx> +#include "Outliner.hxx" +#include <editeng/paperinf.hxx> +#include <svx/svdopage.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdotext.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdundo.hxx> +#include <vcl/svapp.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/langitem.hxx> +#include <svl/itempool.hxx> +#include <svx/svdpool.hxx> +#include <editeng/flditem.hxx> + +#include <sfx2/linkmgr.hxx> +#include <editeng/editdata.hxx> +#include <svx/dialogs.hrc> +#include <svx/dialmgr.hxx> // SVX_RESSTR + +#include "eetext.hxx" +#include <svx/svditer.hxx> +#include <svtools/imapobj.hxx> + + +#include "sdresid.hxx" +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include "pglink.hxx" +#include "glob.hrc" +#include "glob.hxx" +#include "stlpool.hxx" +#include "sdiocmpt.hxx" +#include "anminfo.hxx" +#include "imapinfo.hxx" +#include "cusshow.hxx" +#include "undo/undomanager.hxx" + +#include "../ui/inc/DrawDocShell.hxx" +#include "../ui/inc/FrameView.hxx" +#include "../ui/inc/cfgids.hxx" +#include "../ui/inc/strings.hrc" + +#include "PageListWatcher.hxx" +#include <vcl/virdev.hxx> + +using namespace ::sd; + +const long PRINT_OFFSET = 30; // siehe \svx\source\dialog\page.cxx (PB) + +using namespace com::sun::star; + +/************************************************************************* +|* +|* Sucht ein Objekt per Name +|* +\************************************************************************/ + +SdrObject* SdDrawDocument::GetObj(const String& rObjName) const +{ + SdrObject* pObj = NULL; + SdrObject* pObjFound = NULL; + SdPage* pPage = NULL; + + /************************************************************************** + * Zuerst alle Pages durchsuchen + **************************************************************************/ + USHORT nPage = 0; + const USHORT nMaxPages = GetPageCount(); + + while (nPage < nMaxPages && !pObjFound) + { + pPage = (SdPage*) GetPage(nPage); + SdrObjListIter aIter(*pPage, IM_DEEPWITHGROUPS); + + while (aIter.IsMore() && !pObjFound) + { + pObj = aIter.Next(); + + if( ( rObjName == pObj->GetName() ) || + ( SdrInventor == pObj->GetObjInventor() && + OBJ_OLE2 == pObj->GetObjIdentifier() && + rObjName == static_cast< SdrOle2Obj* >( pObj )->GetPersistName() ) ) + { + pObjFound = pObj; + } + } + + nPage++; + } + + /************************************************************************** + * Wenn nicht gefunden, dann alle MasterPages durchsuchen + **************************************************************************/ + nPage = 0; + const USHORT nMaxMasterPages = GetMasterPageCount(); + + while (nPage < nMaxMasterPages && !pObjFound) + { + pPage = (SdPage*) GetMasterPage(nPage); + SdrObjListIter aIter(*pPage, IM_DEEPWITHGROUPS); + + while (aIter.IsMore() && !pObjFound) + { + pObj = aIter.Next(); + + if( ( rObjName == pObj->GetName() ) || + ( SdrInventor == pObj->GetObjInventor() && + OBJ_OLE2 == pObj->GetObjIdentifier() && + rObjName == static_cast< SdrOle2Obj* >( pObj )->GetPersistName() ) ) + { + pObjFound = pObj; + } + } + + nPage++; + } + + return (pObjFound); +} + + +/************************************************************************* +|* +|* Sucht die SdPage per Name +|* +\************************************************************************/ + +USHORT SdDrawDocument::GetPageByName(const String& rPgName, BOOL& rbIsMasterPage) const +{ + SdPage* pPage = NULL; + USHORT nPage = 0; + const USHORT nMaxPages = GetPageCount(); + USHORT nPageNum = SDRPAGE_NOTFOUND; + + rbIsMasterPage = FALSE; + + // Search all regular pages and all notes pages (handout pages are + // ignored.) + while (nPage < nMaxPages && nPageNum == SDRPAGE_NOTFOUND) + { + pPage = const_cast<SdPage*>(static_cast<const SdPage*>( + GetPage(nPage))); + + if (pPage != NULL + && pPage->GetPageKind() != PK_HANDOUT + && pPage->GetName() == rPgName) + { + nPageNum = nPage; + } + + nPage++; + } + + // Search all master pages when not found among non-master pages. + const USHORT nMaxMasterPages = GetMasterPageCount(); + nPage = 0; + + while (nPage < nMaxMasterPages && nPageNum == SDRPAGE_NOTFOUND) + { + pPage = const_cast<SdPage*>(static_cast<const SdPage*>( + GetMasterPage(nPage))); + + if (pPage && pPage->GetName() == rPgName) + { + nPageNum = nPage; + rbIsMasterPage = TRUE; + } + + nPage++; + } + + return nPageNum; +} + +SdPage* SdDrawDocument::GetSdPage(USHORT nPgNum, PageKind ePgKind) const +{ + // #109538# + return mpDrawPageListWatcher->GetSdPage(ePgKind, sal_uInt32(nPgNum)); +} + +USHORT SdDrawDocument::GetSdPageCount(PageKind ePgKind) const +{ + // #109538# + return (sal_uInt16)mpDrawPageListWatcher->GetSdPageCount(ePgKind); +} + +SdPage* SdDrawDocument::GetMasterSdPage(USHORT nPgNum, PageKind ePgKind) +{ + // #109538# + return mpMasterPageListWatcher->GetSdPage(ePgKind, sal_uInt32(nPgNum)); +} + +USHORT SdDrawDocument::GetMasterSdPageCount(PageKind ePgKind) const +{ + // #109538# + return (sal_uInt16)mpMasterPageListWatcher->GetSdPageCount(ePgKind); +} + +/************************************************************************* +|* +|* die in den Seitenobjekten der Notizseiten eingetragenen +|* Seitennummern anpassen +|* +\************************************************************************/ + +void SdDrawDocument::UpdatePageObjectsInNotes(USHORT nStartPos) +{ + USHORT nPageCount = GetPageCount(); + SdPage* pPage = NULL; + + for (USHORT nPage = nStartPos; nPage < nPageCount; nPage++) + { + pPage = (SdPage*)GetPage(nPage); + + // wenn es eine Notizseite ist, Seitenobjekt suchen + // und Nummer korrigieren + if (pPage && pPage->GetPageKind() == PK_NOTES) + { + ULONG nObjCount = pPage->GetObjCount(); + SdrObject* pObj = NULL; + for (ULONG nObj = 0; nObj < nObjCount; nObj++) + { + pObj = pPage->GetObj(nObj); + if (pObj->GetObjIdentifier() == OBJ_PAGE && + pObj->GetObjInventor() == SdrInventor) + { + // das Seitenobjekt stellt die vorhergende Seite (also + // die Zeichenseite) dar + DBG_ASSERTWARNING(nStartPos, "Notizseitenpos. darf nicht 0 sein"); + + DBG_ASSERTWARNING(nPage > 1, "Seitenobjekt darf nicht Handzettel darstellen"); + + if (nStartPos > 0 && nPage > 1) + ((SdrPageObj*)pObj)->SetReferencedPage(GetPage(nPage - 1)); + } + } + } + } +} + +void SdDrawDocument::UpdatePageRelativeURLs(const String& rOldName, const String& rNewName) +{ + if (rNewName.Len() == 0) + return; + + SfxItemPool& pPool(GetPool()); + USHORT nCount = pPool.GetItemCount(EE_FEATURE_FIELD); + for (USHORT nOff = 0; nOff < nCount; nOff++) + { + const SfxPoolItem *pItem = pPool.GetItem(EE_FEATURE_FIELD, nOff); + const SvxFieldItem* pFldItem = dynamic_cast< const SvxFieldItem * > (pItem); + + if(pFldItem) + { + SvxURLField* pURLField = const_cast< SvxURLField* >( dynamic_cast<const SvxURLField*>( pFldItem->GetField() ) ); + + if(pURLField) + { + XubString aURL = pURLField->GetURL(); + + if (aURL.Len() && (aURL.GetChar(0) == 35) && (aURL.Search(rOldName, 1) == 1)) + { + if (aURL.Len() == rOldName.Len() + 1) // standard page name + { + aURL.Erase (1, aURL.Len() - 1); + aURL += rNewName; + pURLField->SetURL(aURL); + } + else + { + const XubString sNotes = SdResId(STR_NOTES); + if (aURL.Len() == rOldName.Len() + 2 + sNotes.Len() && aURL.Search(sNotes, rOldName.Len() + 2) == rOldName.Len() + 2) + { + aURL.Erase (1, aURL.Len() - 1); + aURL += rNewName; + aURL += ' '; + aURL += sNotes; + pURLField->SetURL(aURL); + } + } + } + } + } + } +} + +void SdDrawDocument::UpdatePageRelativeURLs(SdPage* pPage, USHORT nPos, sal_Int32 nIncrement) +{ + bool bNotes = (pPage->GetPageKind() == PK_NOTES); + + SfxItemPool& pPool(GetPool()); + USHORT nCount = pPool.GetItemCount(EE_FEATURE_FIELD); + for (USHORT nOff = 0; nOff < nCount; nOff++) + { + const SfxPoolItem *pItem = pPool.GetItem(EE_FEATURE_FIELD, nOff); + const SvxFieldItem* pFldItem; + + if ((pFldItem = dynamic_cast< const SvxFieldItem * > (pItem)) != 0) + { + SvxURLField* pURLField = const_cast< SvxURLField* >( dynamic_cast<const SvxURLField*>( pFldItem->GetField() ) ); + + if(pURLField) + { + XubString aURL = pURLField->GetURL(); + + if (aURL.Len() && (aURL.GetChar(0) == 35)) + { + XubString aHashSlide('#'); + aHashSlide += SdResId(STR_PAGE); + + if (aURL.CompareTo(aHashSlide, aHashSlide.Len()) == COMPARE_EQUAL) + { + XubString aURLCopy = aURL; + const XubString sNotes = SdResId(STR_NOTES); + + aURLCopy.Erase(0, aHashSlide.Len()); + + bool bNotesLink = (aURLCopy.Len() >= sNotes.Len() + 3 && aURLCopy.Search(sNotes, aURLCopy.Len() - sNotes.Len()) == aURLCopy.Len() - sNotes.Len()); + + if (bNotesLink ^ bNotes) + continue; // no compatible link and page + + if (bNotes) + aURLCopy.Erase(aURLCopy.Len() - sNotes.Len(), sNotes.Len()); + + sal_Int32 number = aURLCopy.ToInt32(); + USHORT realPageNumber = (nPos + 1)/ 2; + + if ( number >= realPageNumber ) + { + // update link page number + number += nIncrement; + aURL.Erase (aHashSlide.Len() + 1, aURL.Len() - aHashSlide.Len() - 1); + aURL += XubString::CreateFromInt32(number); + if (bNotes) + { + aURL += ' '; + aURL += sNotes; + } + pURLField->SetURL(aURL); + } + } + } + } + } + } +} + +/************************************************************************* +|* +|* Seite verschieben +|* +\************************************************************************/ + +void SdDrawDocument::MovePage(USHORT nPgNum, USHORT nNewPos) +{ + // Seite verschieben + FmFormModel::MovePage(nPgNum, nNewPos); + + USHORT nMin = Min(nPgNum, nNewPos); + + UpdatePageObjectsInNotes(nMin); +} + +/************************************************************************* +|* +|* Seite einfuegen +|* +\************************************************************************/ + +void SdDrawDocument::InsertPage(SdrPage* pPage, USHORT nPos) +{ + bool bLast = (nPos == GetPageCount()); + + FmFormModel::InsertPage(pPage, nPos); + + ((SdPage*)pPage)->ConnectLink(); + + UpdatePageObjectsInNotes(nPos); + + if (!bLast) + UpdatePageRelativeURLs(static_cast<SdPage*>( pPage ), nPos, 1); + +} + +/************************************************************************* +|* +|* Seite loeschen +|* +\************************************************************************/ + +void SdDrawDocument::DeletePage(USHORT nPgNum) +{ + FmFormModel::DeletePage(nPgNum); + + UpdatePageObjectsInNotes(nPgNum); +} + +/************************************************************************* +|* +|* Seite entfernen +|* +\************************************************************************/ + +SdrPage* SdDrawDocument::RemovePage(USHORT nPgNum) +{ + SdrPage* pPage = FmFormModel::RemovePage(nPgNum); + + bool bLast = ((nPgNum+1)/2 == (GetPageCount()+1)/2); + + ((SdPage*)pPage)->DisconnectLink(); + ReplacePageInCustomShows( dynamic_cast< SdPage* >( pPage ), 0 ); + UpdatePageObjectsInNotes(nPgNum); + + if (!bLast) + UpdatePageRelativeURLs((SdPage*)pPage, nPgNum, -1); + + return pPage; +} + +// Warning: This is not called for new master pages created from SdrModel::Merge, +// you also have to modify code in SdDrawDocument::Merge! +void SdDrawDocument::InsertMasterPage(SdrPage* pPage, USHORT nPos ) +{ + FmFormModel::InsertMasterPage( pPage, nPos ); + if( pPage && pPage->IsMasterPage() && (static_cast<SdPage*>(pPage)->GetPageKind() == PK_STANDARD) ) + { + // new master page created, add its style family + SdStyleSheetPool* pStylePool = (SdStyleSheetPool*) GetStyleSheetPool(); + if( pStylePool ) + pStylePool->AddStyleFamily( static_cast<SdPage*>(pPage) ); + } +} + +SdrPage* SdDrawDocument::RemoveMasterPage(USHORT nPgNum) +{ + SdPage* pPage = static_cast<SdPage*>(GetMasterPage(nPgNum )); + if( pPage && pPage->IsMasterPage() && (pPage->GetPageKind() == PK_STANDARD) ) + { + // master page removed, remove its style family + SdStyleSheetPool* pStylePool = (SdStyleSheetPool*) GetStyleSheetPool(); + if( pStylePool ) + pStylePool->RemoveStyleFamily( pPage ); + } + + return FmFormModel::RemoveMasterPage(nPgNum); +} + +/************************************************************************* +|* +|* Seiten selektieren +|* +\************************************************************************/ + +void SdDrawDocument::SetSelected(SdPage* pPage, BOOL bSelect) +{ + PageKind ePageKind = pPage->GetPageKind(); + + if (ePageKind == PK_STANDARD) + { + pPage->SetSelected(bSelect); + + const sal_uInt16 nDestPageNum(pPage->GetPageNum() + 1); + SdPage* pNotesPage = 0L; + + if(nDestPageNum < GetPageCount()) + { + pNotesPage = (SdPage*)GetPage(nDestPageNum); + } + + if (pNotesPage && pNotesPage->GetPageKind() == PK_NOTES) + { + pNotesPage->SetSelected(bSelect); + } + } + else if (ePageKind == PK_NOTES) + { + pPage->SetSelected(bSelect); + SdPage* pStandardPage = (SdPage*) GetPage( pPage->GetPageNum() - 1 ); + + if (pStandardPage && pStandardPage->GetPageKind() == PK_STANDARD) + pStandardPage->SetSelected(bSelect); + } +} + +/************************************************************************* +|* +|* Sofern noch keine Seiten vorhanden sind, werden nun Seiten erzeugt +|* +\************************************************************************/ + +void SdDrawDocument::CreateFirstPages( SdDrawDocument* pRefDocument /* = 0 */ ) +{ + /************************************************************************** + * Wenn noch keine Seite im Model vorhanden ist (Datei-Neu), wird + * eine neue Seite eingefuegt + **************************************************************************/ + USHORT nPageCount = GetPageCount(); + + if (nPageCount <= 1) + { + // #i57181# Paper size depends on Language, like in Writer + Size aDefSize = SvxPaperInfo::GetDefaultPaperSize( MAP_100TH_MM ); + + /********************************************************************** + * Handzettel-Seite einfuegen + **********************************************************************/ + SdPage* pHandoutPage = dynamic_cast< SdPage* >( AllocPage(FALSE) ); + + SdPage* pRefPage = NULL; + + if( pRefDocument ) + pRefPage = pRefDocument->GetSdPage( 0, PK_HANDOUT ); + + if( pRefPage ) + { + pHandoutPage->SetSize(pRefPage->GetSize()); + pHandoutPage->SetBorder( pRefPage->GetLftBorder(), pRefPage->GetUppBorder(), pRefPage->GetRgtBorder(), pRefPage->GetLwrBorder() ); + } + else + { + pHandoutPage->SetSize(aDefSize); + pHandoutPage->SetBorder(0, 0, 0, 0); + } + + pHandoutPage->SetPageKind(PK_HANDOUT); + pHandoutPage->SetName( String (SdResId(STR_HANDOUT) ) ); + InsertPage(pHandoutPage, 0); + + /********************************************************************** + * MasterPage einfuegen und an der Handzettel-Seite vermerken + **********************************************************************/ + SdPage* pHandoutMPage = (SdPage*) AllocPage(TRUE); + pHandoutMPage->SetSize( pHandoutPage->GetSize() ); + pHandoutMPage->SetPageKind(PK_HANDOUT); + pHandoutMPage->SetBorder( pHandoutPage->GetLftBorder(), + pHandoutPage->GetUppBorder(), + pHandoutPage->GetRgtBorder(), + pHandoutPage->GetLwrBorder() ); + InsertMasterPage(pHandoutMPage, 0); + pHandoutPage->TRG_SetMasterPage( *pHandoutMPage ); + + /********************************************************************** + * Seite einfuegen + * Sofern nPageCount==1 ist, wurde das Model fuers Clipboad erzeugt. + * Eine Standard-Seite ist daher schon vorhanden. + **********************************************************************/ + SdPage* pPage; + BOOL bClipboard = FALSE; + + if( pRefDocument ) + pRefPage = pRefDocument->GetSdPage( 0, PK_STANDARD ); + + if (nPageCount == 0) + { + pPage = dynamic_cast< SdPage* >( AllocPage(FALSE) ); + + if( pRefPage ) + { + pPage->SetSize( pRefPage->GetSize() ); + pPage->SetBorder( pRefPage->GetLftBorder(), pRefPage->GetUppBorder(), pRefPage->GetRgtBorder(), pRefPage->GetLwrBorder() ); + } + else if (meDocType == DOCUMENT_TYPE_DRAW) + { + // Draw: stets Default-Groesse mit Raendern + pPage->SetSize(aDefSize); + + SfxPrinter* pPrinter = mpDocSh->GetPrinter(FALSE); + if (pPrinter && pPrinter->IsValid()) + { + Size aOutSize(pPrinter->GetOutputSize()); + Point aPageOffset(pPrinter->GetPageOffset()); + aPageOffset -= pPrinter->PixelToLogic( Point() ); + long nOffset = !aPageOffset.X() && !aPageOffset.X() ? 0 : PRINT_OFFSET; + + ULONG nTop = aPageOffset.Y(); + ULONG nLeft = aPageOffset.X(); + ULONG nBottom = Max((long)(aDefSize.Height() - aOutSize.Height() - nTop + nOffset), 0L); + ULONG nRight = Max((long)(aDefSize.Width() - aOutSize.Width() - nLeft + nOffset), 0L); + + pPage->SetBorder(nLeft, nTop, nRight, nBottom); + } + else + { + // The printer is not available. Use a border of 10mm + // on each side instead. + // This has to be kept synchronized with the border + // width set in the + // SvxPageDescPage::PaperSizeSelect_Impl callback. + pPage->SetBorder(1000, 1000, 1000, 1000); + } + } + else + { + // Impress: stets Bildschirmformat, quer + Size aSz( SvxPaperInfo::GetPaperSize(PAPER_SCREEN, MAP_100TH_MM) ); + pPage->SetSize( Size( aSz.Height(), aSz.Width() ) ); + pPage->SetBorder(0, 0, 0, 0); + } + + InsertPage(pPage, 1); + } + else + { + bClipboard = TRUE; + pPage = (SdPage*) GetPage(1); + } + + /********************************************************************** + * MasterPage einfuegen und an der Seite vermerken + **********************************************************************/ + SdPage* pMPage = (SdPage*) AllocPage(TRUE); + pMPage->SetSize( pPage->GetSize() ); + pMPage->SetBorder( pPage->GetLftBorder(), + pPage->GetUppBorder(), + pPage->GetRgtBorder(), + pPage->GetLwrBorder() ); + InsertMasterPage(pMPage, 1); + pPage->TRG_SetMasterPage( *pMPage ); + if( bClipboard ) + pMPage->SetLayoutName( pPage->GetLayoutName() ); + + /********************************************************************** + * Notizen-Seite einfuegen + **********************************************************************/ + SdPage* pNotesPage = (SdPage*) AllocPage(FALSE); + + if( pRefDocument ) + pRefPage = pRefDocument->GetSdPage( 0, PK_NOTES ); + + if( pRefPage ) + { + pNotesPage->SetSize( pRefPage->GetSize() ); + pNotesPage->SetBorder( pRefPage->GetLftBorder(), pRefPage->GetUppBorder(), pRefPage->GetRgtBorder(), pRefPage->GetLwrBorder() ); + } + else + { + // Stets Hochformat + if (aDefSize.Height() >= aDefSize.Width()) + { + pNotesPage->SetSize(aDefSize); + } + else + { + pNotesPage->SetSize( Size(aDefSize.Height(), aDefSize.Width()) ); + } + + pNotesPage->SetBorder(0, 0, 0, 0); + } + pNotesPage->SetPageKind(PK_NOTES); + InsertPage(pNotesPage, 2); + if( bClipboard ) + pNotesPage->SetLayoutName( pPage->GetLayoutName() ); + + /********************************************************************** + * MasterPage einfuegen und an der Notizen-Seite vermerken + **********************************************************************/ + SdPage* pNotesMPage = (SdPage*) AllocPage(TRUE); + pNotesMPage->SetSize( pNotesPage->GetSize() ); + pNotesMPage->SetPageKind(PK_NOTES); + pNotesMPage->SetBorder( pNotesPage->GetLftBorder(), + pNotesPage->GetUppBorder(), + pNotesPage->GetRgtBorder(), + pNotesPage->GetLwrBorder() ); + InsertMasterPage(pNotesMPage, 2); + pNotesPage->TRG_SetMasterPage( *pNotesMPage ); + if( bClipboard ) + pNotesMPage->SetLayoutName( pPage->GetLayoutName() ); + + + if( !pRefPage && (meDocType != DOCUMENT_TYPE_DRAW) ) + pPage->SetAutoLayout( AUTOLAYOUT_TITLE, TRUE, TRUE ); + + mpWorkStartupTimer = new Timer(); + mpWorkStartupTimer->SetTimeoutHdl( LINK(this, SdDrawDocument, WorkStartupHdl) ); + mpWorkStartupTimer->SetTimeout(2000); + mpWorkStartupTimer->Start(); + + SetChanged(FALSE); + } +} + +/************************************************************************* +|* +|* Erzeugt fehlende Notiz und Handzettelseiten (nach PowerPoint-Import) +|* Es wird davon ausgegangen, dass mindestens eine Standard-Seite und +|* eine Standard-MasterPage vorhanden sind. +|* +\************************************************************************/ + +BOOL SdDrawDocument::CreateMissingNotesAndHandoutPages() +{ + BOOL bOK = FALSE; + USHORT nPageCount = GetPageCount(); + + if (nPageCount != 0) + { + /********************************************************************** + * PageKind setzen + **********************************************************************/ + SdPage* pHandoutMPage = (SdPage*) GetMasterPage(0); + pHandoutMPage->SetPageKind(PK_HANDOUT); + + SdPage* pHandoutPage = (SdPage*) GetPage(0); + pHandoutPage->SetPageKind(PK_HANDOUT); + pHandoutPage->TRG_SetMasterPage( *pHandoutMPage ); + + for (USHORT i = 1; i < nPageCount; i = i + 2) + { + SdPage* pPage = (SdPage*) GetPage(i); + + if(!pPage->TRG_HasMasterPage()) + { + // Keine MasterPage gesetzt -> erste Standard-MasterPage nehmen + // (Wenn bei PPT keine Standard-Seite vorhanden war) + pPage->TRG_SetMasterPage(*GetMasterPage(1)); + } + + SdPage* pNotesPage = (SdPage*) GetPage(i+1); + pNotesPage->SetPageKind(PK_NOTES); + + // Notiz-MasterPages setzen + sal_uInt16 nMasterPageAfterPagesMasterPage = (pPage->TRG_GetMasterPage()).GetPageNum() + 1; + pNotesPage->TRG_SetMasterPage(*GetMasterPage(nMasterPageAfterPagesMasterPage)); + } + + bOK = TRUE; + StopWorkStartupDelay(); + SetChanged(FALSE); + } + + return(bOK); +} + +/************************************************************************* +|* +|* - selektierte Seiten hinter genannte Seite schieben +|* (nTargetPage = (USHORT)-1 --> vor erste Seite schieben) +|* - ergibt TRUE, wenn Seiten verschoben wurden +|* +\************************************************************************/ + +BOOL SdDrawDocument::MovePages(USHORT nTargetPage) +{ + SdPage* pTargetPage = NULL; + SdPage* pPage = NULL; + USHORT nPage; + USHORT nNoOfPages = GetSdPageCount(PK_STANDARD); + BOOL bSomethingHappened = FALSE; + + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + BegUndo(String(SdResId(STR_UNDO_MOVEPAGES))); + + // Liste mit selektierten Seiten + List aPageList; + for (nPage = 0; nPage < nNoOfPages; nPage++) + { + pPage = GetSdPage(nPage, PK_STANDARD); + if (pPage->IsSelected()) + { + aPageList.Insert(pPage, LIST_APPEND); + } + } + + // falls noetig, nach vorne hangeln, bis nicht selektierte Seite gefunden + nPage = nTargetPage; + if (nPage != (USHORT)-1) + { + pPage = GetSdPage(nPage, PK_STANDARD); + while (nPage > 0 && pPage->IsSelected()) + { + nPage--; + pPage = GetSdPage(nPage, PK_STANDARD); + } + + if (pPage->IsSelected()) + { + nPage = (USHORT)-1; + } + } + + // vor der ersten Seite einfuegen + if (nPage == (USHORT)-1) + { + while (aPageList.Count() > 0) + { + aPageList.Last(); + + nPage = ( (SdPage*) aPageList.GetCurObject() )->GetPageNum(); + if (nPage != 0) + { + SdrPage* pPg = GetPage(nPage); + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, 1)); + MovePage(nPage, 1); + pPg = GetPage(nPage+1); + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, 2)); + MovePage(nPage+1, 2); + bSomethingHappened = TRUE; + } + aPageList.Remove(); + } + } + // hinter <nPage> einfuegen + else + { + pTargetPage = GetSdPage(nPage, PK_STANDARD); + nTargetPage = nPage; + nTargetPage = 2 * nTargetPage + 1; // PK_STANDARD --> absolut + while (aPageList.Count() > 0) + { + pPage = (SdPage*)aPageList.GetObject(0); + nPage = pPage->GetPageNum(); + if (nPage > nTargetPage) + { + nTargetPage += 2; // hinter (!) der Seite einfuegen + + if (nPage != nTargetPage) + { + SdrPage* pPg = GetPage(nPage); + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, nTargetPage)); + MovePage(nPage, nTargetPage); + pPg = GetPage(nPage+1); + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, nTargetPage+1)); + MovePage(nPage+1, nTargetPage+1); + bSomethingHappened = TRUE; + } + } + else + { + if (nPage != nTargetPage) + { + SdrPage* pPg = GetPage(nPage+1); + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage+1, nTargetPage+1)); + MovePage(nPage+1, nTargetPage+1); + pPg = GetPage(nPage); + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoSetPageNum(*pPg, nPage, nTargetPage)); + MovePage(nPage, nTargetPage); + bSomethingHappened = TRUE; + } + } + aPageList.Remove((ULONG)0); + nTargetPage = pPage->GetPageNum(); + } + } + + if( bUndo ) + EndUndo(); + + return bSomethingHappened; +} + + +/************************************************************************* +|* +|* Anzahl der Links im sfx2::LinkManager zurueckgeben +|* +\************************************************************************/ + +ULONG SdDrawDocument::GetLinkCount() +{ + return ( pLinkManager->GetLinks().Count() ); +} + +/************************************************************************* +|* +|* Language setzen +|* +\************************************************************************/ + +void SdDrawDocument::SetLanguage( const LanguageType eLang, const USHORT nId ) +{ + BOOL bChanged = FALSE; + + if( nId == EE_CHAR_LANGUAGE && meLanguage != eLang ) + { + meLanguage = eLang; + bChanged = TRUE; + } + else if( nId == EE_CHAR_LANGUAGE_CJK && meLanguageCJK != eLang ) + { + meLanguageCJK = eLang; + bChanged = TRUE; + } + else if( nId == EE_CHAR_LANGUAGE_CTL && meLanguageCTL != eLang ) + { + meLanguageCTL = eLang; + bChanged = TRUE; + } + + if( bChanged ) + { + GetDrawOutliner().SetDefaultLanguage( Application::GetSettings().GetLanguage() ); + pHitTestOutliner->SetDefaultLanguage( Application::GetSettings().GetLanguage() ); + pItemPool->SetPoolDefaultItem( SvxLanguageItem( eLang, nId ) ); + SetChanged( bChanged ); + } +} + + +/************************************************************************* +|* +|* Return language +|* +\************************************************************************/ + +LanguageType SdDrawDocument::GetLanguage( const USHORT nId ) const +{ + LanguageType eLangType = meLanguage; + + if( nId == EE_CHAR_LANGUAGE_CJK ) + eLangType = meLanguageCJK; + else if( nId == EE_CHAR_LANGUAGE_CTL ) + eLangType = meLanguageCTL; + + return eLangType; +} + + +/************************************************************************* +|* +|* WorkStartup einleiten +|* +\************************************************************************/ + +IMPL_LINK( SdDrawDocument, WorkStartupHdl, Timer *, EMPTYARG ) +{ + if( mpDocSh ) + mpDocSh->SetWaitCursor( TRUE ); + + BOOL bChanged = IsChanged(); // merken + + // Autolayouts initialisieren + SdPage* pHandoutMPage = GetMasterSdPage(0, PK_HANDOUT); + + if (pHandoutMPage->GetAutoLayout() == AUTOLAYOUT_NONE) + { + // AutoLayout wurde noch nicht umgesetzt -> Initialisieren + pHandoutMPage->SetAutoLayout(AUTOLAYOUT_HANDOUT6, TRUE, TRUE); + } + + SdPage* pPage = GetSdPage(0, PK_STANDARD); + + if (pPage->GetAutoLayout() == AUTOLAYOUT_NONE) + { + // AutoLayout wurde noch nicht umgesetzt -> Initialisieren + pPage->SetAutoLayout(AUTOLAYOUT_NONE, TRUE, TRUE); + } + + SdPage* pNotesPage = GetSdPage(0, PK_NOTES); + + if (pNotesPage->GetAutoLayout() == AUTOLAYOUT_NONE) + { + // AutoLayout wurde noch nicht umgesetzt -> Initialisieren + pNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, TRUE, TRUE); + } + + SetChanged(bChanged || FALSE); + + if( mpDocSh ) + mpDocSh->SetWaitCursor( FALSE ); + return 0; +} + + +/************************************************************************* +|* +|* Wenn der WorkStartupTimer erzeugt worden ist (das erfolgt ausschliesslich +|* in SdDrawViewShell::Consruct() ), so wird der Timer ggf. gestoppt und +|* das WorkStartup eingeleitet +|* +\************************************************************************/ + +void SdDrawDocument::StopWorkStartupDelay() +{ + if (mpWorkStartupTimer) + { + if ( mpWorkStartupTimer->IsActive() ) + { + // Timer war noch nicht abgelaufen -> WorkStartup wird eingeleitet + mpWorkStartupTimer->Stop(); + WorkStartupHdl(NULL); + } + + delete mpWorkStartupTimer; + mpWorkStartupTimer = NULL; + } +} + +/************************************************************************* +|* +|* Wenn der WorkStartupTimer erzeugt worden ist (das erfolgt ausschliesslich +|* in SdDrawViewShell::Consruct() ), so wird der Timer ggf. gestoppt und +|* das WorkStartup eingeleitet +|* +\************************************************************************/ + +SdAnimationInfo* SdDrawDocument::GetAnimationInfo(SdrObject* pObject) const +{ + DBG_ASSERT(pObject, "sd::SdDrawDocument::GetAnimationInfo(), invalid argument!"); + if( pObject ) + return GetShapeUserData( *pObject, false ); + else + return 0; +} + +SdAnimationInfo* SdDrawDocument::GetShapeUserData(SdrObject& rObject, bool bCreate /* = false */ ) +{ + USHORT nUD = 0; + USHORT nUDCount = rObject.GetUserDataCount(); + SdrObjUserData* pUD = 0; + SdAnimationInfo* pRet = 0; + + // gibt es in den User-Daten eine Animationsinformation? + for (nUD = 0; nUD < nUDCount; nUD++) + { + pUD = rObject.GetUserData(nUD); + if((pUD->GetInventor() == SdUDInventor) && (pUD->GetId() == SD_ANIMATIONINFO_ID)) + { + pRet = dynamic_cast<SdAnimationInfo*>(pUD); + break; + } + } + + if( (pRet == 0) && bCreate ) + { + pRet = new SdAnimationInfo( rObject ); + rObject.InsertUserData( pRet); + } + + return pRet; +} + +SdIMapInfo* SdDrawDocument::GetIMapInfo( SdrObject* pObject ) const +{ + DBG_ASSERT(pObject, "ohne Objekt keine IMapInfo"); + + SdrObjUserData* pUserData = NULL; + SdIMapInfo* pIMapInfo = NULL; + USHORT nCount = pObject->GetUserDataCount(); + + // gibt es in den User-Daten eine IMap-Information? + for ( USHORT i = 0; i < nCount; i++ ) + { + pUserData = pObject->GetUserData( i ); + + if ( ( pUserData->GetInventor() == SdUDInventor ) && ( pUserData->GetId() == SD_IMAPINFO_ID ) ) + pIMapInfo = (SdIMapInfo*) pUserData; + } + + return pIMapInfo; +} + +IMapObject* SdDrawDocument::GetHitIMapObject( SdrObject* pObj, + const Point& rWinPoint, + const ::Window& /* rCmpWnd */ ) +{ + SdIMapInfo* pIMapInfo = GetIMapInfo( pObj ); + IMapObject* pIMapObj = NULL; + + if ( pIMapInfo ) + { + const MapMode aMap100( MAP_100TH_MM ); + Size aGraphSize; + Point aRelPoint( rWinPoint ); + ImageMap& rImageMap = (ImageMap&) pIMapInfo->GetImageMap(); + const Rectangle& rRect = pObj->GetLogicRect(); + BOOL bObjSupported = FALSE; + + // HitTest ausfuehren + if ( pObj->ISA( SdrGrafObj ) ) // einfaches Grafik-Objekt + { + const SdrGrafObj* pGrafObj = (const SdrGrafObj*) pObj; + const GeoStat& rGeo = pGrafObj->GetGeoStat(); + SdrGrafObjGeoData* pGeoData = (SdrGrafObjGeoData*) pGrafObj->GetGeoData(); + + // Drehung rueckgaengig + if ( rGeo.nDrehWink ) + RotatePoint( aRelPoint, rRect.TopLeft(), -rGeo.nSin, rGeo.nCos ); + + // Spiegelung rueckgaengig + if ( pGeoData->bMirrored ) + aRelPoint.X() = rRect.Right() + rRect.Left() - aRelPoint.X(); + + // ggf. Unshear: + if ( rGeo.nShearWink ) + ShearPoint( aRelPoint, rRect.TopLeft(), -rGeo.nTan ); + + if ( pGrafObj->GetGrafPrefMapMode().GetMapUnit() == MAP_PIXEL ) + aGraphSize = Application::GetDefaultDevice()->PixelToLogic( pGrafObj->GetGrafPrefSize(), aMap100 ); + else + aGraphSize = OutputDevice::LogicToLogic( pGrafObj->GetGrafPrefSize(), + pGrafObj->GetGrafPrefMapMode(), aMap100 ); + + delete pGeoData; + bObjSupported = TRUE; + } + else if ( pObj->ISA( SdrOle2Obj ) ) // OLE-Objekt + { + aGraphSize = ( (SdrOle2Obj*) pObj )->GetOrigObjSize(); + bObjSupported = TRUE; + } + + // hat alles geklappt, dann HitTest ausfuehren + if ( bObjSupported ) + { + // relativen Mauspunkt berechnen + aRelPoint -= rRect.TopLeft(); + pIMapObj = rImageMap.GetHitIMapObject( aGraphSize, rRect.GetSize(), aRelPoint ); + + // Deaktivierte Objekte wollen wir nicht + if ( pIMapObj && !pIMapObj->IsActive() ) + pIMapObj = NULL; + } + } + + return pIMapObj; +} + +/** this method enforces that the masterpages are in the currect order, + that is at position 1 is a PK_STANDARD masterpage followed by a + PK_NOTES masterpage and so on. # +*/ +void SdDrawDocument::CheckMasterPages() +{ +// RemoveMasterPage(2); // code to test the creation of notes pages + + USHORT nMaxPages = GetMasterPageCount(); + + // we need at least a handout master and one master page + if( nMaxPages < 2 ) + { + return; + } + + SdPage* pPage = NULL; + SdPage* pNotesPage = NULL; + + USHORT nPage; + + // first see if the page order is correct + for( nPage = 1; nPage < nMaxPages; nPage++ ) + { + pPage = static_cast<SdPage*> (GetMasterPage( nPage )); + // if an odd page is not a standard page or an even page is not a notes page + if( ((1 == (nPage & 1)) && (pPage->GetPageKind() != PK_STANDARD) ) || + ((0 == (nPage & 1)) && (pPage->GetPageKind() != PK_NOTES) ) ) + break; // then we have a fatal error + } + + if( nPage < nMaxPages ) + { + // there is a fatal error in the master page order, + // we need to repair the document + sal_Bool bChanged = sal_False; + + nPage = 1; + while( nPage < nMaxPages ) + { + pPage = static_cast<SdPage*> (GetMasterPage( nPage )); + if( pPage->GetPageKind() != PK_STANDARD ) + { + bChanged = sal_True; + USHORT nFound = nPage + 1; + while( nFound < nMaxPages ) + { + pPage = static_cast<SdPage*>(GetMasterPage( nFound )); + if( PK_STANDARD == pPage->GetPageKind() ) + { + MoveMasterPage( nFound, nPage ); + pPage->SetInserted(sal_True); + break; + + } + + nFound++; + } + + // if we don't have any more standard pages, were done + if( nMaxPages == nFound ) + break; + } + + nPage++; + + if( nPage < nMaxPages ) + pNotesPage = static_cast<SdPage*>(GetMasterPage( nPage )); + else + pNotesPage = NULL; + + if( (NULL == pNotesPage) || (pNotesPage->GetPageKind() != PK_NOTES) || ( pPage->GetLayoutName() != pNotesPage->GetLayoutName() ) ) + { + bChanged = sal_True; + + USHORT nFound = nPage + 1; + while( nFound < nMaxPages ) + { + pNotesPage = static_cast<SdPage*>(GetMasterPage( nFound )); + if( (PK_NOTES == pNotesPage->GetPageKind()) && ( pPage->GetLayoutName() == pNotesPage->GetLayoutName() ) ) + { + MoveMasterPage( nFound, nPage ); + pNotesPage->SetInserted(sal_True); + break; + } + + nFound++; + } + + // looks like we lost a notes page + if( nMaxPages == nFound ) + { + // so create one + + // first find a reference notes page for size + SdPage* pRefNotesPage = NULL; + nFound = 0; + while( nFound < nMaxPages ) + { + pRefNotesPage = static_cast<SdPage*>(GetMasterPage( nFound )); + if( PK_NOTES == pRefNotesPage->GetPageKind() ) + break; + nFound++; + } + if( nFound == nMaxPages ) + pRefNotesPage = NULL; + + SdPage* pNewNotesPage = static_cast<SdPage*>(AllocPage(sal_True)); + pNewNotesPage->SetPageKind(PK_NOTES); + if( pRefNotesPage ) + { + pNewNotesPage->SetSize( pRefNotesPage->GetSize() ); + pNewNotesPage->SetBorder( pRefNotesPage->GetLftBorder(), + pRefNotesPage->GetUppBorder(), + pRefNotesPage->GetRgtBorder(), + pRefNotesPage->GetLwrBorder() ); + } + InsertMasterPage(pNewNotesPage, nPage ); + pNewNotesPage->SetLayoutName( pPage->GetLayoutName() ); + pNewNotesPage->SetAutoLayout(AUTOLAYOUT_NOTES, sal_True, sal_True ); + nMaxPages++; + } + } + + nPage++; + } + + // now remove all remaining and unused non PK_STANDARD slides + while( nPage < nMaxPages ) + { + bChanged = sal_True; + + RemoveMasterPage( nPage ); + nMaxPages--; + } + + if( bChanged ) + { + DBG_ERROR( "master pages where in a wrong order" ); + RecalcPageNums( sal_True); + } + } +} + +USHORT SdDrawDocument::CreatePage ( + SdPage* pActualPage, + PageKind ePageKind, + const String& sStandardPageName, + const String& sNotesPageName, + AutoLayout eStandardLayout, + AutoLayout eNotesLayout, + BOOL bIsPageBack, + BOOL bIsPageObj) +{ + SdPage* pPreviousStandardPage; + SdPage* pPreviousNotesPage; + SdPage* pStandardPage; + SdPage* pNotesPage; + + // From the given page determine the standard page and notes page of which + // to take the layout and the position where to insert the new pages. + if (ePageKind == PK_NOTES) + { + pPreviousNotesPage = pActualPage; + USHORT nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2; + pPreviousStandardPage = (SdPage*) GetPage(nNotesPageNum - 3); + eStandardLayout = pPreviousStandardPage->GetAutoLayout(); + } + else + { + pPreviousStandardPage = pActualPage; + USHORT nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2; + pPreviousNotesPage = (SdPage*) GetPage(nStandardPageNum - 1); + eNotesLayout = pPreviousNotesPage->GetAutoLayout(); + } + + // Create new standard page and set it up. + pStandardPage = (SdPage*) AllocPage(FALSE); + + // #108658# + // Set the size here since else the presobj autolayout + // will be wrong. + pStandardPage->SetSize( pPreviousStandardPage->GetSize() ); + pStandardPage->SetBorder( pPreviousStandardPage->GetLftBorder(), + pPreviousStandardPage->GetUppBorder(), + pPreviousStandardPage->GetRgtBorder(), + pPreviousStandardPage->GetLwrBorder() ); + + // Use master page of current page. + pStandardPage->TRG_SetMasterPage(pPreviousStandardPage->TRG_GetMasterPage()); + + // User layout of current standard page. + pStandardPage->SetLayoutName( pPreviousStandardPage->GetLayoutName() ); + pStandardPage->SetAutoLayout(eStandardLayout, TRUE); + pStandardPage->setHeaderFooterSettings( pPreviousStandardPage->getHeaderFooterSettings() ); + + // transition settings of current page + pStandardPage->setTransitionType( pPreviousStandardPage->getTransitionType() ); + pStandardPage->setTransitionSubtype( pPreviousStandardPage->getTransitionSubtype() ); + pStandardPage->setTransitionDirection( pPreviousStandardPage->getTransitionDirection() ); + pStandardPage->setTransitionFadeColor( pPreviousStandardPage->getTransitionFadeColor() ); + pStandardPage->setTransitionDuration( pPreviousStandardPage->getTransitionDuration() ); + + // apply previous animation timing + pStandardPage->SetPresChange( pPreviousStandardPage->GetPresChange() ); + pStandardPage->SetTime( pPreviousStandardPage->GetTime() ); + + // Create new notes page and set it up. + pNotesPage = (SdPage*) AllocPage(FALSE); + pNotesPage->SetPageKind(PK_NOTES); + + // Use master page of current page. + pNotesPage->TRG_SetMasterPage(pPreviousNotesPage->TRG_GetMasterPage()); + + // Use layout of current notes page. + pNotesPage->SetLayoutName( pPreviousNotesPage->GetLayoutName() ); + pNotesPage->SetAutoLayout(eNotesLayout, TRUE); + pNotesPage->setHeaderFooterSettings( pPreviousNotesPage->getHeaderFooterSettings() ); + + return InsertPageSet ( + pActualPage, ePageKind, + sStandardPageName, + sNotesPageName, + eStandardLayout, + eNotesLayout, + bIsPageBack, + bIsPageObj, + + pStandardPage, + pNotesPage); +} + + + + +USHORT SdDrawDocument::DuplicatePage (USHORT nPageNum) +{ + PageKind ePageKind = PK_STANDARD; + + // Get current page. + SdPage* pActualPage = GetSdPage(nPageNum, ePageKind); + + // Get background flags. + SdrLayerAdmin& rLayerAdmin = GetLayerAdmin(); + BYTE aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), FALSE); + BYTE aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), FALSE); + SetOfByte aVisibleLayers = pActualPage->TRG_GetMasterPageVisibleLayers(); + + // Get layout from current page. + AutoLayout eAutoLayout = pActualPage->GetAutoLayout(); + + return DuplicatePage ( + pActualPage, ePageKind, + // No names for the new slides. + String(), String(), + eAutoLayout, eAutoLayout, + aVisibleLayers.IsSet(aBckgrnd), + aVisibleLayers.IsSet(aBckgrndObj)); +} + + + + +USHORT SdDrawDocument::DuplicatePage ( + SdPage* pActualPage, + PageKind ePageKind, + const String& sStandardPageName, + const String& sNotesPageName, + AutoLayout eStandardLayout, + AutoLayout eNotesLayout, + BOOL bIsPageBack, + BOOL bIsPageObj) +{ + SdPage* pPreviousStandardPage; + SdPage* pPreviousNotesPage; + SdPage* pStandardPage; + SdPage* pNotesPage; + + // From the given page determine the standard page and the notes page + // of which to make copies. + if (ePageKind == PK_NOTES) + { + pPreviousNotesPage = pActualPage; + USHORT nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2; + pPreviousStandardPage = (SdPage*) GetPage(nNotesPageNum - 3); + } + else + { + pPreviousStandardPage = pActualPage; + USHORT nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2; + pPreviousNotesPage = (SdPage*) GetPage(nStandardPageNum - 1); + } + + // Create duplicates of a standard page and the associated notes page. + pStandardPage = (SdPage*) pPreviousStandardPage->Clone(); + pNotesPage = (SdPage*) pPreviousNotesPage->Clone(); + + return InsertPageSet ( + pActualPage, ePageKind, + sStandardPageName, + sNotesPageName, + eStandardLayout, + eNotesLayout, + bIsPageBack, + bIsPageObj, + + pStandardPage, + pNotesPage); +} + + + + +USHORT SdDrawDocument::InsertPageSet ( + SdPage* pActualPage, + PageKind ePageKind, + const String& sStandardPageName, + const String& sNotesPageName, + AutoLayout eStandardLayout, + AutoLayout eNotesLayout, + BOOL bIsPageBack, + BOOL bIsPageObj, + + SdPage* pStandardPage, + SdPage* pNotesPage) +{ + SdPage* pPreviousStandardPage; + SdPage* pPreviousNotesPage; + USHORT nStandardPageNum; + USHORT nNotesPageNum; + String aStandardPageName = sStandardPageName; + String aNotesPageName = sNotesPageName; + + // Gather some information about the standard page and the notes page + // that are to be inserted. This makes sure that there is allways one + // standard page followed by one notes page. + if (ePageKind == PK_NOTES) + { + pPreviousNotesPage = pActualPage; + nNotesPageNum = pPreviousNotesPage->GetPageNum() + 2; + pPreviousStandardPage = (SdPage*) GetPage(nNotesPageNum - 3); + nStandardPageNum = nNotesPageNum - 1; + eStandardLayout = pPreviousStandardPage->GetAutoLayout(); + } + else + { + pPreviousStandardPage = pActualPage; + nStandardPageNum = pPreviousStandardPage->GetPageNum() + 2; + pPreviousNotesPage = (SdPage*) GetPage(nStandardPageNum - 1); + nNotesPageNum = nStandardPageNum + 1; + aNotesPageName = aStandardPageName; + eNotesLayout = pPreviousNotesPage->GetAutoLayout(); + } + + + // Set up and insert the standard page. + SetupNewPage ( + pPreviousStandardPage, + pStandardPage, + aStandardPageName, + nStandardPageNum, + bIsPageBack, + bIsPageObj); + + // Set up and insert the notes page. + pNotesPage->SetPageKind(PK_NOTES); + SetupNewPage ( + pPreviousNotesPage, + pNotesPage, + aNotesPageName, + nNotesPageNum, + bIsPageBack, + bIsPageObj); + + // Return an index that allows the caller to access the newly inserted + // pages by using GetSdPage(). + return pStandardPage->GetPageNum() / 2; +} + + + + +void SdDrawDocument::SetupNewPage ( + SdPage* pPreviousPage, + SdPage* pPage, + const String& sPageName, + USHORT nInsertionPoint, + BOOL bIsPageBack, + BOOL bIsPageObj) +{ + if (pPreviousPage != NULL) + { + pPage->SetSize( pPreviousPage->GetSize() ); + pPage->SetBorder( pPreviousPage->GetLftBorder(), + pPreviousPage->GetUppBorder(), + pPreviousPage->GetRgtBorder(), + pPreviousPage->GetLwrBorder() ); + } + pPage->SetName(sPageName); + + InsertPage(pPage, nInsertionPoint); + + if (pPreviousPage != NULL) + { + SdrLayerAdmin& rLayerAdmin = GetLayerAdmin(); + BYTE aBckgrnd = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRND)), FALSE); + BYTE aBckgrndObj = rLayerAdmin.GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), FALSE); + SetOfByte aVisibleLayers = pPreviousPage->TRG_GetMasterPageVisibleLayers(); + aVisibleLayers.Set(aBckgrnd, bIsPageBack); + aVisibleLayers.Set(aBckgrndObj, bIsPageObj); + pPage->TRG_SetMasterPageVisibleLayers(aVisibleLayers); + } +} + +sd::UndoManager* SdDrawDocument::GetUndoManager() const +{ + return mpDocSh ? dynamic_cast< sd::UndoManager* >(mpDocSh->GetUndoManager()) : 0; +} + +// eof + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/drawdoc3.cxx b/sd/source/core/drawdoc3.cxx new file mode 100644 index 000000000000..f8559d980f16 --- /dev/null +++ b/sd/source/core/drawdoc3.cxx @@ -0,0 +1,2037 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + + +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +#include "comphelper/anytostring.hxx" +#include "cppuhelper/exc_hlp.hxx" + +#include <utility> +#include <algorithm> +#include <vcl/wrkwin.hxx> +#include <sfx2/docfile.hxx> +#include <sot/storage.hxx> +#include <sfx2/app.hxx> +#include <svl/itemset.hxx> + +#include <unotools/ucbstreamhelper.hxx> +#include <sfx2/fcontnr.hxx> +#include <svx/svdopath.hxx> +#include <svx/svditer.hxx> +#include <svl/style.hxx> +#include <sfx2/linkmgr.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdundo.hxx> +#include <vcl/msgbox.hxx> +#include <sot/storage.hxx> +#include <sot/formats.hxx> + +#include <set> + +#include "glob.hrc" +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include "stlpool.hxx" +#include "sdresid.hxx" +#include "sdiocmpt.hxx" +#include "strmname.h" +#include "anminfo.hxx" + +#include "../ui/inc/unmovss.hxx" +#include "../ui/inc/unchss.hxx" +#include "../ui/inc/unprlout.hxx" +#include "../ui/inc/DrawDocShell.hxx" +#include "../ui/inc/GraphicDocShell.hxx" +#include "../ui/inc/ViewShell.hxx" +#include "../ui/inc/View.hxx" +#include "../ui/inc/cfgids.hxx" +#include "../ui/inc/strings.hrc" + +using namespace ::com::sun::star; + +#define POOL_BUFFER_SIZE (USHORT)32768 +#define BASIC_BUFFER_SIZE (USHORT)8192 +#define DOCUMENT_BUFFER_SIZE (USHORT)32768 + +/************************************************************************* +|* +|* Oeffnet ein Bookmark-Dokument +|* +\************************************************************************/ + +SdDrawDocument* SdDrawDocument::OpenBookmarkDoc(SfxMedium& rMedium) +{ + BOOL bOK = TRUE; + SdDrawDocument* pBookmarkDoc = NULL; + String aBookmarkName = rMedium.GetName(); + const SfxFilter* pFilter = rMedium.GetFilter(); + if ( !pFilter ) + { + rMedium.UseInteractionHandler( TRUE ); + SFX_APP()->GetFilterMatcher().GuessFilter( rMedium, &pFilter ); + } + + if ( !pFilter ) + { + bOK = FALSE; + } + else if ( maBookmarkFile != aBookmarkName && aBookmarkName.Len() ) + { + BOOL bCreateGraphicShell = pFilter->GetServiceName().EqualsAscii( "com.sun.star.drawing.DrawingDocument" ); + BOOL bCreateImpressShell = pFilter->GetServiceName().EqualsAscii( "com.sun.star.presentation.PresentationDocument" ); + if ( bCreateGraphicShell || bCreateImpressShell ) + { + CloseBookmarkDoc(); + + // Es wird eine DocShell erzeugt, da in dem Dokument OLE-Objekte + // enthalten sein koennten (Persist) + // Wenn dem nicht so waere, so koennte man auch das Model + // direkt laden + if ( bCreateGraphicShell ) + // Draw + mxBookmarkDocShRef = new ::sd::GraphicDocShell(SFX_CREATE_MODE_STANDARD, TRUE); + else + // Impress + mxBookmarkDocShRef = new ::sd::DrawDocShell(SFX_CREATE_MODE_STANDARD, TRUE); + + bOK = mxBookmarkDocShRef->DoLoad(&rMedium); + if( bOK ) + { + maBookmarkFile = aBookmarkName; + pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); + } + } + } + + DBG_ASSERT(aBookmarkName.Len(), "Empty document name!"); + + if (!bOK) + { + ErrorBox aErrorBox( NULL, (WinBits)WB_OK, String(SdResId(STR_READ_DATA_ERROR))); + aErrorBox.Execute(); + + CloseBookmarkDoc(); + pBookmarkDoc = NULL; + } + else if (mxBookmarkDocShRef.Is()) + { + pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); + } + + return(pBookmarkDoc); +} + +/************************************************************************* +|* +|* Oeffnet ein Bookmark-Dokument +|* +\************************************************************************/ + +SdDrawDocument* SdDrawDocument::OpenBookmarkDoc(const String& rBookmarkFile) +{ + SdDrawDocument* pBookmarkDoc = NULL; + + if (maBookmarkFile != rBookmarkFile && rBookmarkFile.Len()) + { + SfxMedium* pMedium = new SfxMedium( rBookmarkFile, STREAM_READ, FALSE ); + pBookmarkDoc = OpenBookmarkDoc(*pMedium); + } + else if (mxBookmarkDocShRef.Is()) + { + pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); + } + + return(pBookmarkDoc); +} + +/************************************************************************* +|* +|* Fuegt ein Bookmark (Seite oder Objekt) ein +|* +\************************************************************************/ + +BOOL SdDrawDocument::InsertBookmark( + List* pBookmarkList, // Liste der Namen der einzufuegenden Bookmarks + List* pExchangeList, // Liste der zu verwendenen Namen + BOOL bLink, // Bookmarks sollen als Verknuepfung eingefuegt werden + BOOL bReplace, // Aktuellen Seiten (Standard&Notiz) werden ersetzt + USHORT nInsertPos, // Einfuegeposition fuer Seiten + BOOL bNoDialogs, // Keine Dialoge anzeigen + ::sd::DrawDocShell* pBookmarkDocSh, // Wenn gesetzt, so ist dieses das Source-Dokument + BOOL bCopy, // Seiten werden kopiert + Point* pObjPos) // Einfuegeposition fuer Objekte +{ + BOOL bOK = TRUE; + BOOL bInsertPages = FALSE; + + if (!pBookmarkList) + { + /********************************************************************** + * Alle Seiten werden eingefuegt + **********************************************************************/ + bInsertPages = TRUE; + } + else + { + SdDrawDocument* pBookmarkDoc = NULL; + String aBookmarkName; + + if (pBookmarkDocSh) + { + pBookmarkDoc = pBookmarkDocSh->GetDoc(); + aBookmarkName = pBookmarkDocSh->GetMedium()->GetName(); + } + else if ( mxBookmarkDocShRef.Is() ) + { + pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); + aBookmarkName = maBookmarkFile; + } + else + bOK = FALSE; + + for (USHORT nPos = 0; bOK && ( nPos < pBookmarkList->Count() ) && !bInsertPages; nPos++) + { + /****************************************************************** + * Gibt es in der Bookmark-Liste einen Seitennamen? + ******************************************************************/ + String aBMPgName (*(String*) pBookmarkList->GetObject(nPos)); + BOOL bIsMasterPage; + + if( pBookmarkDoc->GetPageByName( aBMPgName, bIsMasterPage ) != SDRPAGE_NOTFOUND ) + { + // Seite gefunden + bInsertPages = TRUE; + } + } + } + + if ( bOK && bInsertPages ) + { + // Zuerst werden alle Seiten-Bookmarks eingefuegt + bOK = InsertBookmarkAsPage(pBookmarkList, pExchangeList, bLink, bReplace, + nInsertPos, bNoDialogs, pBookmarkDocSh, bCopy, TRUE, FALSE); + } + + if ( bOK && pBookmarkList ) + { + // Es werden alle Objekt-Bookmarks eingefuegt + bOK = InsertBookmarkAsObject(pBookmarkList, pExchangeList, bLink, + pBookmarkDocSh, pObjPos); + } + + return bOK; +} + +/************************************************************************* +|* +|* Fuegt ein Bookmark als Seite ein +|* +\************************************************************************/ + +/** Concrete incarnations get called by IterateBookmarkPages, for + every page in the bookmark document/list + */ +class SdDrawDocument::InsertBookmarkAsPage_PageFunctorBase +{ +public: + virtual ~InsertBookmarkAsPage_PageFunctorBase() = 0; + virtual void operator()( SdDrawDocument&, SdPage* ) = 0; +}; + +SdDrawDocument::InsertBookmarkAsPage_PageFunctorBase::~InsertBookmarkAsPage_PageFunctorBase() +{ +} + +void SdDrawDocument::IterateBookmarkPages( SdDrawDocument* pBookmarkDoc, List* pBookmarkList, USHORT nBMSdPageCount, + SdDrawDocument::InsertBookmarkAsPage_PageFunctorBase& rPageIterator ) +{ + // + // #96029# Refactored copy'n'pasted layout name collection from InsertBookmarkAsPage + // + int nPos, nEndPos; + + if( !pBookmarkList ) + { + // no list? whole source document + nEndPos = nBMSdPageCount; + } + else + { + // bookmark list? number of entries + nEndPos = pBookmarkList->Count(); + } + + SdPage* pBMPage; + + // iterate over number of pages to insert + for (nPos = 0; nPos < nEndPos; ++nPos) + { + // the master page associated to the nPos'th page to insert + SdPage* pBMMPage = NULL; + + if( !pBookmarkList ) + { + // simply take master page of nPos'th page in source document + pBMMPage = (SdPage*)(&(pBookmarkDoc->GetSdPage((USHORT)nPos, PK_STANDARD)->TRG_GetMasterPage())); + } + else + { + // fetch nPos'th entry from bookmark list, and determine master page + String aBMPgName (*(String*) pBookmarkList->GetObject(nPos)); + BOOL bIsMasterPage; + + USHORT nBMPage = pBookmarkDoc->GetPageByName( aBMPgName, bIsMasterPage ); + + if (nBMPage != SDRPAGE_NOTFOUND) + { + pBMPage = (SdPage*) pBookmarkDoc->GetPage(nBMPage); + } + else + { + pBMPage = NULL; + } + + // enforce that bookmarked page is a standard page and not already a master page + if (pBMPage && pBMPage->GetPageKind()==PK_STANDARD && !pBMPage->IsMasterPage()) + { + const USHORT nBMSdPage = (nBMPage - 1) / 2; + pBMMPage = (SdPage*) (&(pBookmarkDoc->GetSdPage(nBMSdPage, PK_STANDARD)->TRG_GetMasterPage())); + } + } + + // successfully determined valid (bookmarked) page? + if( pBMMPage ) + { + // yes, call functor + rPageIterator( *this, pBMMPage ); + } + } +} + +class InsertBookmarkAsPage_FindDuplicateLayouts : public SdDrawDocument::InsertBookmarkAsPage_PageFunctorBase +{ +public: + InsertBookmarkAsPage_FindDuplicateLayouts( List* pLayoutsToTransfer, SdDrawDocument* pBookmarkDoc, + List* pBookmarkList, USHORT nBMSdPageCount ) : + mpLayoutsToTransfer(pLayoutsToTransfer), mpBookmarkDoc(pBookmarkDoc), + mpBookmarkList(pBookmarkList), mnBMSdPageCount(nBMSdPageCount) {} + virtual ~InsertBookmarkAsPage_FindDuplicateLayouts() {}; + virtual void operator()( SdDrawDocument&, SdPage* ); +private: + List* mpLayoutsToTransfer; + SdDrawDocument* mpBookmarkDoc; + List* mpBookmarkList; + USHORT mnBMSdPageCount; +}; + +void InsertBookmarkAsPage_FindDuplicateLayouts::operator()( SdDrawDocument& rDoc, SdPage* pBMMPage ) +{ + // now check for duplicate masterpage and layout names + // =================================================== + + String sFullLayoutName( pBMMPage->GetLayoutName() ); + String* pLayout = new String(sFullLayoutName); + pLayout->Erase( pLayout->SearchAscii( SD_LT_SEPARATOR )); + + String* pTest = (String*) mpLayoutsToTransfer->First(); + BOOL bFound = FALSE; + + while (pTest && !bFound) // found yet? + { + if (*pLayout == *pTest) + bFound = TRUE; + else + pTest = (String*)mpLayoutsToTransfer->Next(); + } + + const USHORT nMPageCount = rDoc.GetMasterPageCount(); + for (USHORT nMPage = 0; nMPage < nMPageCount && !bFound; nMPage++) + { + /************************************************************** + * Gibt es die Layouts schon im Dokument? + **************************************************************/ + SdPage* pTestPage = (SdPage*) rDoc.GetMasterPage(nMPage); + String aTest(pTestPage->GetLayoutName()); + aTest.Erase( aTest.SearchAscii( SD_LT_SEPARATOR )); + + if (aTest == *pLayout) + bFound = TRUE; + } + + if (!bFound) + mpLayoutsToTransfer->Insert(pLayout, LIST_APPEND); + else + delete pLayout; +} + + +BOOL SdDrawDocument::InsertBookmarkAsPage( + List* pBookmarkList, + List* pExchangeList, // Liste der zu verwendenen Namen + BOOL bLink, + BOOL bReplace, + USHORT nInsertPos, + BOOL bNoDialogs, + ::sd::DrawDocShell* pBookmarkDocSh, + BOOL bCopy, + BOOL bMergeMasterPages, + BOOL bPreservePageNames) +{ + BOOL bOK = TRUE; + BOOL bContinue = TRUE; + BOOL bScaleObjects = FALSE; + USHORT nReplacedStandardPages = 0; + + SdDrawDocument* pBookmarkDoc = NULL; + String aBookmarkName; + + if (pBookmarkDocSh) + { + pBookmarkDoc = pBookmarkDocSh->GetDoc(); + + if (pBookmarkDocSh->GetMedium()) + { + aBookmarkName = pBookmarkDocSh->GetMedium()->GetName(); + } + } + else if ( mxBookmarkDocShRef.Is() ) + { + pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); + aBookmarkName = maBookmarkFile; + } + else + { + return FALSE; + } + + const USHORT nSdPageCount = GetSdPageCount(PK_STANDARD); + const USHORT nBMSdPageCount = pBookmarkDoc->GetSdPageCount(PK_STANDARD); + const USHORT nMPageCount = GetMasterPageCount(); + + if (nSdPageCount==0 || nBMSdPageCount==0 || nMPageCount==0) + { + bContinue = bOK = FALSE; + return(bContinue); + } + + // Store the size and some other properties of the first page and notes + // page so that inserted pages can be properly scaled even when inserted + // before the first page. + // Note that the pointers are used later on as general page pointers. + SdPage* pRefPage = GetSdPage(0, PK_STANDARD); + Size aSize(pRefPage->GetSize()); + INT32 nLeft = pRefPage->GetLftBorder(); + INT32 nRight = pRefPage->GetRgtBorder(); + INT32 nUpper = pRefPage->GetUppBorder(); + INT32 nLower = pRefPage->GetLwrBorder(); + Orientation eOrient = pRefPage->GetOrientation(); + + SdPage* pNPage = GetSdPage(0, PK_NOTES); + Size aNSize(GetSdPage(0, PK_NOTES)->GetSize()); + INT32 nNLeft = pNPage->GetLftBorder(); + INT32 nNRight = pNPage->GetRgtBorder(); + INT32 nNUpper = pNPage->GetUppBorder(); + INT32 nNLower = pNPage->GetLwrBorder(); + Orientation eNOrient = pRefPage->GetOrientation(); + + // Seitengroesse und -raender an die Werte der letzten + // Seiten anpassen? + pRefPage = GetSdPage(nSdPageCount - 1, PK_STANDARD); + + if( bNoDialogs ) + { + if( !pBookmarkList ) + bScaleObjects = pRefPage->IsScaleObjects(); + else + bScaleObjects = TRUE; + } + else + { + SdPage* pBMPage = pBookmarkDoc->GetSdPage(0,PK_STANDARD); + + if (pBMPage->GetSize() != pRefPage->GetSize() || + pBMPage->GetLftBorder() != pRefPage->GetLftBorder() || + pBMPage->GetRgtBorder() != pRefPage->GetRgtBorder() || + pBMPage->GetUppBorder() != pRefPage->GetUppBorder() || + pBMPage->GetLwrBorder() != pRefPage->GetLwrBorder()) + { + String aStr(SdResId(STR_SCALE_OBJECTS)); + USHORT nBut = QueryBox( NULL, WB_YES_NO_CANCEL, aStr).Execute(); + + bScaleObjects = nBut == RET_YES; + bContinue = nBut != RET_CANCEL; + + if (!bContinue) + { + return(bContinue); + } + } + } + + + /************************************************************************** + |* Die benoetigten Praesentations-StyleSheets ermitteln und vor + |* den Seiten transferieren, sonst verlieren die Textobjekte + |* beim Transfer den Bezug zur Vorlage + \*************************************************************************/ + SfxUndoManager* pUndoMgr = NULL; + if( mpDocSh ) + { + pUndoMgr = mpDocSh->GetUndoManager(); + pUndoMgr->EnterListAction(String(SdResId(STR_UNDO_INSERTPAGES)), String()); + } + + List* pLayoutsToTransfer = new List; + + // + // #96029# Refactored copy'n'pasted layout name collection into IterateBookmarkPages + // + InsertBookmarkAsPage_FindDuplicateLayouts aSearchFunctor( pLayoutsToTransfer, pBookmarkDoc, + pBookmarkList, nBMSdPageCount ); + IterateBookmarkPages( pBookmarkDoc, pBookmarkList, nBMSdPageCount, aSearchFunctor ); + + + /************************************************************************** + * Die tatsaechlich benoetigten Vorlagen kopieren + **************************************************************************/ + SdStyleSheetPool* pBookmarkStyleSheetPool = + (SdStyleSheetPool*) pBookmarkDoc->GetStyleSheetPool(); + String* pLayout = (String*) pLayoutsToTransfer->First(); + + // Wenn Vorlagen kopiert werden muessen, dann muessen auch die + // MasterPages kopiert werden! + if( pLayout ) + bMergeMasterPages = TRUE; + + while (pLayout) + { + SdStyleSheetVector aCreatedStyles; + + ((SdStyleSheetPool*)GetStyleSheetPool())->CopyLayoutSheets(*pLayout, *pBookmarkStyleSheetPool,aCreatedStyles); + + if(!aCreatedStyles.empty()) + { + if( pUndoMgr ) + { + SdMoveStyleSheetsUndoAction* pMovStyles = new SdMoveStyleSheetsUndoAction(this, aCreatedStyles, TRUE); + pUndoMgr->AddUndoAction(pMovStyles); + } + } + + delete pLayout; + + pLayout = (String*)pLayoutsToTransfer->Next(); + } + + delete pLayoutsToTransfer; + + /************************************************************************** + * Dokument einfuegen + **************************************************************************/ + + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + BegUndo(String(SdResId(STR_UNDO_INSERTPAGES))); + + if (!pBookmarkList) + { + if (nInsertPos >= GetPageCount()) + { + // Seiten werden hinten angefuegt + nInsertPos = GetPageCount(); + } + + USHORT nActualInsertPos = nInsertPos; + + List aNameList; + std::set<USHORT> aRenameSet; + USHORT nBMSdPage; + + for (nBMSdPage=0; nBMSdPage < nBMSdPageCount; nBMSdPage++) + { + SdPage* pBMPage = pBookmarkDoc->GetSdPage(nBMSdPage, PK_STANDARD); + String pName( pBMPage->GetName() ); + BOOL bIsMasterPage; + + if (bLink) + { + // Es werden sich die Namen aller Seiten gemerkt + aNameList.Insert(new String(pName), nBMSdPage); + } + + // #95677# Have to check for duplicate names here, too + // #67905# don't change name if source and dest model are the same! + if( pBookmarkDoc != this && + GetPageByName(pName, bIsMasterPage ) != SDRPAGE_NOTFOUND ) + { + // #95991# delay renaming *after* pages are copied (might destroy source otherwise) + aRenameSet.insert(nBMSdPage); + } + } + + Merge(*pBookmarkDoc, + 1, // Nicht die Handzettelseite + 0xFFFF, // Aber alle anderen + nActualInsertPos, // An Position einfuegen + bMergeMasterPages, // MasterPages mitnehmen + FALSE, // Aber nur die benoetigten MasterPages + TRUE, // Undo-Aktion erzeugen + bCopy); // Seiten kopieren (oder mergen) + + for (nBMSdPage=0; nBMSdPage < nBMSdPageCount; nBMSdPage++) + { + SdPage* pPage = (SdPage*) GetPage(nActualInsertPos); + SdPage* pNotesPage = (SdPage*) GetPage(nActualInsertPos+1); + String* pName = (String*) aNameList.GetObject(nBMSdPage); + + // #95991# delay renaming *after* pages are copied (might destroy source otherwise) + if( aRenameSet.find(nBMSdPage) != aRenameSet.end() ) + { + // Seitenname schon vorhanden -> Defaultname + // fuer Standard & Notizseite + pPage->SetName(String()); + pNotesPage->SetName(String()); + } + + if (bLink) + { + // Nun werden die Link-Namen zusammengestellt + pPage->SetFileName(aBookmarkName); + pPage->SetBookmarkName(*(pName)); + delete pName; + pPage->SetModel(this); + } + + nActualInsertPos += 2; + } + } + else + { + /********************************************************************** + * Ausgewaehlte Seiten einfuegen + **********************************************************************/ + SdPage* pBMPage; + + if (nInsertPos >= GetPageCount()) + { + // Seiten werden hinten angefuegt + bReplace = FALSE; + nInsertPos = GetPageCount(); + } + + USHORT nActualInsertPos = nInsertPos; + + for (USHORT nPos = 0; nPos < pBookmarkList->Count(); nPos++) + { + /************************************************************** + * Namen der Bookmark-Seiten aus Liste holen + **************************************************************/ + String aPgName(*(String*) pBookmarkList->GetObject(nPos)); + BOOL bIsMasterPage; + USHORT nBMPage = pBookmarkDoc->GetPageByName( aPgName, bIsMasterPage ); + + if (nBMPage != SDRPAGE_NOTFOUND) + { + pBMPage = (SdPage*) pBookmarkDoc->GetPage(nBMPage); + } + else + { + pBMPage = NULL; + } + + if (pBMPage && pBMPage->GetPageKind()==PK_STANDARD && !pBMPage->IsMasterPage()) + { + /************************************************************** + * Es muss eine StandardSeite sein + **************************************************************/ + sal_Bool bMustRename = sal_False; + + // #95991# delay renaming *after* pages are copied (might destroy source otherwise) + // #67905# don't change name if source and dest model are the same! + // #96029# avoid renaming if replacing the same page + USHORT nPageSameName = GetPageByName(aPgName, bIsMasterPage); + if( pBookmarkDoc != this && + nPageSameName != SDRPAGE_NOTFOUND && + ( !bReplace || + nPageSameName != nActualInsertPos ) ) + { + bMustRename = sal_True; + } + + SdPage* pBookmarkPage = dynamic_cast< SdPage* >( pBookmarkDoc->GetPage(nBMPage) ); + if (bReplace ) + { + ReplacePageInCustomShows( dynamic_cast< SdPage* >( GetPage( nActualInsertPos ) ), pBookmarkPage ); + } + + Merge(*pBookmarkDoc, + nBMPage, // Von Seite (Standard) + nBMPage+1, // Bis Seite (Notizen) + nActualInsertPos, // An Position einfuegen + bMergeMasterPages, // MasterPages mitnehmen + FALSE, // Aber nur die benoetigten MasterPages + TRUE, // Undo-Aktion erzeugen + bCopy); // Seiten kopieren (oder mergen) + + if( bReplace ) + { + if( GetPage( nActualInsertPos ) != pBookmarkPage ) + { + // bookmark page was not moved but cloned, so update custom shows again + ReplacePageInCustomShows( pBookmarkPage, dynamic_cast< SdPage* >( GetPage( nActualInsertPos ) ) ); + } + } + + if( bMustRename ) + { + // Seitenname schon vorhanden -> Defaultname + // fuer Standard & Notizseite + SdPage* pPage = (SdPage*) GetPage(nActualInsertPos); + pPage->SetName(String()); + SdPage* pNotesPage = (SdPage*) GetPage(nActualInsertPos+1); + pNotesPage->SetName(String()); + } + + if (bLink) + { + SdPage* pPage = (SdPage*) GetPage(nActualInsertPos); + pPage->SetFileName(aBookmarkName); + pPage->SetBookmarkName(aPgName); + pPage->SetModel(this); + } + + if (bReplace) + { + // Seite & Notizseite ausfuegen + const sal_uInt16 nDestPageNum(nActualInsertPos + 2); + SdPage* pStandardPage = 0L; + + if(nDestPageNum < GetPageCount()) + { + pStandardPage = (SdPage*)GetPage(nDestPageNum); + } + + if (pStandardPage) + { + if( bPreservePageNames ) + { + // #96029# Take old slide names for inserted pages + SdPage* pPage = (SdPage*) GetPage(nActualInsertPos); + pPage->SetName( pStandardPage->GetRealName() ); + } + + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pStandardPage)); + + RemovePage(nDestPageNum); + + if( !bUndo ) + delete pStandardPage; + } + + SdPage* pNotesPage = 0L; + + if(nDestPageNum < GetPageCount()) + { + pNotesPage = (SdPage*)GetPage(nDestPageNum); + } + + if (pNotesPage) + { + if( bPreservePageNames ) + { + // #96029# Take old slide names for inserted pages + SdPage* pNewNotesPage = (SdPage*) GetPage(nActualInsertPos+1); + if( pNewNotesPage ) + pNewNotesPage->SetName( pStandardPage->GetRealName() ); + } + + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pNotesPage)); + + RemovePage(nDestPageNum); + + if( !bUndo ) + delete pNotesPage; + } + + nReplacedStandardPages++; + } + + nActualInsertPos += 2; + } + } + } + + + /************************************************************************** + |* Dabei sind evtl. zu viele Masterpages ruebergekommen, da die + |* DrawingEngine gleiche Praesentationslayouts nicht erkennen kann. + |* Ueberzaehlige MasterPages entfernen. + \*************************************************************************/ + USHORT nNewMPageCount = GetMasterPageCount(); + + // rueckwaerts, damit Nummern nicht durcheinander geraten + for (USHORT nPage = nNewMPageCount - 1; nPage >= nMPageCount; nPage--) + { + pRefPage = (SdPage*) GetMasterPage(nPage); + String aMPLayout(pRefPage->GetLayoutName()); + PageKind eKind = pRefPage->GetPageKind(); + + // gibt's den schon? + for (USHORT nTest = 0; nTest < nMPageCount; nTest++) + { + SdPage* pTest = (SdPage*) GetMasterPage(nTest); + String aTest(pTest->GetLayoutName()); + + // #96029# nInsertPos > 2 is always true when inserting into non-empty models + if ( nInsertPos > 2 && + aTest == aMPLayout && + eKind == pTest->GetPageKind() ) + { + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pRefPage)); + + RemoveMasterPage(nPage); + + if( !bUndo ) + delete pRefPage; + nNewMPageCount--; + break; + } + } + } + + // #96029# nInsertPos > 2 is always true when inserting into non-empty models + if (nInsertPos > 0) + { + USHORT nSdPageStart = (nInsertPos - 1) / 2; + USHORT nSdPageEnd = GetSdPageCount(PK_STANDARD) - nSdPageCount + + nSdPageStart - 1; + const bool bRemoveEmptyPresObj = pBookmarkDoc && + (pBookmarkDoc->GetDocumentType() == DOCUMENT_TYPE_IMPRESS) && + (GetDocumentType() == DOCUMENT_TYPE_DRAW); + + if( bReplace ) + { + nSdPageEnd = nSdPageStart + nReplacedStandardPages - 1; + } + + for (USHORT nSdPage = nSdPageStart; nSdPage <= nSdPageEnd; nSdPage++) + { + pRefPage = GetSdPage(nSdPage, PK_STANDARD); + + if (pExchangeList) + { + // Zuverwendener Name aus Exchange-Liste holen + if (pExchangeList->GetCurObject()) + { + String aExchangeName (*(String*) pExchangeList->GetCurObject()); + pRefPage->SetName(aExchangeName); + SdrHint aHint(HINT_PAGEORDERCHG); + aHint.SetPage(pRefPage); + Broadcast(aHint); + SdPage* pNewNotesPage = GetSdPage(nSdPage, PK_NOTES); + pNewNotesPage->SetName(aExchangeName); + aHint.SetPage(pNewNotesPage); + Broadcast(aHint); + } + + pExchangeList->Next(); + } + + String aLayout(pRefPage->GetLayoutName()); + aLayout.Erase(aLayout.SearchAscii( SD_LT_SEPARATOR )); + + // update layout and referred master page + pRefPage->SetPresentationLayout(aLayout); + if( bUndo ) + AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage ) ); + + if (bScaleObjects) + { + Rectangle aBorderRect(nLeft, nUpper, nRight, nLower); + pRefPage->ScaleObjects(aSize, aBorderRect, TRUE); + } + pRefPage->SetSize(aSize); + pRefPage->SetBorder(nLeft, nUpper, nRight, nLower); + pRefPage->SetOrientation( eOrient ); + + if( bRemoveEmptyPresObj ) + pRefPage->RemoveEmptyPresentationObjects(); + + pRefPage = GetSdPage(nSdPage, PK_NOTES); + + // update layout and referred master page + pRefPage->SetPresentationLayout(aLayout); + if( bUndo ) + AddUndo( GetSdrUndoFactory().CreateUndoPageChangeMasterPage( *pRefPage ) ); + + if (bScaleObjects) + { + Rectangle aBorderRect(nNLeft, nNUpper, nNRight, nNLower); + pRefPage->ScaleObjects(aNSize, aBorderRect, TRUE); + } + + pRefPage->SetSize(aNSize); + pRefPage->SetBorder(nNLeft, nNUpper, nNRight, nNLower); + pRefPage->SetOrientation( eNOrient ); + + if( bRemoveEmptyPresObj ) + pRefPage->RemoveEmptyPresentationObjects(); + } + + for (USHORT nPage = nMPageCount; nPage < nNewMPageCount; nPage++) + { + pRefPage = (SdPage*) GetMasterPage(nPage); + if (pRefPage->GetPageKind() == PK_STANDARD) + { + if (bScaleObjects) + { + Rectangle aBorderRect(nLeft, nUpper, nRight, nLower); + pRefPage->ScaleObjects(aSize, aBorderRect, TRUE); + } + pRefPage->SetSize(aSize); + pRefPage->SetBorder(nLeft, nUpper, nRight, nLower); + pRefPage->SetOrientation( eOrient ); + } + else // kann nur noch NOTES sein + { + if (bScaleObjects) + { + Rectangle aBorderRect(nNLeft, nNUpper, nNRight, nNLower); + pRefPage->ScaleObjects(aNSize, aBorderRect, TRUE); + } + pRefPage->SetSize(aNSize); + pRefPage->SetBorder(nNLeft, nNUpper, nNRight, nNLower); + pRefPage->SetOrientation( eNOrient ); + } + + if( bRemoveEmptyPresObj ) + pRefPage->RemoveEmptyPresentationObjects(); + } + } + + // #91146# Make absolutely sure no double masterpages are there + RemoveUnnecessaryMasterPages(NULL, TRUE, TRUE); + + if( bUndo ) + EndUndo(); + pUndoMgr->LeaveListAction(); + + return bContinue; +} + +/************************************************************************* +|* +|* Fuegt ein Bookmark als Objekt ein +|* +\************************************************************************/ + +BOOL SdDrawDocument::InsertBookmarkAsObject( + List* pBookmarkList, + List* pExchangeList, // Liste der zu verwendenen Namen + BOOL /* bLink */, + ::sd::DrawDocShell* pBookmarkDocSh, + Point* pObjPos) +{ + BOOL bOK = TRUE; + BOOL bOLEObjFound = FALSE; + ::sd::View* pBMView = NULL; + + SdDrawDocument* pBookmarkDoc = NULL; + String aBookmarkName; + + if (pBookmarkDocSh) + { + pBookmarkDoc = pBookmarkDocSh->GetDoc(); + + if (pBookmarkDocSh->GetMedium()) + { + aBookmarkName = pBookmarkDocSh->GetMedium()->GetName(); + } + } + else if ( mxBookmarkDocShRef.Is() ) + { + pBookmarkDoc = mxBookmarkDocShRef->GetDoc(); + aBookmarkName = maBookmarkFile; + } + else + { + return FALSE; + } + + if (!pBookmarkList) + { + pBMView = new ::sd::View(pBookmarkDoc, (OutputDevice*) NULL); + pBMView->EndListening(*pBookmarkDoc); + pBMView->MarkAll(); + } + else + { + SdrPage* pPage; + SdrPageView* pPV; + + for (USHORT nPos = 0; nPos < pBookmarkList->Count(); nPos++) + { + /****************************************************************** + * Namen der Bookmarks aus Liste holen + ******************************************************************/ + String aBMName (*(String*) pBookmarkList->GetObject(nPos)); + + SdrObject* pObj = pBookmarkDoc->GetObj(aBMName); + + if (pObj) + { + // Objekt gefunden + + if (pObj->GetObjInventor() == SdrInventor && + pObj->GetObjIdentifier() == OBJ_OLE2) + { + bOLEObjFound = TRUE; + } + + if (!pBMView) + { + // View erstmalig erzeugen + pBMView = new ::sd::View(pBookmarkDoc, (OutputDevice*) NULL); + pBMView->EndListening(*pBookmarkDoc); + } + + pPage = pObj->GetPage(); + + if (pPage->IsMasterPage()) + { + pPV = pBMView->ShowSdrPage(pBMView->GetModel()->GetMasterPage(pPage->GetPageNum())); + } + else + { + pPV = pBMView->GetSdrPageView(); + if( !pPV || (pPV->GetPage() != pPage)) + pPV = pBMView->ShowSdrPage(pPage); + } + + pBMView->MarkObj(pObj, pPV, FALSE); + } + } + } + + if (pBMView) + { + /********************************************************************** + * Selektierte Objekte einfuegen + **********************************************************************/ + ::sd::View* pView = new ::sd::View(this, (OutputDevice*) NULL); + pView->EndListening(*this); + + // Seite bestimmen, auf der die Objekte eingefuegt werden sollen + SdrPage* pPage = GetSdPage(0, PK_STANDARD); + + if (mpDocSh) + { + ::sd::ViewShell* pViewSh = mpDocSh->GetViewShell(); + + if (pViewSh) + { + // Welche Seite wird denn aktuell angezeigt? + SdrPageView* pPV = pViewSh->GetView()->GetSdrPageView(); + + if (pPV) + { + pPage = pPV->GetPage(); + } + else if (pViewSh->GetActualPage()) + { + pPage = pViewSh->GetActualPage(); + } + } + } + + Point aObjPos; + + if (pObjPos) + { + aObjPos = *pObjPos; + } + else + { + aObjPos = Rectangle(Point(), pPage->GetSize()).Center(); + } + + ULONG nCountBefore = 0; + + if (pExchangeList) + { + // OrdNums sortieren und Anzahl Objekte vor dem Einfuegen bestimmen + pPage->RecalcObjOrdNums(); + nCountBefore = pPage->GetObjCount(); + } + + if (bOLEObjFound) + pBMView->GetDoc()->SetAllocDocSh(TRUE); + + SdDrawDocument* pTmpDoc = (SdDrawDocument*) pBMView->GetAllMarkedModel(); + bOK = pView->Paste(*pTmpDoc, aObjPos, pPage); + + if (bOLEObjFound) + pBMView->GetDoc()->SetAllocDocSh(FALSE); + + if (!bOLEObjFound) + delete pTmpDoc; // Wird ansonsten von der DocShell zerstoert + + delete pView; + + if (pExchangeList) + { + // Anzahl Objekte nach dem Einfuegen bestimmen + ULONG nCount = pPage->GetObjCount(); + + for (ULONG nObj = nCountBefore; nObj < nCount; nObj++) + { + // Zuverwendener Name aus Exchange-Liste holen + if (pExchangeList->GetCurObject()) + { + String aExchangeName (*(String*) pExchangeList->GetCurObject()); + + if (pPage->GetObj(nObj)) + { + pPage->GetObj(nObj)->SetName(aExchangeName); + } + } + + pExchangeList->Next(); + } + } + } + + delete pBMView; + + return bOK; +} + +/************************************************************************* +|* +|* Beendet das Einfuegen von Bookmarks +|* +\************************************************************************/ + +void SdDrawDocument::CloseBookmarkDoc() +{ + if (mxBookmarkDocShRef.Is()) + { + mxBookmarkDocShRef->DoClose(); + } + + mxBookmarkDocShRef.Clear(); + maBookmarkFile = String(); +} + +/************************************************************************* +|* +|* Dokument laden (fuer gelinkte Objekte) +|* +\************************************************************************/ + +const SdrModel* SdDrawDocument::LoadModel(const String& rFileName) +{ + return ( OpenBookmarkDoc(rFileName) ); +} + +/************************************************************************* +|* +|* Dokument schliessen (fuer gelinkte Objekte) +|* +\************************************************************************/ + +void SdDrawDocument::DisposeLoadedModels() +{ + CloseBookmarkDoc(); +} + +/************************************************************************* +|* +|* Ist das Dokument read-only? +|* +\************************************************************************/ + +bool SdDrawDocument::IsReadOnly() const +{ + return FALSE; +} + + +/************************************************************************* +|* +|* In anschliessendem AllocModel() wird eine DocShell erzeugt +|* (xAllocedDocShRef). Eine bereits bestehende DocShell wird ggf. geloescht +|* +\************************************************************************/ + +void SdDrawDocument::SetAllocDocSh(BOOL bAlloc) +{ + mbAllocDocSh = bAlloc; + + if(mxAllocedDocShRef.Is()) + { + mxAllocedDocShRef->DoClose(); + } + + mxAllocedDocShRef.Clear(); +} + +/************************************************************************* +|* +|* Liste der CustomShows zurueckgeben (ggf. zuerst erzeugen) +|* +\************************************************************************/ + +List* SdDrawDocument::GetCustomShowList(BOOL bCreate) +{ + if (!mpCustomShowList && bCreate) + { + // Liste erzeugen + mpCustomShowList = new List(); + } + + return(mpCustomShowList); +} + +/************************************************************************* +|* +|* Document-Stream herausgeben (fuer load-on-demand Graphiken) +|* +\************************************************************************/ + +SvStream* SdDrawDocument::GetDocumentStream(SdrDocumentStreamInfo& rStreamInfo) const +{ + uno::Reference < embed::XStorage > xStor; + if (mpDocSh) + xStor = mpDocSh->GetStorage(); + SvStream* pRet = NULL; + + if( xStor.is() ) + { + //TODO/MBA: binary format removed, needs testing + if( rStreamInfo.maUserData.Len() && + ( rStreamInfo.maUserData.GetToken( 0, ':' ) == + String( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package" ) ) ) ) + { + const String aPicturePath( rStreamInfo.maUserData.GetToken( 1, ':' ) ); + + // graphic from picture stream in picture storage in XML package + if( aPicturePath.GetTokenCount( '/' ) == 2 ) try + { + const String aPictureStreamName( aPicturePath.GetToken( 1, '/' ) ); + const String aPictureStorageName( aPicturePath.GetToken( 0, '/' ) ); + if( xStor->isStorageElement( aPictureStorageName ) ) + { + uno::Reference < embed::XStorage > xPictureStorage = + xStor->openStorageElement( aPictureStorageName, embed::ElementModes::READ ); + try + { + if( xPictureStorage.is() && xPictureStorage->isStreamElement( aPictureStreamName ) ) + { + uno::Reference < io::XStream > xStream = xPictureStorage->openStreamElement( aPictureStreamName, embed::ElementModes::READ ); + if( xStream.is() ) + pRet = ::utl::UcbStreamHelper::CreateStream( xStream ); + } + } + catch( container::NoSuchElementException& ) + { + } + } + } + catch( uno::Exception& e ) + { + (void)e; + DBG_ERROR( + (rtl::OString("sd::SdDrawDocument::GetDocumentStream(), " + "exception caught: ") + + rtl::OUStringToOString( + comphelper::anyToString( cppu::getCaughtException() ), + RTL_TEXTENCODING_UTF8 ) + + rtl::OString("\r\nATTENTION: Graphics may get lost now, please inform CL or KA!") ).getStr() ); + } + + rStreamInfo.mbDeleteAfterUse = ( pRet != NULL ); + } + } + +#if OSL_DEBUG_LEVEL > 1 + if( pRet ) + { + // try to get some information from stream + const ULONG nStartPos = pRet->Tell(); + const ULONG nEndPos = pRet->Seek( STREAM_SEEK_TO_END ); + const ULONG nStmLen = nEndPos - nStartPos; + sal_uChar aTestByte; + + // try to read one byte + if( nStmLen ) + *pRet >> aTestByte; + + pRet->Seek( nStartPos ); + } +#endif + + return pRet; +} + + +/************************************************************************* +|* +|* Nicht benutzte MasterPages und Layouts entfernen +|* +\************************************************************************/ + +void SdDrawDocument::RemoveUnnecessaryMasterPages(SdPage* pMasterPage, BOOL bOnlyDuplicatePages, BOOL bUndo) +{ + ::sd::View* pView = NULL; + SfxUndoManager* pUndoMgr = NULL; + + if( bUndo && !IsUndoEnabled() ) + bUndo = FALSE; + + if (mpDocSh) + { + pUndoMgr = mpDocSh->GetUndoManager(); + + if (mpDocSh->GetViewShell()) + pView = mpDocSh->GetViewShell()->GetView(); + } + + /*********************************************************** + * Alle MasterPages pruefen + ***********************************************************/ + USHORT nSdMasterPageCount = GetMasterSdPageCount( PK_STANDARD ); + for (sal_Int32 nMPage = nSdMasterPageCount - 1; nMPage >= 0; nMPage--) + { + SdPage* pMaster = pMasterPage; + SdPage* pNotesMaster = NULL; + + if (!pMaster) + { + pMaster = (SdPage*) GetMasterSdPage( (USHORT) nMPage, PK_STANDARD ); + pNotesMaster = (SdPage*) GetMasterSdPage( (USHORT) nMPage, PK_NOTES ); + } + else + { + for ( USHORT nMPg = 0; nMPg < GetMasterPageCount(); nMPg++ ) + { + if ( pMaster == GetMasterPage( nMPg ) ) + { + pNotesMaster = (SdPage*) GetMasterPage( ++nMPg ); + break; + } + } + } + + DBG_ASSERT( pMaster->GetPageKind() == PK_STANDARD, "wrong page kind" ); + + if ( pMaster->GetPageKind() == PK_STANDARD && + GetMasterPageUserCount( pMaster ) == 0 && + pNotesMaster ) + { + // Do not delete master pages that have their precious flag set. + BOOL bDeleteMaster = !pMaster->IsPrecious(); + String aLayoutName = pMaster->GetLayoutName(); + + if(bOnlyDuplicatePages ) + { + // remove only duplicate pages + bDeleteMaster = FALSE; + for (USHORT i = 0; i < GetMasterSdPageCount( PK_STANDARD ); i++) + { + SdPage* pMPg = (SdPage*) GetMasterSdPage( i, PK_STANDARD ); + if( pMPg != pMaster && + pMPg->GetLayoutName() == aLayoutName ) + { + // duplicate page found -> remove it + bDeleteMaster = TRUE; + } + } + } + + if( bDeleteMaster ) + { + if (pView) + { + // if MasterPage is visible hide on pageview + SdrPageView* pPgView = pView->GetSdrPageView(); + if (pPgView) + { + SdrPage* pShownPage = pPgView->GetPage(); + if( (pShownPage == pMaster) || (pShownPage == pNotesMaster) ) + { + pView->HideSdrPage(); + pView->ShowSdrPage( GetSdPage( 0, PK_STANDARD ) ); + } + } + } + + if( bUndo ) + { + BegUndo(); + AddUndo( GetSdrUndoFactory().CreateUndoDeletePage( *pNotesMaster ) ); + } + + RemoveMasterPage( pNotesMaster->GetPageNum() ); + + if( !bUndo ) + delete pNotesMaster; + + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoDeletePage(*pMaster)); + + RemoveMasterPage( pMaster->GetPageNum() ); + + if( !bUndo ) + delete pMaster; + + if( bUndo ) + EndUndo(); // schon hier, damit sich Joes Actions ZWISCHEN unsere eigenen schieben + + // alte Layoutvorlagen loeschen, wenn sie nicht mehr benoetigt werden + BOOL bDeleteOldStyleSheets = TRUE; + for ( USHORT nMPg = 0; + nMPg < GetMasterPageCount() && bDeleteOldStyleSheets; + nMPg++ ) + { + SdPage* pMPg = (SdPage*) GetMasterPage(nMPg); + if (pMPg->GetLayoutName() == aLayoutName) + { + bDeleteOldStyleSheets = FALSE; + } + } + + if (bDeleteOldStyleSheets) + { + SdStyleSheetVector aRemove; + static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutSheetList( aLayoutName, aRemove ); + + if( bUndo ) + { + // die Liste gehoert der UndoAction + SdMoveStyleSheetsUndoAction* pMovStyles = new SdMoveStyleSheetsUndoAction( this, aRemove, false ); + + if (pUndoMgr) + pUndoMgr->AddUndoAction(pMovStyles); + } + + for( SdStyleSheetVector::iterator iter = aRemove.begin(); iter != aRemove.end(); ++iter ) + static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->Remove((*iter).get()); + } + } + } + + if (pMasterPage) + break; // Nur diese eine MasterPage! + } +} + + +/************************************************************************* +|* +|* MasterPage austauschen +|* +|* Entweder erhaelt nSdPageNum eine neue, eigene MasterPage, oder die MasterPage +|* wird komplett ausgetauscht (gilt dann fuer alle Seiten). +|* +|* nSdPageNum : Nummer der Seite, welche die neue MasterPage erhalten soll +|* rLayoutName : LayoutName der neuen MasterPage +|* pSourceDoc : Dokument (Vorlage) aus dem die MasterPage geholt wird +|* bMaster : Die MasterPage von nSdPageNum soll ausgetauscht werden +|* bCheckMasters: Nicht benutzte MasterPages sollen entfernt werden +|* +|* Ist pSourceDoc == NULL, so wird eine leere MasterPage zugewiesen. +|* Ist rLayoutName leer, so wird die erste MasterPage genommen +\************************************************************************/ + +void SdDrawDocument::SetMasterPage(USHORT nSdPageNum, + const String& rLayoutName, + SdDrawDocument* pSourceDoc, + BOOL bMaster, + BOOL bCheckMasters) +{ + if( mpDocSh ) + mpDocSh->SetWaitCursor( TRUE ); + + SfxUndoManager* pUndoMgr = mpDocSh->GetUndoManager(); + + const bool bUndo = IsUndoEnabled(); + + if( bUndo ) + { + pUndoMgr->EnterListAction(String(SdResId(STR_UNDO_SET_PRESLAYOUT)), String()); + } + + SdPage* pSelectedPage = GetSdPage(nSdPageNum, PK_STANDARD); + SdPage* pNotes = (SdPage*) GetPage(pSelectedPage->GetPageNum()+1); + SdPage& rOldMaster = (SdPage&)pSelectedPage->TRG_GetMasterPage(); + SdPage& rOldNotesMaster = (SdPage&)pNotes->TRG_GetMasterPage(); + SdPage* pMaster = NULL; + SdPage* pNotesMaster = NULL; + SdPage* pPage = NULL; + String aOldPageLayoutName(pSelectedPage->GetLayoutName()); + String aOldLayoutName(aOldPageLayoutName); + aOldLayoutName.Erase(aOldLayoutName.SearchAscii( SD_LT_SEPARATOR )); + + String aNewLayoutName( rLayoutName ); + + if (pSourceDoc) + { + List* pReplList = NULL; + BOOL bLayoutReloaded = FALSE; // Wurde ex. Layout wieder geladen? + + /********************************************************************* + |* LayoutName, Page and Notespage + \*********************************************************************/ + if (rLayoutName.Len() == 0) + { + // No LayoutName: take first MasterPage + pMaster = (SdPage*) pSourceDoc->GetMasterSdPage(0, PK_STANDARD); + pNotesMaster = (SdPage*) pSourceDoc->GetMasterSdPage(0, PK_NOTES); + aNewLayoutName = pMaster->GetName(); + } + else + { + String aSearchFor(rLayoutName); + aSearchFor.AppendAscii( RTL_CONSTASCII_STRINGPARAM( SD_LT_SEPARATOR )); + aSearchFor.Append( String(SdResId(STR_LAYOUT_OUTLINE))) ; + + for (USHORT nMP = 0; nMP < pSourceDoc->GetMasterPageCount(); nMP++) + { + SdPage* pMP = (SdPage*) pSourceDoc->GetMasterPage(nMP); + + if (pMP->GetLayoutName() == aSearchFor) + { + if (pMP->GetPageKind() == PK_STANDARD) + pMaster = pMP; + if (pMP->GetPageKind() == PK_NOTES) + pNotesMaster = pMP; + } + if (pMaster && pNotesMaster) + break; + } + DBG_ASSERT(pMaster, "MasterPage (Standard page) not found"); + DBG_ASSERT(pNotesMaster, "MasterPage (Notes page) not found"); + + // this should not happen, but looking at crashreports, it does + if( (pMaster == NULL) || (pNotesMaster == NULL) ) + { + // so take the first MasterPage + pMaster = (SdPage*) pSourceDoc->GetMasterSdPage(0, PK_STANDARD); + pNotesMaster = (SdPage*) pSourceDoc->GetMasterSdPage(0, PK_NOTES); + aNewLayoutName = pMaster->GetName(); + } + } + + // we should never reach this, but one never knows.... + if( (pMaster == NULL) || (pNotesMaster == NULL) ) + { + pUndoMgr->LeaveListAction(); + + if( mpDocSh ) + mpDocSh->SetWaitCursor( FALSE ); + + DBG_ERROR( "SdDrawDocument::SetMasterPage() failed!" ); + + return; + } + + if (pSourceDoc != this) + { + const USHORT nMasterPageCount = GetMasterPageCount(); + for ( USHORT nMPage = 0; nMPage < nMasterPageCount; nMPage++ ) + { + SdPage* pCheckMaster = (SdPage*)GetMasterPage(nMPage); + if( pCheckMaster->GetName() == aNewLayoutName ) + { + bLayoutReloaded = TRUE; + break; + } + } + + /***************************************************************** + |* Praesentationsvorlagen korrigieren bzw. neu anlegen + \****************************************************************/ + // nur die Praesentationsvorlagen beachten + String aName; + SdStyleSheetPool* pSourceStyleSheetPool = (SdStyleSheetPool*) pSourceDoc->GetStyleSheetPool(); + pSourceStyleSheetPool->SetSearchMask(SD_STYLE_FAMILY_MASTERPAGE); + static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->SetSearchMask(SD_STYLE_FAMILY_MASTERPAGE); + + pReplList = new List; // Liste fuer ersetzte StyleSheets + SdStyleSheetVector aCreatedStyles; // Liste fuer erzeugte StyleSheets + + SfxStyleSheetBase* pHisSheet = pSourceStyleSheetPool->First(); + + while (pHisSheet) + { + aName = pHisSheet->GetName(); + + if( aName.Search( aNewLayoutName ) == 0 ) + { + SfxStyleSheet* pMySheet = static_cast<SfxStyleSheet*>( mxStyleSheetPool->Find(aName, SD_STYLE_FAMILY_MASTERPAGE) ); + + if (pMySheet) + { + // Es ist eine gleichnamige Vorlage vorhanden ist: Inhalte ersetzen +#ifdef DBG_UTIL + BOOL bTest = +#endif + pMySheet->SetName(pHisSheet->GetName()); + DBG_ASSERT(bTest, "StyleSheet-Umbenennung fehlgeschlagen"); + pMySheet->GetItemSet().ClearItem(0); // alle loeschen + + StyleSheetUndoAction* pUndoChStyle = new StyleSheetUndoAction(this, + pMySheet, &pHisSheet->GetItemSet()); + pUndoMgr->AddUndoAction(pUndoChStyle); + pMySheet->GetItemSet().Put(pHisSheet->GetItemSet()); + pMySheet->Broadcast(SfxSimpleHint(SFX_HINT_DATACHANGED)); + } + else + { + // create new style + String aHelpFile; + pMySheet = static_cast<SfxStyleSheet*>( &mxStyleSheetPool->Make(aName, SD_STYLE_FAMILY_MASTERPAGE, pHisSheet->GetMask()) ); + pMySheet->SetHelpId( aHelpFile, pHisSheet->GetHelpId(aHelpFile) ); + pMySheet->GetItemSet().ClearItem(0); // alle loeschen + pMySheet->GetItemSet().Put(pHisSheet->GetItemSet()); + + aCreatedStyles.push_back( SdStyleSheetRef( static_cast< SdStyleSheet* >( pMySheet ) ) ); + } + + StyleReplaceData* pReplData = new StyleReplaceData; + pReplData->nNewFamily = pMySheet->GetFamily(); + pReplData->nFamily = pMySheet->GetFamily(); + pReplData->aNewName = pMySheet->GetName(); + + String aTemp(pMySheet->GetName()); + USHORT nPos = aTemp.SearchAscii( SD_LT_SEPARATOR ); + aTemp.Erase(0, nPos); + aTemp.Insert(aOldLayoutName, 0); + pReplData->aName = aTemp; + pReplList->Insert(pReplData, LIST_APPEND); + } + + pHisSheet = (SfxStyleSheet*) pSourceStyleSheetPool->Next(); + } + + // wenn neue Vorlagen erzeugt wurden: + // eventuell bestehende Parent-Verkettung der Itemsets in den + // Vorlagen wieder aufbauen + if(!aCreatedStyles.empty()) + { + StyleReplaceData* pRData = (StyleReplaceData*)pReplList->First(); + + while (pRData) + { + SfxStyleSheetBase* pSOld = mxStyleSheetPool->Find(pRData->aName); + SfxStyleSheetBase* pSNew = mxStyleSheetPool->Find(pRData->aNewName); + + if (pSOld && pSNew) + { + const String& rParentOfOld = pSOld->GetParent(); + const String& rParentOfNew = pSNew->GetParent(); + + if (rParentOfOld.Len() > 0 && rParentOfNew.Len() == 0) + { + + for (ULONG i = 0; i < pReplList->Count(); i++) + { + StyleReplaceData* pRD = (StyleReplaceData*)pReplList-> + GetObject(i); + if ((pRD->aName == rParentOfOld) && (pRD->aName != pRD->aNewName)) + { + String aParentOfNew(pRD->aNewName); + pSNew->SetParent(aParentOfNew); + break; + } + } + } + } + pRData = (StyleReplaceData*) pReplList->Next(); + } + + // ab jetzt beim Suchen alle beachten + pSourceStyleSheetPool->SetSearchMask(SFX_STYLE_FAMILY_ALL); + mxStyleSheetPool->SetSearchMask(SFX_STYLE_FAMILY_ALL); + } + + if( !aCreatedStyles.empty() ) + { + // UndoAction fuer das Erzeugen und Einfuegen vorn StyleSheets + // auf den UndoManager legen + SdMoveStyleSheetsUndoAction* pMovStyles = new SdMoveStyleSheetsUndoAction( this, aCreatedStyles, TRUE); + pUndoMgr->AddUndoAction(pMovStyles); + } + } + + // Layoutnamen auf Basis des Seitenlayoutnamens der Masterpage bilden + String aPageLayoutName(pMaster->GetLayoutName()); + String aLayoutName = aPageLayoutName; + aLayoutName.Erase( aLayoutName.SearchAscii( SD_LT_SEPARATOR )); + + if (pSourceDoc != this) + { + // Aus dem Source-Dokument austragen + pSourceDoc->RemoveMasterPage(pNotesMaster->GetPageNum()); + pSourceDoc->RemoveMasterPage(pMaster->GetPageNum()); + } + + /********************************************************************* + |* Neue MasterPages ins Dokument eintragen und den Standard- und + |* Notizseiten das Praesentationslayout ueberbraten + \********************************************************************/ + if (pSourceDoc != this) + { + // Die Masterpages einfuegen: + // Masterpages von neuen Layouts hinten anhaengen; wird ein Layout + // dagegen ersetzt, so muss vor der Position der alten Masterpage + // eingefuegt werden, damit ab jetzt beim Suchen (z. B. SdPage:: + // SetPresentationLayout) die neue Masterpage zuerst gefunden wird + USHORT nInsertPos = rOldMaster.GetPageNum(); + BegUndo(); + + if (!bLayoutReloaded) + nInsertPos = 0xFFFF; + InsertMasterPage(pMaster, nInsertPos); + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pMaster)); + + nInsertPos++; + if (!bLayoutReloaded) + nInsertPos = 0xFFFF; + InsertMasterPage(pNotesMaster, nInsertPos); + if( bUndo ) + { + AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pNotesMaster)); + + EndUndo(); // schon hier, damit sich Joes Actions ZWISCHEN unsere eigenen schieben + } + } + + // Liste mit Seiten fuellen + List* pPageList = new List; + +// #98456, this has to be removed according to CL (KA 07/08/2002) +// #109884# but we need them again to restore the styles of the presentation objects while undo + pPageList->Insert(pMaster, LIST_APPEND); + pPageList->Insert(pNotesMaster, LIST_APPEND); + + if (bMaster || bLayoutReloaded) + { + for (USHORT nPage = 1; nPage < GetPageCount(); nPage++) + { + pPage = (SdPage*) GetPage(nPage); + String aTest = pPage->GetLayoutName(); + if (aTest == aOldPageLayoutName) + { + pPageList->Insert(pPage, LIST_APPEND); + } + } + + } + else + { + pPageList->Insert(pSelectedPage, LIST_APPEND); + pPageList->Insert(pNotes, LIST_APPEND); + } + + pPage = (SdPage*)pPageList->First(); + while (pPage) + { + AutoLayout eAutoLayout = pPage->GetAutoLayout(); + + if( bUndo ) + { + SdPresentationLayoutUndoAction * pPLUndoAction = + new SdPresentationLayoutUndoAction + (this, + pPage->IsMasterPage() ? aLayoutName : aOldLayoutName, + aLayoutName, + eAutoLayout, eAutoLayout, FALSE, pPage); + pUndoMgr->AddUndoAction(pPLUndoAction); + } + pPage->SetPresentationLayout(aLayoutName); + pPage->SetAutoLayout(eAutoLayout); + + pPage = (SdPage*)pPageList->Next(); + } + delete pPageList; + + /********************************************************************* + |* Neue Masterpages angleichen + \********************************************************************/ + if (pSourceDoc != this) + { + // die Masterpages angleichen + Size aSize(rOldMaster.GetSize()); + Rectangle aBorderRect(rOldMaster.GetLftBorder(), + rOldMaster.GetUppBorder(), + rOldMaster.GetRgtBorder(), + rOldMaster.GetLwrBorder()); + pMaster->ScaleObjects(aSize, aBorderRect, TRUE); + pMaster->SetSize(aSize); + pMaster->SetBorder(rOldMaster.GetLftBorder(), + rOldMaster.GetUppBorder(), + rOldMaster.GetRgtBorder(), + rOldMaster.GetLwrBorder()); + pMaster->SetOrientation( rOldMaster.GetOrientation() ); + pMaster->SetAutoLayout(pMaster->GetAutoLayout()); + + aSize = rOldNotesMaster.GetSize(); + Rectangle aNotesBorderRect(rOldNotesMaster.GetLftBorder(), + rOldNotesMaster.GetUppBorder(), + rOldNotesMaster.GetRgtBorder(), + rOldNotesMaster.GetLwrBorder()); + pNotesMaster->ScaleObjects(aSize, aNotesBorderRect, TRUE); + pNotesMaster->SetSize(aSize); + pNotesMaster->SetBorder(rOldNotesMaster.GetLftBorder(), + rOldNotesMaster.GetUppBorder(), + rOldNotesMaster.GetRgtBorder(), + rOldNotesMaster.GetLwrBorder()); + pNotesMaster->SetOrientation( rOldNotesMaster.GetOrientation() ); + pNotesMaster->SetAutoLayout(pNotesMaster->GetAutoLayout()); + + // Liste der ersetzten Vorlagen mit Inhalt loeschen + StyleReplaceData* pReplData = (StyleReplaceData*)pReplList->First(); + while (pReplData) + { + delete pReplData; + pReplData = (StyleReplaceData*)pReplList->Next(); + } + delete pReplList; + + + if( (pSourceDoc->GetDocumentType() == DOCUMENT_TYPE_IMPRESS) && + (GetDocumentType() == DOCUMENT_TYPE_DRAW) ) + { + pMaster->RemoveEmptyPresentationObjects(); + pNotesMaster->RemoveEmptyPresentationObjects(); + } + } + } + else + { + /********************************************************************* + |* Einen neuen Layoutnamen ausdenken + \********************************************************************/ + String aName = String(SdResId(STR_LAYOUT_DEFAULT_NAME)); + String aTest; + BOOL bNotANewName = TRUE; + USHORT nCount = 0; + USHORT nMPgCount = GetMasterPageCount(); + + for (nCount = 0; bNotANewName; nCount++) + { + // Testnamen bilden + aTest = aName; // Standard, Standard1, Standard2, ... + if (nCount > 0) + aTest += String::CreateFromInt32( nCount ); + + // gibt's schon eine, die so heisst? + bNotANewName = FALSE; + for (USHORT nMPg = 1; nMPg < nMPgCount; nMPg++) + { + const SdrPage* pTest = GetMasterPage(nMPg); + String aPageLayoutName(pTest->GetLayoutName()); + aPageLayoutName.Erase( aPageLayoutName.SearchAscii( SD_LT_SEPARATOR )); + + if (aPageLayoutName == aTest) + bNotANewName = TRUE; + } + } + aName = aTest; + String aPageLayoutName(aName); + aPageLayoutName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( SD_LT_SEPARATOR )); + aPageLayoutName += String(SdResId(STR_LAYOUT_OUTLINE)); + + /********************************************************************* + |* Neue StyleSheets erzeugen + \********************************************************************/ + static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutStyleSheets(aName); + SdStyleSheetVector aCreatedStyles; + static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->CreateLayoutSheetList(aName, aCreatedStyles); + + if( bUndo ) + { + SdMoveStyleSheetsUndoAction* pMovStyles = new SdMoveStyleSheetsUndoAction(this, aCreatedStyles, TRUE); + pUndoMgr->AddUndoAction(pMovStyles); + } + + /********************************************************************* + |* Neue MasterPages erzeugen und ins Dokument eintragen + \********************************************************************/ + + if( bUndo ) + BegUndo(); + + pMaster = (SdPage*) AllocPage(TRUE); + pMaster->SetSize(pSelectedPage->GetSize()); + pMaster->SetBorder(pSelectedPage->GetLftBorder(), + pSelectedPage->GetUppBorder(), + pSelectedPage->GetRgtBorder(), + pSelectedPage->GetLwrBorder() ); + pMaster->SetName(aName); + pMaster->SetLayoutName(aPageLayoutName); + InsertMasterPage(pMaster); + + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pMaster)); + + pMaster->SetAutoLayout(AUTOLAYOUT_NONE, true, true); + + pNotesMaster = (SdPage*) AllocPage(TRUE); + pNotesMaster->SetPageKind(PK_NOTES); + pNotesMaster->SetSize(pNotes->GetSize()); + pNotesMaster->SetBorder(pNotes->GetLftBorder(), + pNotes->GetUppBorder(), + pNotes->GetRgtBorder(), + pNotes->GetLwrBorder() ); + pNotesMaster->SetName(aName); + pNotesMaster->SetLayoutName(aPageLayoutName); + InsertMasterPage(pNotesMaster); + + if( bUndo ) + AddUndo(GetSdrUndoFactory().CreateUndoNewPage(*pNotesMaster)); + + pNotesMaster->SetAutoLayout(AUTOLAYOUT_NOTES, true, true); + + if( bUndo ) + EndUndo(); + + /********************************************************************* + |* Liste der betroffenen Standard- und Notizseiten erstellen + \********************************************************************/ + List* pPageList = new List; + if (bMaster) + { + for (USHORT nPage = 1; nPage < GetPageCount(); nPage++) + { + pPage = (SdPage*) GetPage(nPage); + const String s(pPage->GetLayoutName()); + if(s == aOldPageLayoutName) + { + pPageList->Insert(pPage, LIST_APPEND); + } + } + } + else + { + pPageList->Insert(pSelectedPage, LIST_APPEND); + pPageList->Insert(pNotes, LIST_APPEND); + } + + /********************************************************************* + |* An den betroffenen Seiten Praesentations- und Autolayout setzen + \********************************************************************/ + pPage = (SdPage*)pPageList->First(); + while(pPage) + { + AutoLayout eOldAutoLayout = pPage->GetAutoLayout(); + AutoLayout eNewAutoLayout = + pPage->GetPageKind() == PK_STANDARD ? AUTOLAYOUT_NONE : AUTOLAYOUT_NOTES; + + if( bUndo ) + { + SdPresentationLayoutUndoAction * pPLUndoAction = + new SdPresentationLayoutUndoAction + (this, aOldLayoutName, aName, + eOldAutoLayout, eNewAutoLayout, TRUE, + pPage); + pUndoMgr->AddUndoAction(pPLUndoAction); + } + + pPage->SetPresentationLayout(aName); + pPage->SetAutoLayout(eNewAutoLayout); + + pPage = (SdPage*)pPageList->Next(); + } + + // Seitenliste loeschen + delete pPageList; + } + + /********************************************************************* + |* falls die alten Masterpages nicht mehr benoetigt werden, + |* muessen sie und die entsprechenden Praesentationsvorlagen + |* entfernt werden + \********************************************************************/ + if (bCheckMasters) + { + // Alle pruefen + RemoveUnnecessaryMasterPages(); + } + else + { + // Nur die ausgetauschte MasterPage pruefen + RemoveUnnecessaryMasterPages(&rOldMaster); + } + + if( bUndo ) + pUndoMgr->LeaveListAction(); + + if( mpDocSh ) + mpDocSh->SetWaitCursor( FALSE ); +} + + + +void SdDrawDocument::Merge(SdrModel& rSourceModel, + USHORT nFirstPageNum, USHORT nLastPageNum, + USHORT nDestPos, + bool bMergeMasterPages, bool bAllMasterPages, + bool bUndo, bool bTreadSourceAsConst) +{ + sal_uInt16 nMasterPageCount = GetMasterPageCount(); + SdrModel::Merge( rSourceModel, nFirstPageNum, nLastPageNum, nDestPos, bMergeMasterPages, bAllMasterPages, bUndo, bTreadSourceAsConst ); + + // add style family for each new master page + for( sal_uInt16 nMaster = nMasterPageCount; nMaster < GetMasterPageCount(); nMaster++ ) + { + SdPage* pPage = static_cast< SdPage* >( GetMasterPage( nMaster ) ); + if( pPage && pPage->IsMasterPage() && (pPage->GetPageKind() == PK_STANDARD) ) + { + // new master page created, add its style family + SdStyleSheetPool* pStylePool = (SdStyleSheetPool*) GetStyleSheetPool(); + if( pStylePool ) + pStylePool->AddStyleFamily( pPage ); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/drawdoc4.cxx b/sd/source/core/drawdoc4.cxx new file mode 100644 index 000000000000..c2978ddfe6c9 --- /dev/null +++ b/sd/source/core/drawdoc4.cxx @@ -0,0 +1,1470 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include <com/sun/star/style/XStyle.hpp> +#include <com/sun/star/container/XNameAccess.hpp> + +#include <tools/urlobj.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/dispatch.hxx> +#include "Outliner.hxx" +#include <comphelper/processfactory.hxx> +#include <editeng/outliner.hxx> + +#include "../ui/inc/DrawDocShell.hxx" +#include <editeng/eeitem.hxx> +#include <vcl/svapp.hxx> +#include <eetext.hxx> + +#include <editeng/akrnitem.hxx> + +#include <svx/svxids.hrc> +#include <svl/srchitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/lspcitem.hxx> +#include <editeng/adjitem.hxx> +#include <svx/dialogs.hrc> +#include <svx/dialmgr.hxx> // SVX_RESSTR +#include <editeng/bulitem.hxx> +#include <svx/xtable.hxx> +#include <svx/sxmsuitm.hxx> +#include <editeng/borderline.hxx> +#include <editeng/boxitem.hxx> +#include <svx/xit.hxx> +#include <svx/xlineit0.hxx> +#include <svx/sdshitm.hxx> +#include <svx/svdotext.hxx> +#include <svx/xfillit0.hxx> +#include <svx/sdshcitm.hxx> +#include <editeng/editstat.hxx> +#include <editeng/colritem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/cntritem.hxx> +#include <editeng/emphitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/shdditem.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflclit.hxx> +#include <svx/xlnedcit.hxx> +#include <svx/xlnstcit.hxx> +#include <svx/xlnedwit.hxx> +#include <svx/xlnstwit.hxx> +#include <svx/xlnedit.hxx> +#include <editeng/charreliefitem.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xlndsit.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xlnclit.hxx> +#include <svx/svditer.hxx> +#include <svx/svdogrp.hxx> +#include <tools/shl.hxx> +#include <editeng/numitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/unolingu.hxx> +#include <com/sun/star/linguistic2/XHyphenator.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <svl/itempool.hxx> +#include <editeng/outlobj.hxx> +#include <sfx2/viewfrm.hxx> +#include <editeng/langitem.hxx> +#include <editeng/frmdiritem.hxx> + +#include "sdresid.hxx" +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include "glob.hrc" +#include "glob.hxx" +#include "stlpool.hxx" +#include "helpids.h" +#include "sdiocmpt.hxx" +#include "shapelist.hxx" +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <svl/itemset.hxx> + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::linguistic2; +using namespace ::sd; + +/************************************************************************* +|* +|* CreateLayoutTemplates, Layoutvorlagen erzeugen +|* +|* Z.Zt. (31.03.95) speichert der StyleSheetPool nur diejenigen Sheets, die +|* ein ItemSet haben. Damit alle Sheets gespeichert werden, wird die ItemSet- +|* Erzeugung mit einem GetItemSet-Aufruf erzwungen. +|* Dies kann entfallen, sobald der Pool auch Sheets ohne ItemSet speichert. +|* +\************************************************************************/ + +void SdDrawDocument::CreateLayoutTemplates() +{ + SdStyleSheetPool* pSSPool = (SdStyleSheetPool*)GetStyleSheetPool(); + SfxStyleSheetBase* pSheet = NULL; + String aHelpFile; + String aStdName = String(SdResId(STR_STANDARD_STYLESHEET_NAME)); + + // ---- Standardvorlage ----------------------------------------------- + + // nicht benutzt, nicht benutzerdefiniert + // SB hatte wahrscheinlich Probleme mit SFXSTYLEBIT_AUTO, da dann gar nichts + // mehr im Gestalter angezeigt wird. Dieses Problem ist zu 364 j behoben worden + // USHORT nMask = SFXSTYLEBIT_ALL & ~(SFXSTYLEBIT_USED | SFXSTYLEBIT_USERDEF); + USHORT nMask = SFXSTYLEBIT_AUTO; + + String aName(aStdName); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetHelpId( aHelpFile, HID_STANDARD_STYLESHEET_NAME ); + SfxItemSet& rISet = pSheet->GetItemSet(); + SfxItemPool* pPool = rISet.GetPool(); + + String aNullStr; + + ::basegfx::B2DPolyPolygon aNullPolyPolygon; + Color aNullCol(RGB_Color(COL_BLACK)); + + XDash aNullDash; + XGradient aNullGrad(aNullCol,RGB_Color(COL_WHITE)); + aNullGrad.SetStartIntens( 100 ); + aNullGrad.SetEndIntens( 100 ); + XHatch aNullHatch(aNullCol); + + // Linienattribute (Extended OutputDevice) + rISet.Put(XLineStyleItem(XLINE_SOLID)); + rISet.Put(XLineColorItem(String(), RGB_Color(COL_BLACK))); + rISet.Put(XLineWidthItem(0)); + rISet.Put(XLineDashItem(pPool,aNullDash)); + rISet.Put(XLineStartItem(pPool,aNullPolyPolygon)); + rISet.Put(XLineEndItem(pPool,aNullPolyPolygon)); + rISet.Put(XLineStartWidthItem(300)); + rISet.Put(XLineEndWidthItem(300)); + rISet.Put(XLineStartCenterItem()); + rISet.Put(XLineEndCenterItem()); + + // Fuellattribute (Extended OutputDevice) + rISet.Put(XFillStyleItem(XFILL_SOLID)); + rISet.Put(XFillColorItem(String(), RGB_Color(COL_DEFAULT_SHAPE_FILLING))); // "Blue 8" + + rISet.Put(XFillGradientItem(pPool,aNullGrad)); + rISet.Put(XFillHatchItem(pPool,aNullHatch)); + Size aNullSize( 32, 32 ); + Color aNullColor( COL_WHITE ); + Bitmap aNullBmp( aNullSize, 8 ); + aNullBmp.Erase( aNullColor ); + rISet.Put(XFillBitmapItem(pPool,aNullBmp)); + + // Schattenattribute (Drawing Engine) + rISet.Put(SdrShadowItem(FALSE)); + rISet.Put(SdrShadowColorItem(aNullStr, RGB_Color(COL_GRAY))); + rISet.Put(SdrShadowXDistItem(300)); // 3 mm Schattendistanz + rISet.Put(SdrShadowYDistItem(300)); + + Font aLatinFont, aCJKFont, aCTLFont; + + getDefaultFonts( aLatinFont, aCJKFont, aCTLFont ); + + SvxFontItem aSvxFontItem( aLatinFont.GetFamily(), aLatinFont.GetName(), aLatinFont.GetStyleName(), aLatinFont.GetPitch(), + aLatinFont.GetCharSet(), EE_CHAR_FONTINFO ); + + SvxFontItem aSvxFontItemCJK( aCJKFont.GetFamily(), aCJKFont.GetName(), aCJKFont.GetStyleName(), aCJKFont.GetPitch(), + aCJKFont.GetCharSet(), EE_CHAR_FONTINFO_CJK ); + + SvxFontItem aSvxFontItemCTL( aCTLFont.GetFamily(), aCTLFont.GetName(), aCTLFont.GetStyleName(), aCTLFont.GetPitch(), + aCTLFont.GetCharSet(), EE_CHAR_FONTINFO_CTL ); + + rISet.Put( aSvxFontItem ); + rISet.Put( aSvxFontItemCJK ); + rISet.Put( aSvxFontItemCTL ); + + rISet.Put( SvxFontHeightItem( 635, 100, EE_CHAR_FONTHEIGHT ) ); // sj: (i33745) changed default from 24 to 18 pt + rISet.Put( SvxFontHeightItem( 635, 100, EE_CHAR_FONTHEIGHT_CJK ) ); // 18 pt + rISet.Put( SvxFontHeightItem( convertFontHeightToCTL( 635 ), 100, EE_CHAR_FONTHEIGHT_CTL ) ); // 18 pt + + rISet.Put( SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT ) ); + rISet.Put( SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ) ); + rISet.Put( SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ) ); + + rISet.Put( SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC ) ); + rISet.Put( SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CJK ) ); + rISet.Put( SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CTL ) ); + + rISet.Put(SvxContourItem(FALSE, EE_CHAR_OUTLINE )); + rISet.Put(SvxShadowedItem(FALSE, EE_CHAR_SHADOW )); + rISet.Put(SvxUnderlineItem(UNDERLINE_NONE, EE_CHAR_UNDERLINE)); + rISet.Put(SvxOverlineItem(UNDERLINE_NONE, EE_CHAR_OVERLINE)); + rISet.Put(SvxCrossedOutItem(STRIKEOUT_NONE, EE_CHAR_STRIKEOUT )); + rISet.Put(SvxEmphasisMarkItem(EMPHASISMARK_NONE, EE_CHAR_EMPHASISMARK)); + rISet.Put(SvxCharReliefItem(RELIEF_NONE, EE_CHAR_RELIEF)); + rISet.Put(SvxColorItem(Color(COL_AUTO), EE_CHAR_COLOR )); + + // Absatzattribute (Edit Engine) + rISet.Put(SvxLRSpaceItem(EE_PARA_LRSPACE)); + rISet.Put(SvxULSpaceItem(EE_PARA_ULSPACE)); + + rISet.Put( SdrTextLeftDistItem( 250 ) ); // sj: (i33745) using text frame distances seems to be a better default + rISet.Put( SdrTextRightDistItem( 250 ) ); + rISet.Put( SdrTextUpperDistItem( 125 ) ); + rISet.Put( SdrTextLowerDistItem( 125 ) ); + + rISet.Put( SvxLineSpacingItem( LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL ) ); + + // #i16874# enable kerning by default but only for new documents + rISet.Put( SvxAutoKernItem( TRUE, EE_CHAR_PAIRKERNING ) ); + + // Bullet + // BulletItem und BulletFont fuer Titel und Gliederung + SvxBulletItem aBulletItem(EE_PARA_BULLET); + // die sind in allen Ebenen identisch + aBulletItem.SetStyle(BS_BULLET); + aBulletItem.SetStart(1); + aBulletItem.SetScale(45); // in Prozent + + Font aBulletFont( pSSPool->GetBulletFont() ); + + aBulletFont.SetSize(Size(0,635)); // sj: (i33745) changed default from 24 to 18 pt + + aBulletItem.SetFont(aBulletFont); + aBulletItem.SetSymbol( 0x25CF ); // Punkt + rISet.Put(aBulletItem); + + // Neues BulletItem + pSSPool->PutNumBulletItem( pSheet, aBulletFont ); + + SfxItemSet* pISet = NULL; + + // ---- Objekt mit Pfeilspitze ---------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_OBJWITHARROW)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_OBJWITHARROW ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XLineStyleItem(XLINE_SOLID)); + pISet->Put(XLineColorItem(String(), RGB_Color(COL_BLACK))); + pISet->Put(XLineWidthItem(150)); + + ::basegfx::B2DPolygon aArrow; + aArrow.append(::basegfx::B2DPoint(10.0, 0.0)); + aArrow.append(::basegfx::B2DPoint(0.0, 30.0)); + aArrow.append(::basegfx::B2DPoint(20.0, 30.0)); + aArrow.setClosed(true); + pISet->Put(XLineStartItem(SVX_RESSTR(RID_SVXSTR_ARROW),::basegfx::B2DPolyPolygon(aArrow))); + + pISet->Put(XLineStartWidthItem(700)); + pISet->Put(XLineEndWidthItem(300)); + pISet->Put(XLineStartCenterItem(TRUE)); + + // ---- Objekt mit Schatten ------------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_OBJWITHSHADOW)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_OBJWITHSHADOW ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(SdrShadowItem(TRUE)); + pISet->Put(SdrShadowColorItem(aNullStr, RGB_Color(COL_GRAY))); + pISet->Put(SdrShadowXDistItem(300)); // 3 mm Schattendistanz + pISet->Put(SdrShadowYDistItem(300)); + + // ---- Objekt ohne Fllung ------------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_OBJWITHOUTFILL)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_OBJWITHOUTFILL ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XFillStyleItem(XFILL_NONE)); + + // ---- Text ---------------------------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_TEXT)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_TEXT ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XLineStyleItem(XLINE_NONE)); + pISet->Put(XFillStyleItem(XFILL_NONE)); + + // ---- Textk”rper ---------------------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_TEXTBODY)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_TEXTBODY ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XLineStyleItem(XLINE_NONE)); + pISet->Put(XFillStyleItem(XFILL_NONE)); + + pISet->Put(SvxFontHeightItem(564, 100, EE_CHAR_FONTHEIGHT)); // 16 pt + + // ---- Textk”rper mit Blocksatz -------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_TEXTBODY_JUSTIFY)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_TEXTBODY_JUSTIFY ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XLineStyleItem(XLINE_NONE)); + pISet->Put(XFillStyleItem(XFILL_NONE)); + + pISet->Put(SvxAdjustItem(SVX_ADJUST_BLOCK, EE_PARA_JUST )); + + // ---- Textkoerper mit Einzug ----------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_TEXTBODY_INDENT)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_TEXTBODY_INDENT ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XLineStyleItem(XLINE_NONE)); + pISet->Put(XFillStyleItem(XFILL_NONE)); + + SvxLRSpaceItem aLRSpaceItem( EE_PARA_LRSPACE ); + aLRSpaceItem.SetTxtFirstLineOfst(600); // Erstzeileneinzug 6mm, rechts 0 + pISet->Put(aLRSpaceItem); + +/* #i35937# */ + // ---- Titel --------------------------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_TITLE)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_TITLE ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XLineStyleItem(XLINE_NONE)); + pISet->Put(XFillStyleItem(XFILL_NONE)); + + pISet->Put(SvxFontHeightItem(1551, 100, EE_CHAR_FONTHEIGHT )); // 44 pt + + // ---- Titel1 -------------------------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_TITLE1)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_TITLE1 ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XLineStyleItem(XLINE_NONE)); + pISet->Put(XFillStyleItem(XFILL_SOLID)); + pISet->Put(XFillColorItem(String(), RGB_Color(COL_CYAN))); + + pISet->Put(SdrShadowItem(TRUE)); + pISet->Put(SdrShadowColorItem(aNullStr, RGB_Color(COL_GRAY))); + pISet->Put(SdrShadowXDistItem(200)); // 2 mm Schattendistanz + pISet->Put(SdrShadowYDistItem(200)); + + pISet->Put(SvxFontHeightItem(846, 100, EE_CHAR_FONTHEIGHT )); // 24 pt + + pISet->Put(SvxAdjustItem(SVX_ADJUST_CENTER, EE_PARA_JUST )); + + // ---- Titel2 -------------------------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_TITLE2)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_TITLE2 ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XLineWidthItem(50)); + + // Farbe nicht aus der Farbtabelle holen, denn da kann diese Farbe + // geloescht oder veraendert sein + Color aOrange4(255, 204, 153); + pISet->Put(XFillColorItem(String(), aOrange4)); + + pISet->Put(SdrShadowItem(TRUE)); + pISet->Put(SdrShadowColorItem(aNullStr, RGB_Color(COL_GRAY))); + pISet->Put(SdrShadowXDistItem(200)); // 2 mm Schattendistanz + pISet->Put(SdrShadowYDistItem(200)); + + pISet->Put(SvxFontHeightItem(1270, 100, EE_CHAR_FONTHEIGHT )); // 36 pt + + SvxLRSpaceItem aLRSpItem( 200, 200, 0, 0, EE_PARA_LRSPACE); + pISet->Put( aLRSpItem ); // Erstzeileneinzug 0 mm, links und rechts 2 mm + +/* #i35937# */ + + pISet->Put(SvxULSpaceItem(100, 100, EE_PARA_ULSPACE )); // Absatzrand oben/unten 1 mm + + pISet->Put(SvxAdjustItem(SVX_ADJUST_CENTER, EE_PARA_JUST )); + + // ---- Ueberschrift --------------------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_HEADLINE)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_HEADLINE ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XLineStyleItem(XLINE_NONE)); + pISet->Put(XFillStyleItem(XFILL_NONE)); + + pISet->Put(SvxFontHeightItem(846, 100, EE_CHAR_FONTHEIGHT )); // 24 pt + + pISet->Put(SvxULSpaceItem(420, 210, EE_PARA_ULSPACE )); // Absatzrand oben 4,2 mm, + // unten 2,1 mm + + // ---- Ueberschrift1 -------------------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_HEADLINE1)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_HEADLINE1 ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XLineStyleItem(XLINE_NONE)); + pISet->Put(XFillStyleItem(XFILL_NONE)); + + pISet->Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT )); + + pISet->Put(SvxFontHeightItem(635, 100, EE_CHAR_FONTHEIGHT )); // 18 pt + + pISet->Put(SvxULSpaceItem(420, 210, EE_PARA_ULSPACE )); // Absatzrand oben 4,2 mm, + // unten 2,1 mm + + // ---- Ueberschrift2 -------------------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_HEADLINE2)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_HEADLINE2 ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XLineStyleItem(XLINE_NONE)); + pISet->Put(XFillStyleItem(XFILL_NONE)); + + pISet->Put(SvxPostureItem(ITALIC_NORMAL, EE_CHAR_ITALIC )); + pISet->Put(SvxWeightItem(WEIGHT_BOLD, EE_CHAR_WEIGHT)); + + pISet->Put(SvxFontHeightItem(494, 100, EE_CHAR_FONTHEIGHT )); // 14 pt + + pISet->Put(SvxULSpaceItem(420, 210, EE_PARA_ULSPACE )); // Absatzrand oben 4,2 mm, + // unten 2,1 mm + + // ---- Bemassung -------------------------------------------------- + + aName = String(SdResId(STR_POOLSHEET_MEASURE)); + pSheet = &(pSSPool->Make(aName, SD_STYLE_FAMILY_GRAPHICS, nMask)); + pSheet->SetParent(aStdName); + pSheet->SetHelpId( aHelpFile, HID_POOLSHEET_MEASURE ); + pISet = &pSheet->GetItemSet(); + + pISet->Put(XFillStyleItem(XFILL_NONE)); + + pISet->Put(SvxFontHeightItem(423, 100, EE_CHAR_FONTHEIGHT )); // 12 pt + + pISet->Put(XLineStartItem(SVX_RESSTR(RID_SVXSTR_ARROW),::basegfx::B2DPolyPolygon(aArrow))); + pISet->Put(XLineStartWidthItem(200)); + pISet->Put(XLineEndItem(SVX_RESSTR(RID_SVXSTR_ARROW),::basegfx::B2DPolyPolygon(aArrow))); + pISet->Put(XLineEndWidthItem(200)); + pISet->Put(XLineStyleItem(XLINE_SOLID)); + pISet->Put(SdrMeasureShowUnitItem(true)); + + // Praesentationsvorlagen fuer das Standardlayout erzeugen + String aPrefix = String(SdResId(STR_LAYOUT_DEFAULT_NAME)); + pSSPool->CreateLayoutStyleSheets(aPrefix); +} + +static Any implMakeSolidCellStyle( SdStyleSheetPool* pSSPool, const OUString& rName, const OUString rParent, const Color& rColor ) +{ + SfxStyleSheetBase* pSheet = &(pSSPool->Make(rName, SD_STYLE_FAMILY_CELL, SFXSTYLEBIT_AUTO)); + pSheet->SetParent(rParent); + SfxItemSet* pISet = &pSheet->GetItemSet(); + pISet->Put(XFillStyleItem(XFILL_SOLID)); + pISet->Put(XFillColorItem(String(), rColor)); + + return Any( Reference< XStyle >( static_cast< XWeak* >( pSheet ), UNO_QUERY ) ); +} + +static void implCreateTableTemplate( const Reference< XNameContainer >& xTableFamily, const OUString& rName, const Any& rBody, const Any& rHeading, const Any& rBanding ) +{ + if( xTableFamily.is() ) try + { + if( !xTableFamily->hasByName( OUString( rName ) ) ) + { + Reference< XSingleServiceFactory > xFactory( xTableFamily, UNO_QUERY_THROW ); + Reference< XNameReplace > xDefaultTableStyle( xFactory->createInstance(), UNO_QUERY_THROW ); + xTableFamily->insertByName( OUString( rName ), Any( xDefaultTableStyle ) ); + + xDefaultTableStyle->replaceByName( OUString( RTL_CONSTASCII_USTRINGPARAM("body") ), rBody ); + xDefaultTableStyle->replaceByName( OUString( RTL_CONSTASCII_USTRINGPARAM("odd-rows") ), rBanding ); + xDefaultTableStyle->replaceByName( OUString( RTL_CONSTASCII_USTRINGPARAM("odd-columns") ), rBanding ); + xDefaultTableStyle->replaceByName( OUString( RTL_CONSTASCII_USTRINGPARAM("first-row") ), rHeading ); + xDefaultTableStyle->replaceByName( OUString( RTL_CONSTASCII_USTRINGPARAM("first-column") ), rHeading ); + xDefaultTableStyle->replaceByName( OUString( RTL_CONSTASCII_USTRINGPARAM("last-row") ), rHeading ); + xDefaultTableStyle->replaceByName( OUString( RTL_CONSTASCII_USTRINGPARAM("last-column") ), rHeading ); + } + } + catch( Exception& ) + { + DBG_ERROR("sd::implCreateTableTemplate(), exception caught!"); + } +} + +void SdDrawDocument::CreateDefaultCellStyles() +{ + SdStyleSheetPool* pSSPool = static_cast< SdStyleSheetPool* >(GetStyleSheetPool()); + SfxStyleSheetBase* pSheet = NULL; + String aHelpFile; + + const OUString sFamilyName( RTL_CONSTASCII_USTRINGPARAM( "table" ) ); + Reference< XNameContainer > xTableFamily( pSSPool->getByName( sFamilyName ), UNO_QUERY ); + + // ---- Default ----------------------------------------------- + + USHORT nMask = SFXSTYLEBIT_AUTO; + + OUString aDefaultCellStyleName( RTL_CONSTASCII_USTRINGPARAM("default") ); + + pSheet = &(pSSPool->Make(aDefaultCellStyleName, SD_STYLE_FAMILY_CELL, nMask)); + pSheet->SetHelpId( aHelpFile, HID_SD_CELL_STYLE_DEFAULT ); + SfxItemSet& rISet = pSheet->GetItemSet(); + + String aNullStr; + + Color aNullCol(RGB_Color(COL_BLACK)); + + XDash aNullDash; + XGradient aNullGrad(aNullCol,RGB_Color(COL_WHITE)); + aNullGrad.SetStartIntens( 100 ); + aNullGrad.SetEndIntens( 100 ); + XHatch aNullHatch(aNullCol); + + rISet.Put(XFillStyleItem(XFILL_SOLID)); + rISet.Put(XFillColorItem(String(), RGB_Color(0x00ccccff))); + + Font aLatinFont, aCJKFont, aCTLFont; + + getDefaultFonts( aLatinFont, aCJKFont, aCTLFont ); + + SvxFontItem aSvxFontItem( aLatinFont.GetFamily(), aLatinFont.GetName(), aLatinFont.GetStyleName(), aLatinFont.GetPitch(), + aLatinFont.GetCharSet(), EE_CHAR_FONTINFO ); + + SvxFontItem aSvxFontItemCJK( aCJKFont.GetFamily(), aCJKFont.GetName(), aCJKFont.GetStyleName(), aCJKFont.GetPitch(), + aCJKFont.GetCharSet(), EE_CHAR_FONTINFO_CJK ); + + SvxFontItem aSvxFontItemCTL( aCTLFont.GetFamily(), aCTLFont.GetName(), aCTLFont.GetStyleName(), aCTLFont.GetPitch(), + aCTLFont.GetCharSet(), EE_CHAR_FONTINFO_CTL ); + + rISet.Put( aSvxFontItem ); + rISet.Put( aSvxFontItemCJK ); + rISet.Put( aSvxFontItemCTL ); + + rISet.Put( SvxFontHeightItem( 635, 100, EE_CHAR_FONTHEIGHT ) ); // sj: (i33745) changed default from 24 to 18 pt + rISet.Put( SvxFontHeightItem( 635, 100, EE_CHAR_FONTHEIGHT_CJK ) ); // 18 pt + rISet.Put( SvxFontHeightItem( convertFontHeightToCTL( 635 ), 100, EE_CHAR_FONTHEIGHT_CTL ) ); // 18 pt + + rISet.Put(SvxColorItem(Color(COL_AUTO), EE_CHAR_COLOR )); + + // Absatzattribute (Edit Engine) + rISet.Put(SvxLRSpaceItem(EE_PARA_LRSPACE)); + rISet.Put(SvxULSpaceItem(EE_PARA_ULSPACE)); + + rISet.Put( SdrTextLeftDistItem( 250 ) ); + rISet.Put( SdrTextRightDistItem( 250 ) ); + rISet.Put( SdrTextUpperDistItem( 130 ) ); + rISet.Put( SdrTextLowerDistItem( 130 ) ); + + rISet.Put( SvxLineSpacingItem( LINE_SPACE_DEFAULT_HEIGHT, EE_PARA_SBL ) ); + rISet.Put( SvxAutoKernItem( TRUE, EE_CHAR_PAIRKERNING ) ); + rISet.Put( SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP) ); + rISet.Put( SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT) ); + + Color aWhite( COL_WHITE ); + SvxBorderLine aBorderLine( &aWhite, 1, 0, 0 ); + + SvxBoxItem aBoxItem( SDRATTR_TABLE_BORDER ); + aBoxItem.SetLine( &aBorderLine, BOX_LINE_TOP ); + aBoxItem.SetLine( &aBorderLine, BOX_LINE_BOTTOM ); + aBoxItem.SetLine( &aBorderLine, BOX_LINE_LEFT ); + aBoxItem.SetLine( &aBorderLine, BOX_LINE_RIGHT ); + + rISet.Put( aBoxItem ); + + Any aDefaultCellStyle( Reference< XStyle >( static_cast< XWeak* >( pSheet ), UNO_QUERY ) ); + + // ---- default -------------------------------------------------- + + Any aGray1( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("gray1") ), aDefaultCellStyleName, RGB_COLORDATA(230,230,230))); + Any aGray2( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("gray2") ), aDefaultCellStyleName, RGB_COLORDATA(204,204,204))); + Any aGray3( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("gray3") ), aDefaultCellStyleName, RGB_COLORDATA(179,179,179))); + + implCreateTableTemplate( xTableFamily, OUString(RTL_CONSTASCII_USTRINGPARAM("default") ), aGray1, aGray3, aGray2 ); + + // ---- BW ------------------------------------------------ + + Any aBW1( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("bw1") ), aDefaultCellStyleName, RGB_COLORDATA(255,255,255))); + Any aBW2( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("bw2") ), aDefaultCellStyleName, RGB_COLORDATA(230,230,230))); + Any aBW3( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("bw3") ), aDefaultCellStyleName, RGB_COLORDATA(0,0,0))); + + implCreateTableTemplate( xTableFamily, OUString(RTL_CONSTASCII_USTRINGPARAM("bw") ), aBW1, aBW3, aBW2 ); + + // ---- Orange -------------------------------------------------- + + Any aOrange1( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("orange1") ), aDefaultCellStyleName, RGB_COLORDATA(255,204,153))); + Any aOrange2( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("orange2") ), aDefaultCellStyleName, RGB_COLORDATA(255,153,102))); + Any aOrange3( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("orange3") ), aDefaultCellStyleName, RGB_COLORDATA(255,102,51))); + + implCreateTableTemplate( xTableFamily, OUString(RTL_CONSTASCII_USTRINGPARAM("orange") ), aOrange1, aOrange3, aOrange2 ); + + // ---- Turquise -------------------------------------------------- + + Any aTurquise1( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("turquise1") ), aDefaultCellStyleName, RGB_COLORDATA(71,184,184))); + Any aTurquise2( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("turquise2") ), aDefaultCellStyleName, RGB_COLORDATA(51,163,163))); + Any aTurquise3( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("turquise3") ), aDefaultCellStyleName, RGB_COLORDATA(25,138,138))); + + implCreateTableTemplate( xTableFamily, OUString(RTL_CONSTASCII_USTRINGPARAM("turquise") ), aTurquise1, aTurquise3, aTurquise2 ); + + // ---- Gray ------------------------------------------------ + + Any aBlue1( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("blue1") ), aDefaultCellStyleName, RGB_COLORDATA(153,204,255))); + Any aBlue2( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("blue2") ), aDefaultCellStyleName, RGB_COLORDATA(0,153,255))); + Any aBlue3( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("blue3") ), aDefaultCellStyleName, RGB_COLORDATA(0,102,204))); + + implCreateTableTemplate( xTableFamily, OUString(RTL_CONSTASCII_USTRINGPARAM("blue")), aBlue1, aBlue3, aBlue2 ); + + // ---- Sun ------------------------------------------------ + + Any aSun1( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("sun1") ), aDefaultCellStyleName, RGB_COLORDATA(230,230,255))); + Any aSun2( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("sun2") ), aDefaultCellStyleName, RGB_COLORDATA(204,204,255))); + Any aSun3( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("sun3") ), aDefaultCellStyleName, RGB_COLORDATA(153,153,255))); + + implCreateTableTemplate( xTableFamily, OUString(RTL_CONSTASCII_USTRINGPARAM("sun") ), aSun1, aSun3, aSun2 ); + + // ---- Earth ---------------------------------------------- + + Any aEarth1( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("earth1") ), aDefaultCellStyleName, RGB_COLORDATA(255,255,204))); + Any aEarth2( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("earth2") ), aDefaultCellStyleName, RGB_COLORDATA(255,204,153))); + Any aEarth3( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("earth3") ), aDefaultCellStyleName, RGB_COLORDATA(204,102,51))); + + implCreateTableTemplate( xTableFamily, OUString(RTL_CONSTASCII_USTRINGPARAM("earth") ), aEarth1, aEarth3, aEarth2 ); + + // ---- Green ---------------------------------------------- + + Any aGreen1( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("green1") ), aDefaultCellStyleName, RGB_COLORDATA(255,255,204))); + Any aGreen2( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("green2") ), aDefaultCellStyleName, RGB_COLORDATA(148,189,94))); + Any aGreen3( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("green3") ), aDefaultCellStyleName, RGB_COLORDATA(92,133,38))); + + implCreateTableTemplate( xTableFamily, OUString(RTL_CONSTASCII_USTRINGPARAM("green") ), aGreen1, aGreen3, aGreen2 ); + + // ---- Seetang ---------------------------------------------- + + Any aSeetang1( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("seetang1") ), aDefaultCellStyleName, RGB_COLORDATA(204,255,255))); + Any aSeetang2( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("seetang2") ), aDefaultCellStyleName, RGB_COLORDATA(71,184,184))); + Any aSeetang3( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("seetang3") ), aDefaultCellStyleName, RGB_COLORDATA(51,163,163))); + + implCreateTableTemplate( xTableFamily, OUString(RTL_CONSTASCII_USTRINGPARAM("seetang") ), aSeetang1, aSeetang3, aSeetang2 ); + + // ---- LightBlue ---------------------------------------------- + + Any aLightBlue1( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("lightblue1") ), aDefaultCellStyleName, RGB_COLORDATA(255,255,255))); + Any aLightBlue2( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("lightblue2") ), aDefaultCellStyleName, RGB_COLORDATA(230,230,255))); + Any aLightBlue3( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("lightblue3") ), aDefaultCellStyleName, RGB_COLORDATA(153,153,204))); + + implCreateTableTemplate( xTableFamily, OUString(RTL_CONSTASCII_USTRINGPARAM("lightblue") ), aLightBlue1, aLightBlue3, aLightBlue2 ); + + // ---- Yellow ---------------------------------------------- + + Any aYellow1( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("yellow1") ), aDefaultCellStyleName, RGB_COLORDATA(255,255,204))); + Any aYellow2( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("yellow2") ), aDefaultCellStyleName, RGB_COLORDATA(255,255,153))); + Any aYellow3( implMakeSolidCellStyle( pSSPool, OUString( RTL_CONSTASCII_USTRINGPARAM("yellow3") ), aDefaultCellStyleName, RGB_COLORDATA(255,204,153))); + + implCreateTableTemplate( xTableFamily, OUString(RTL_CONSTASCII_USTRINGPARAM("yellow") ), aYellow1, aYellow3, aYellow2 ); +} + +/************************************************************************* +|* +|* Anzahl der Seiten, die eine masterPage referenzieren +|* +\************************************************************************/ + +USHORT SdDrawDocument::GetMasterPageUserCount(SdrPage* pMaster) const +{ + USHORT nResult = 0; + USHORT nPage; + USHORT nPageCount = GetPageCount(); + + for (nPage = 0; nPage < nPageCount; nPage++) + { + const SdrPage* pPage = GetPage(nPage); + + if(pPage->TRG_HasMasterPage()) + { + if(&(pPage->TRG_GetMasterPage()) == pMaster) + { + nResult++; + } + } + } + return nResult; +} + + +/************************************************************************* +|* +|* OnlineSpelling im Hintergrund beenden +|* +\************************************************************************/ + +void SdDrawDocument::StopOnlineSpelling() +{ + if (mpOnlineSpellingTimer && mpOnlineSpellingTimer->IsActive()) + { + mpOnlineSpellingTimer->Stop(); + } + + delete mpOnlineSpellingTimer; + mpOnlineSpellingTimer = NULL; + + delete mpOnlineSpellingList; + mpOnlineSpellingList = NULL; +} + +/************************************************************************* +|* +|* OnlineSpelling im Hintergrund starten +|* +\************************************************************************/ + +void SdDrawDocument::StartOnlineSpelling(BOOL bForceSpelling) +{ + if (mbOnlineSpell && (bForceSpelling || mbInitialOnlineSpellingEnabled) && + mpDocSh && !mpDocSh->IsReadOnly() ) + { + StopOnlineSpelling(); + + ::sd::Outliner* pOutl = GetInternalOutliner(TRUE); + + Reference< XSpellChecker1 > xSpellChecker( LinguMgr::GetSpellChecker() ); + if ( xSpellChecker.is() ) + pOutl->SetSpeller( xSpellChecker ); + + Reference< XHyphenator > xHyphenator( LinguMgr::GetHyphenator() ); + if( xHyphenator.is() ) + pOutl->SetHyphenator( xHyphenator ); + + pOutl->SetDefaultLanguage( meLanguage ); + + mpOnlineSpellingList = new ShapeList; + USHORT nPage; + + for ( nPage = 0; nPage < GetPageCount(); nPage++ ) + { + // Alle Pages durchsuchen + FillOnlineSpellingList((SdPage*) GetPage(nPage)); + } + + for (nPage = 0; nPage < GetMasterPageCount(); nPage++) + { + // Alle MasterPages durchsuchen + FillOnlineSpellingList((SdPage*) GetMasterPage(nPage)); + } + + mpOnlineSpellingList->seekShape(0); + mpOnlineSpellingTimer = new Timer(); + mpOnlineSpellingTimer->SetTimeoutHdl( LINK(this, SdDrawDocument, OnlineSpellingHdl) ); + mpOnlineSpellingTimer->SetTimeout(250); + mpOnlineSpellingTimer->Start(); + } +} + +/************************************************************************* +|* +|* OnlineSpelling-Liste fuellen +|* +\************************************************************************/ + +void SdDrawDocument::FillOnlineSpellingList(SdPage* pPage) +{ + SdrObject* pObj = NULL; + SdrObjListIter aIter(*pPage, IM_FLAT); + + while (aIter.IsMore()) + { + pObj = aIter.Next(); + + if( !pObj ) + continue; + + if (pObj->GetOutlinerParaObject()) + { + // Textobjekt gefunden + mpOnlineSpellingList->addShape(*pObj); + } + else if (pObj->GetObjIdentifier() == OBJ_GRUP) + { + // Gruppenobjekt gefunden + SdrObjListIter aGroupIter(*((SdrObjGroup*)pObj)->GetSubList(), + IM_DEEPNOGROUPS); + + BOOL bSubTextObjFound = FALSE; + + while (aGroupIter.IsMore() && !bSubTextObjFound) + { + if (aGroupIter.Next()->GetOutlinerParaObject()) + { + // Textobjekt im Gruppenobjekt gefunden + bSubTextObjFound = TRUE; + } + } + + if (bSubTextObjFound) + { + mpOnlineSpellingList->addShape(*pObj); + } + } + } +} + +/************************************************************************* +|* +|* OnlineSpelling im Hintergrund +|* +\************************************************************************/ + +IMPL_LINK(SdDrawDocument, OnlineSpellingHdl, Timer*, EMPTYARG ) +{ + if (mpOnlineSpellingList!=NULL + && ( !mbOnlineSpell || mpOnlineSpellingList->hasMore())) + { + /********************************************************************** + * Naechstes Objekt spellen + **********************************************************************/ + SdrObject* pObj = mpOnlineSpellingList->getNextShape(); + + if (pObj) + { + if (pObj->GetOutlinerParaObject() && pObj->ISA(SdrTextObj)) + { + // Textobjekt spellen + SpellObject((SdrTextObj*) pObj); + } + else if (pObj->GetObjIdentifier() == OBJ_GRUP) + { + // Gruppenobjekt gefunden + SdrObjListIter aGroupIter(*((SdrObjGroup*)pObj)->GetSubList(), + IM_DEEPNOGROUPS); + + SdrObject* pSubObj = NULL; + + while (aGroupIter.IsMore()) + { + pSubObj = aGroupIter.Next(); + + if (pSubObj->GetOutlinerParaObject() && pSubObj->ISA(SdrTextObj)) + { + // Textobjekt im Gruppenobjekt gefunden + SpellObject((SdrTextObj*) pSubObj); + } + } + } + } + + // Weitersuchen + mpOnlineSpellingTimer->Start(); + } + else + { + // Spelling wurde initial durchgefuehrt + mbInitialOnlineSpellingEnabled = FALSE; + + // Suche beenden + StopOnlineSpelling(); + + delete mpOnlineSearchItem; + mpOnlineSearchItem = NULL; + } + + return(0); +} + +/************************************************************************* +|* +|* Objekt spellen (fuer OnlineSpelling) +|* +\************************************************************************/ + +void SdDrawDocument::SpellObject(SdrTextObj* pObj) +{ + if (pObj && pObj->GetOutlinerParaObject() /* && pObj != pView->GetTextEditObject() */) + { + mbHasOnlineSpellErrors = FALSE; + ::sd::Outliner* pOutl = GetInternalOutliner(TRUE); + pOutl->SetUpdateMode(TRUE); + Link aEvtHdl = pOutl->GetStatusEventHdl(); + pOutl->SetStatusEventHdl(LINK(this, SdDrawDocument, OnlineSpellEventHdl)); + + USHORT nOldOutlMode = pOutl->GetMode(); + USHORT nOutlMode = OUTLINERMODE_TEXTOBJECT; + if (((SdrTextObj*) pObj)->GetObjInventor() == SdrInventor && + ((SdrTextObj*) pObj)->GetObjIdentifier() == OBJ_OUTLINETEXT) + { + nOutlMode = OUTLINERMODE_OUTLINEOBJECT; + } + pOutl->Init( nOutlMode ); + + // Text in den Outliner setzen + pOutl->SetText(*((SdrTextObj*) pObj)->GetOutlinerParaObject()); + + if (!mpOnlineSearchItem || pOutl->HasText(*mpOnlineSearchItem)) + { + // Spelling + pOutl->CompleteOnlineSpelling(); + + if (mbHasOnlineSpellErrors) + { + sd::ModifyGuard aGuard( this ); + SdrModel* pModel = pObj->GetModel(); + bool bLock = sal_False; + if ( pModel ) + { + bLock = pModel->isLocked(); + pModel->setLock(true); + } + // taking text from the outliner + ((SdrTextObj*) pObj)->SetOutlinerParaObject( pOutl->CreateParaObject() ); + + pObj->BroadcastObjectChange(); + if ( pModel ) + pModel->setLock(bLock); + } + } + + pOutl->SetStatusEventHdl(aEvtHdl); + pOutl->SetUpdateMode(FALSE); + pOutl->Init( nOldOutlMode ); + mbHasOnlineSpellErrors = FALSE; + } +} + +/************************************************************************* +|* +|* Objekt wurde ins Model eingefuegt +|* +\************************************************************************/ +void SdDrawDocument::InsertObject(SdrObject* pObj, SdPage* /*pPage*/) +{ + if(mpOnlineSpellingList && pObj) + { + if (pObj->GetOutlinerParaObject() || (pObj->GetObjIdentifier() == OBJ_GRUP)) + { + // Objekt in OnlineSpelling-Liste aufnehmen + mpOnlineSpellingList->addShape(*pObj); + } + } +} + +/************************************************************************* +|* +|* Objekt wurde aus dem Model entfernt +|* +\************************************************************************/ +void SdDrawDocument::RemoveObject(SdrObject* pObj, SdPage* /*pPage*/) +{ + if(mpOnlineSpellingList && pObj) + { + if (pObj->GetOutlinerParaObject() || (pObj->GetObjIdentifier() == OBJ_GRUP)) + { + // Objekt in OnlineSpelling-Liste durch NULL-Pointer ersetzt + mpOnlineSpellingList->removeShape(*pObj); + } + } +} + +/************************************************************************* +|* +|* Callback fuer ExecuteSpellPopup() +|* +\************************************************************************/ +IMPL_LINK(SdDrawDocument, OnlineSpellEventHdl, EditStatus*, pEditStat) +{ + ULONG nStat = pEditStat->GetStatusWord(); + mbHasOnlineSpellErrors = (nStat & EE_STAT_WRONGWORDCHANGED) != 0; + + return(0); +} + +/************************************************************************* +|* +|* Callback fuer ExecuteSpellPopup() +|* +\************************************************************************/ + +// #91457# removed link and replaced with Imp method +void SdDrawDocument::ImpOnlineSpellCallback(SpellCallbackInfo* pInfo, SdrObject* pObj, SdrOutliner* pOutl) +{ + delete mpOnlineSearchItem; + mpOnlineSearchItem = NULL; + + USHORT nCommand = pInfo->nCommand; + + if (nCommand == SPELLCMD_IGNOREWORD + // #91457# restart when add to dictionary takes place, too. + || nCommand == SPELLCMD_ADDTODICTIONARY) + { + if(pObj && pOutl && pObj->ISA(SdrTextObj)) + { + BOOL bModified(IsChanged()); + ((SdrTextObj*)pObj)->SetOutlinerParaObject(pOutl->CreateParaObject()); + SetChanged(bModified); + pObj->BroadcastObjectChange(); + } + + mpOnlineSearchItem = new SvxSearchItem( SID_SEARCH_ITEM ); + mpOnlineSearchItem->SetSearchString(pInfo->aWord); + StartOnlineSpelling(); + } + else if (nCommand == SPELLCMD_STARTSPELLDLG) + { + SfxViewFrame::Current()->GetDispatcher()->Execute( SID_SPELL_DIALOG, + SFX_CALLMODE_ASYNCHRON ); + } +} + +/************************************************************************* +|* +|* Eindeutige Namen der StandardLayer durch sprachabhaengige Namen ersetzen +|* +\************************************************************************/ +void SdDrawDocument::RestoreLayerNames() +{ + SdrLayerAdmin& rLayerAdmin = GetLayerAdmin(); + USHORT nLayerCount = rLayerAdmin.GetLayerCount(); + + for (USHORT nLayer = 0; nLayer < nLayerCount; nLayer++) + { + SdrLayer* pLayer = rLayerAdmin.GetLayer(nLayer); + + if (pLayer) + { + String aLayerName(pLayer->GetName()); + + if (aLayerName.EqualsAscii( "LAYER_LAYOUT" )) + { + pLayer->SetName(String(SdResId(STR_LAYER_LAYOUT))); + } + else if (aLayerName.EqualsAscii( "LAYER_BCKGRND" )) + { + pLayer->SetName(String(SdResId(STR_LAYER_BCKGRND))); + } + else if (aLayerName.EqualsAscii( "LAYER_BACKGRNDOBJ" )) + { + pLayer->SetName(String(SdResId(STR_LAYER_BCKGRNDOBJ))); + } + else if (aLayerName.EqualsAscii( "LAYER_CONTROLS" )) + { + pLayer->SetName(String(SdResId(STR_LAYER_CONTROLS))); + } + else if (aLayerName.EqualsAscii( "LAYER_MEASURELINES" )) + { + pLayer->SetName(String(SdResId(STR_LAYER_MEASURELINES))); + } + } + } +} + +/************************************************************************* +|* +|* Formatierte Seitennummer zurueckgeben (1, I, i, a, usw.) +|* +\************************************************************************/ + +String SdDrawDocument::CreatePageNumValue(USHORT nNum) const +{ + String aPageNumValue; + BOOL bUpper = FALSE; + + switch (mePageNumType) + { + case SVX_CHARS_UPPER_LETTER: + aPageNumValue += (sal_Unicode)(char)((nNum - 1) % 26 + 'A'); + break; + case SVX_CHARS_LOWER_LETTER: + aPageNumValue += (sal_Unicode)(char)((nNum - 1) % 26 + 'a'); + break; + case SVX_ROMAN_UPPER: + bUpper = TRUE; + case SVX_ROMAN_LOWER: + aPageNumValue += SvxNumberFormat::CreateRomanString(nNum, bUpper); + break; + case SVX_NUMBER_NONE: + aPageNumValue.Erase(); + aPageNumValue += sal_Unicode(' '); + break; + default: + aPageNumValue += String::CreateFromInt32( (sal_Int32)nNum ); + } + + return(aPageNumValue); +} + + + +/************************************************************************* +|* +|* Layout-Template umbenennen +|* Zu beachten ist, das rOldLayoutName im Gegensatz zu rNewName den +|* kompletten Layout(!)-Namen enthaelt (inkl. ~LT~)! +|* +\************************************************************************/ + +void SdDrawDocument::RenameLayoutTemplate(const String& rOldLayoutName, const String& rNewName) +{ + String aOldName(rOldLayoutName); + USHORT nPos = aOldName.SearchAscii( SD_LT_SEPARATOR ); + + // erase everything after '~LT~' + aOldName.Erase(nPos + sizeof(SD_LT_SEPARATOR) - 1 ); + USHORT nLen = aOldName.Len(); + + List aReplList; + SfxStyleSheetIterator aIter(mxStyleSheetPool.get(), SD_STYLE_FAMILY_MASTERPAGE); + SfxStyleSheetBase* pSheet = aIter.First(); + + while (pSheet) + { + String aSheetName = pSheet->GetName(); + + // if the sheetname starts with aOldName + "~LT~" + if (aSheetName.Match(aOldName) == nLen) + { + aSheetName.Erase(0, nLen - sizeof(SD_LT_SEPARATOR) + 1 ); + aSheetName.Insert(rNewName, 0); + + StyleReplaceData* pReplData = new StyleReplaceData; + pReplData->nFamily = pSheet->GetFamily(); + pReplData->nNewFamily = pSheet->GetFamily(); + pReplData->aName = pSheet->GetName(); + pReplData->aNewName = aSheetName; + aReplList.Insert(pReplData, LIST_APPEND); + + pSheet->SetName(aSheetName); + } + + pSheet = aIter.Next(); + } + + // jetzt noch den Layoutnamen der Zeichen- und der Notizseite + // sowie ihrer Masterpages setzen + String aPageLayoutName(rNewName); + aPageLayoutName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( SD_LT_SEPARATOR )); + aPageLayoutName += String(SdResId(STR_LAYOUT_OUTLINE)); + + // an allen Seiten, die das jetzt umbeannte Layout benutzen, die + // Textobjekte von der Aenderung unterrichten und Layoutnamen setzen + USHORT nPage; + for (nPage = 0; nPage < GetPageCount(); nPage++) + { + SdPage* pPage = (SdPage*) GetPage(nPage); + String aTemp(pPage->GetLayoutName()); + + if (aTemp == rOldLayoutName) + { + pPage->SetLayoutName(aPageLayoutName); + + for (ULONG nObj = 0; nObj < pPage->GetObjCount(); nObj++) + { + SdrObject* pObj = pPage->GetObj(nObj); + + if (pObj->GetObjInventor() == SdrInventor) + { + switch( pObj->GetObjIdentifier() ) + { + case OBJ_TEXT: + case OBJ_OUTLINETEXT: + case OBJ_TITLETEXT: + { + OutlinerParaObject* pOPO = ((SdrTextObj*) pObj)->GetOutlinerParaObject(); + + if (pOPO) + { + StyleReplaceData* pReplData = (StyleReplaceData*) aReplList.First(); + + while( pReplData ) + { + pOPO->ChangeStyleSheets( pReplData->aName, pReplData->nFamily, pReplData->aNewName, pReplData->nNewFamily ); + pReplData = (StyleReplaceData*) aReplList.Next(); + } + } + } + break; + + default: + break; + } + } + } + } + } + + // und nochmal fuer die Masterpages + // die betroffenen Masterpages erhalten als Seitennamen den Namen + // des Layouts + for (nPage = 0; nPage < GetMasterPageCount(); nPage++) + { + SdPage* pPage = (SdPage*) GetMasterPage(nPage); + String aTemp(pPage->GetLayoutName()); + + if (aTemp == rOldLayoutName) + { + pPage->SetLayoutName(aPageLayoutName); + pPage->SetName(rNewName); + + for (ULONG nObj = 0; nObj < pPage->GetObjCount(); nObj++) + { + SdrObject* pObj = pPage->GetObj(nObj); + + if (pObj->GetObjInventor() == SdrInventor) + { + switch(pObj->GetObjIdentifier()) + { + case OBJ_TEXT: + case OBJ_OUTLINETEXT: + case OBJ_TITLETEXT: + { + OutlinerParaObject* pOPO = ((SdrTextObj*)pObj)->GetOutlinerParaObject(); + + if (pOPO) + { + StyleReplaceData* pReplData = (StyleReplaceData*) aReplList.First(); + + while( pReplData ) + { + pOPO->ChangeStyleSheets( pReplData->aName, pReplData->nFamily, pReplData->aNewName, pReplData->nNewFamily ); + pReplData = (StyleReplaceData*) aReplList.Next(); + } + } + } + break; + + default: + break; + } + } + } + } + } +} + +/************************************************************************* +|* +|* Outliner-Defaults setzen (Pool-Defaults) +|* +\************************************************************************/ +void SdDrawDocument::SetTextDefaults() const +{ + // BulletItem und BulletFont fuer Titel und Gliederung + SvxBulletItem aBulletItem(EE_PARA_BULLET); + Font aBulletFont( static_cast<SdStyleSheetPool*>( mxStyleSheetPool.get())->GetBulletFont() ); + aBulletFont.SetSize(Size(0,846)); // 24 pt + aBulletItem.SetFont(aBulletFont); + aBulletItem.SetStyle(BS_BULLET); + aBulletItem.SetStart(1); + aBulletItem.SetScale(45); // in Prozent + aBulletItem.SetSymbol( 0x25CF ); // Punkt + pItemPool->SetPoolDefaultItem( aBulletItem ); + + // Neues BulletItem + SvxNumberFormat aNumberFormat(SVX_NUM_CHAR_SPECIAL); + aNumberFormat.SetBulletFont(&aBulletFont); + aNumberFormat.SetBulletChar( 0x25CF ); // StarBats: 0xF000 + 34 + aNumberFormat.SetBulletRelSize(45); + aNumberFormat.SetBulletColor(Color(COL_AUTO)); + aNumberFormat.SetStart(1); + aNumberFormat.SetNumAdjust(SVX_ADJUST_LEFT); + + SvxNumRule aNumRule( NUM_BULLET_REL_SIZE|NUM_BULLET_COLOR|NUM_CHAR_TEXT_DISTANCE, 10, FALSE); + + aNumberFormat.SetLSpace( 0 ); + aNumberFormat.SetAbsLSpace( 0 ); + aNumberFormat.SetFirstLineOffset( 0 ); + aNumRule.SetLevel( 0, aNumberFormat ); + + for( USHORT i = 1; i < aNumRule.GetLevelCount(); i++ ) + { + const short nLSpace = (i + 1) * 600; + aNumberFormat.SetLSpace(nLSpace); + aNumberFormat.SetAbsLSpace(nLSpace); + aNumberFormat.SetFirstLineOffset(-600); + aNumRule.SetLevel( i, aNumberFormat ); + } + + SvxNumBulletItem aNumBulletItem( aNumRule, EE_PARA_NUMBULLET ); + pItemPool->SetPoolDefaultItem( aNumBulletItem ); +} + +::com::sun::star::text::WritingMode SdDrawDocument::GetDefaultWritingMode() const +{ + const SfxPoolItem* pItem = ( pItemPool ? pItemPool->GetPoolDefaultItem( EE_PARA_WRITINGDIR ) : NULL ); + ::com::sun::star::text::WritingMode eRet = ::com::sun::star::text::WritingMode_LR_TB; + + if( pItem ) + { + switch( ( (SvxFrameDirectionItem&)( *pItem ) ).GetValue() ) + { + case( FRMDIR_HORI_LEFT_TOP ): eRet = ::com::sun::star::text::WritingMode_LR_TB; break; + case( FRMDIR_HORI_RIGHT_TOP ): eRet = ::com::sun::star::text::WritingMode_RL_TB; break; + case( FRMDIR_VERT_TOP_RIGHT ): eRet = ::com::sun::star::text::WritingMode_TB_RL; break; + + default: + DBG_ERROR( "Frame direction not supported yet" ); + break; + } + } + + return eRet; +} + +void SdDrawDocument::SetDefaultWritingMode(::com::sun::star::text::WritingMode eMode ) +{ + if( pItemPool ) + { + SvxFrameDirection nVal; + switch( eMode ) + { + case ::com::sun::star::text::WritingMode_LR_TB: nVal = FRMDIR_HORI_LEFT_TOP; break; + case ::com::sun::star::text::WritingMode_RL_TB: nVal = FRMDIR_HORI_RIGHT_TOP; break; + case ::com::sun::star::text::WritingMode_TB_RL: nVal = FRMDIR_VERT_TOP_RIGHT; break; + default: + DBG_ERROR( "Frame direction not supported yet" ); + return; + } + + SvxFrameDirectionItem aModeItem( nVal, EE_PARA_WRITINGDIR ); + pItemPool->SetPoolDefaultItem( aModeItem ); + + SvxAdjustItem aAdjust( SVX_ADJUST_LEFT, EE_PARA_JUST ); + + if( eMode == ::com::sun::star::text::WritingMode_RL_TB ) + aAdjust.SetEnumValue( SVX_ADJUST_RIGHT ); + + pItemPool->SetPoolDefaultItem( aAdjust ); + + + } +} + +void SdDrawDocument::getDefaultFonts( Font& rLatinFont, Font& rCJKFont, Font& rCTLFont ) +{ + LanguageType eLatin = GetLanguage( EE_CHAR_LANGUAGE ); + + // #108374# / #107782#: If the UI language is Korean, the default Latin font has to + // be queried for Korean, too (the Latin language from the document can't be Korean). + // This is the same logic as in SwDocShell::InitNew. + LanguageType eUiLanguage = Application::GetSettings().GetUILanguage(); + switch( eUiLanguage ) + { + case LANGUAGE_KOREAN: + case LANGUAGE_KOREAN_JOHAB: + eLatin = eUiLanguage; + break; + } + + rLatinFont = OutputDevice::GetDefaultFont( DEFAULTFONT_LATIN_PRESENTATION, eLatin, DEFAULTFONT_FLAGS_ONLYONE ); + rCJKFont = OutputDevice::GetDefaultFont( DEFAULTFONT_CJK_PRESENTATION, GetLanguage( EE_CHAR_LANGUAGE_CJK ), DEFAULTFONT_FLAGS_ONLYONE ); + rCTLFont = OutputDevice::GetDefaultFont( DEFAULTFONT_CTL_PRESENTATION, GetLanguage( EE_CHAR_LANGUAGE_CTL ), DEFAULTFONT_FLAGS_ONLYONE ) ; +} + +/* converts the given western font height to a corresponding ctl font height, deppending on the system language */ +sal_uInt32 SdDrawDocument::convertFontHeightToCTL( sal_uInt32 nWesternFontHeight ) +{ + LanguageType eRealCTLLanguage = Application::GetSettings().GetLanguage(); + if( LANGUAGE_THAI == eRealCTLLanguage ) + { + // http://specs.openoffice.org/g11n/font_sizes/42775_42725_Individual_configurable_font_size_for_default_fonts.odt + double fTemp = double(nWesternFontHeight) * 1.333; + nWesternFontHeight = (sal_uInt32)fTemp; + // make some nice values for UI that displays PT instead of 1/100th mm + nWesternFontHeight = ((nWesternFontHeight * 72) + 1270) / 2540L; + nWesternFontHeight = ((nWesternFontHeight * 2540L) + 36) / 72; + } + return nWesternFontHeight; +} + +SdStyleSheetPool* SdDrawDocument::GetSdStyleSheetPool() const +{ + return dynamic_cast< SdStyleSheetPool* >( GetStyleSheetPool() ); +} + +ModifyGuard::ModifyGuard( SdDrawDocument* pDoc ) +: mpDocShell( 0 ), mpDoc( pDoc ) +{ + init(); +} + +void ModifyGuard::init() +{ + if( mpDocShell ) + { + mpDoc = mpDocShell->GetDoc(); + } + else if( mpDoc ) + { + mpDocShell = mpDoc->GetDocSh(); + } + + mbIsEnableSetModified = mpDocShell ? mpDocShell->IsEnableSetModified() : FALSE; + mbIsDocumentChanged = mpDoc ? mpDoc->IsChanged() : FALSE; + + if( mbIsEnableSetModified ) + mpDocShell->EnableSetModified( FALSE ); +} + +ModifyGuard::~ModifyGuard() +{ + if( mbIsEnableSetModified ) + mpDocShell->EnableSetModified( TRUE ); + + if( mpDoc && (mpDoc->IsChanged() != mbIsDocumentChanged) ) + mpDoc->SetChanged(mbIsDocumentChanged); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/drawdoc_animations.cxx b/sd/source/core/drawdoc_animations.cxx new file mode 100644 index 000000000000..2d024f8a7c84 --- /dev/null +++ b/sd/source/core/drawdoc_animations.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include "drawdoc.hxx" +#include "cusshow.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::presentation; + +/** replaces a slide from all custom shows with a new one or removes a slide from + all custom shows if pNewPage is 0. +*/ +void SdDrawDocument::ReplacePageInCustomShows( const SdPage* pOldPage, const SdPage* pNewPage ) +{ + if ( mpCustomShowList ) + { + for (ULONG i = 0; i < mpCustomShowList->Count(); i++) + { + SdCustomShow* pCustomShow = (SdCustomShow*) mpCustomShowList->GetObject(i); + if( pNewPage == 0 ) + pCustomShow->RemovePage(pOldPage); + else + pCustomShow->ReplacePage(pOldPage,pNewPage); + } + } +} + +extern Reference< XPresentation2 > CreatePresentation( const SdDrawDocument& rDocument ); + +const Reference< XPresentation2 >& SdDrawDocument::getPresentation() const +{ + if( !mxPresentation.is() ) + { + const_cast< SdDrawDocument* >( this )->mxPresentation = CreatePresentation(*this); + } + return mxPresentation; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/glob.src b/sd/source/core/glob.src new file mode 100755 index 000000000000..f1c7058ddf79 --- /dev/null +++ b/sd/source/core/glob.src @@ -0,0 +1,426 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +/* StarView ressource file */ + +#define __RSC + +#include "misc.hxx" +#include "glob.hrc" +#include "sderror.hxx" + +String STR_LAYER_BCKGRND +{ + Text [ en-US ] = "Background" ; +}; +String STR_LAYER_BCKGRNDOBJ +{ + Text [ en-US ] = "Background objects" ; +}; +String STR_LAYER_LAYOUT +{ + Text [ en-US ] = "Layout" ; +}; +String STR_LAYER_CONTROLS +{ + Text [ en-US ] = "Controls" ; +}; +String STR_LAYER_MEASURELINES +{ + Text [ en-US ] = "Dimension Lines" ; +}; +String STR_PAGE +{ + Text [ en-US ] = "Slide" ; +}; +String STR_PAGE_NAME +{ + Text [ en-US ] = "Page" ; +}; +String STR_SLIDE_NAME +{ + Text [ en-US ] = "Slide" ; +}; +String STR_MASTERPAGE +{ + Text [ en-US ] = "Background" ; +}; +String STR_NOTES +{ + Text [ en-US ] = "(Notes)" ; +}; +String STR_HANDOUT +{ + Text [ en-US ] = "Handouts" ; +}; +String STR_PRESOBJ_MPTITLE +{ + Text [ en-US ] = "Click to edit the title text format" ; +}; +String STR_PRESOBJ_MPOUTLINE +{ + Text [ en-US ] = "Click to edit the outline text format" ; +}; +String STR_PRESOBJ_MPOUTLLAYER2 +{ + Text [ en-US ] = "Second Outline Level" ; +}; +String STR_PRESOBJ_MPOUTLLAYER3 +{ + Text [ en-US ] = "Third Outline Level" ; +}; +String STR_PRESOBJ_MPOUTLLAYER4 +{ + Text [ en-US ] = "Fourth Outline Level" ; +}; +String STR_PRESOBJ_MPOUTLLAYER5 +{ + Text [ en-US ] = "Fifth Outline Level" ; +}; +String STR_PRESOBJ_MPOUTLLAYER6 +{ + Text [ en-US ] = "Sixth Outline Level" ; +}; +String STR_PRESOBJ_MPOUTLLAYER7 +{ + Text [ en-US ] = "Seventh Outline Level" ; +}; +String STR_PRESOBJ_MPOUTLLAYER8 +{ + Text [ en-US ] = "Eighth Outline Level" ; +}; +String STR_PRESOBJ_MPOUTLLAYER9 +{ + Text [ en-US ] = "Ninth Outline Level" ; +}; +String STR_PRESOBJ_MPNOTESTITLE +{ + Text [ en-US ] = "Click to move the slide" ; +}; +String STR_PRESOBJ_MPNOTESTEXT +{ + Text [ en-US ] = "Click to edit the notes format" ; +}; +String STR_PRESOBJ_TITLE +{ + Text [ en-US ] = "Click to add title" ; +}; +String STR_PRESOBJ_OUTLINE +{ + Text [ en-US ] = "Click to add text" ; +}; +String STR_PRESOBJ_TEXT +{ + Text [ en-US ] = "Click to add text" ; +}; +String STR_PRESOBJ_NOTESTEXT +{ + Text [ en-US ] = "Click to add notes" ; +}; +String STR_PRESOBJ_GRAPHIC +{ + Text [ en-US ] = "Double-click to add graphics" ; +}; +String STR_PRESOBJ_OBJECT +{ + Text [ en-US ] = "Double-click to add an object" ; +}; +String STR_PRESOBJ_CHART +{ + Text [ en-US ] = "Double-click to add a chart" ; +}; +String STR_PRESOBJ_ORGCHART +{ + Text [ en-US ] = "Double-click to add an organization chart" ; +}; +String STR_PRESOBJ_TABLE +{ + Text [ en-US ] = "Double-click to add a spreadsheet" ; +}; +String STR_OUTLINEVIEWSHELL +{ + Text [ en-US ] = "Outline View" ; +}; +String STR_DRAWVIEWSHELL +{ + Text [ en-US ] = "Drawing View" ; +}; +String STR_PRESVIEWSHELL +{ + Text [ en-US ] = "Presentation mode" ; +}; +String STR_PREVIEWVIEWSHELL +{ + Text [ en-US ] = "Preview Window"; +}; +String STR_TEXTOBJECTBARSHELL +{ + Text [ en-US ] = "Text Mode" ; +}; +String STR_STDOBJECTBARSHELL +{ + Text [ en-US ] = "Document Mode" ; +}; +String STR_BEZIEROBJECTBARSHELL +{ + Text [ en-US ] = "Bézier mode" ; +}; +String STR_APPLICATIONOBJECTBAR +{ + Text [ en-US ] = "StarImpress 4.0" ; +}; +String STR_GLUEPOINTSOBJECTBARSHELL +{ + Text [ en-US ] = "Glue Points Mode" ; +}; +/* nicht uebersetzen */ +String STR_LAYOUT_TITLE +{ + Text = "Titel" ; +}; +/* nicht uebersetzen */ +String STR_LAYOUT_OUTLINE +{ + Text = "Gliederung" ; +}; +/* nicht uebersetzen */ +String STR_LAYOUT_BACKGROUND +{ + Text = "Hintergrund" ; +}; +/* nicht uebersetzen */ +String STR_LAYOUT_BACKGROUNDOBJECTS +{ + Text = "Hintergrundobjekte" ; +}; +/* nicht uebersetzen */ +String STR_LAYOUT_NOTES +{ + Text = "Notizen" ; +}; +String STR_LAYOUT_DEFAULT_NAME +{ + Text [ en-US ] = "Default" ; +}; +String STR_LAYOUT_DEFAULT_TITLE_NAME +{ + Text [ en-US ] = "Title" ; +}; +String STR_STANDARD_STYLESHEET_NAME +{ + Text [ en-US ] = "Default" ; +}; +String STR_BAD_PASSWORD_OR_FILE_CORRUPTED +{ + Text [ en-US ] = "The password is incorrect or the file is damaged." ; +}; +String STR_UNDO_MOVEPAGES +{ + Text [ en-US ] = "Move slides" ; +}; +String STR_NOT_ENOUGH_MEMORY +{ + Text [ en-US ] = "Not enough memory!\nThe action will be aborted." ; +}; +/* nicht uebersetzen */ +String STR_LAYOUT_SUBTITLE +{ + Text = "Untertitel" ; +}; +String STR_POOLSHEET_MEASURE +{ + Text [ en-US ] = "Dimension Line" ; +}; +String STR_POOLSHEET_OBJWITHARROW +{ + Text [ en-US ] = "Object with arrow" ; +}; +String STR_POOLSHEET_OBJWITHSHADOW +{ + Text [ en-US ] = "Object with shadow" ; +}; +String STR_POOLSHEET_OBJWITHOUTFILL +{ + Text [ en-US ] = "Object without fill" ; +}; +String STR_POOLSHEET_TEXT +{ + Text [ en-US ] = "Text" ; +}; +String STR_POOLSHEET_TEXTBODY +{ + Text [ en-US ] = "Text body" ; +}; +String STR_POOLSHEET_TEXTBODY_JUSTIFY +{ + Text [ en-US ] = "Text body justified" ; +}; +String STR_POOLSHEET_TEXTBODY_INDENT +{ + Text [ en-US ] = "First line indent" ; +}; +String STR_POOLSHEET_TITLE +{ + Text [ en-US ] = "Title" ; +}; +String STR_POOLSHEET_TITLE1 +{ + Text [ en-US ] = "Title1" ; +}; +String STR_POOLSHEET_TITLE2 +{ + Text [ en-US ] = "Title2" ; +}; +String STR_POOLSHEET_HEADLINE +{ + Text [ en-US ] = "Heading" ; +}; +String STR_POOLSHEET_HEADLINE1 +{ + Text [ en-US ] = "Heading1" ; +}; + +String STR_POOLSHEET_HEADLINE2 +{ + Text [ en-US ] = "Heading2" ; +}; +String STR_EMPTY_STYLESHEET_NAME +{ + Text [ en-US ] = "Blank template" ; +}; +String STR_PSEUDOSHEET_TITLE +{ + Text [ en-US ] = "Title" ; +}; +String STR_PSEUDOSHEET_SUBTITLE +{ + Text [ en-US ] = "Subtitle"; +}; +String STR_PSEUDOSHEET_OUTLINE +{ + Text [ en-US ] = "Outline" ; +}; +String STR_PSEUDOSHEET_BACKGROUNDOBJECTS +{ + Text [ en-US ] = "Background objects" ; +}; +String STR_PSEUDOSHEET_BACKGROUND +{ + Text [ en-US ] = "Background" ; +}; +String STR_PSEUDOSHEET_NOTES +{ + Text [ en-US ] = "Notes" ; +}; +String STR_GRAFOBJECTBARSHELL +{ + Text [ en-US ] = "Graphics mode" ; +}; + +String STR_MEDIAOBJECTBARSHELL +{ + Text [ en-US ] = "Media Playback" ; +}; + +String STR_TABLEOBJECTBARSHELL +{ + Text [ de ] = "Tabelle" ; + Text [ en-US ] = "Table" ; + Text [ x-comment ] = " "; +}; + +String STR_POWERPOINT_IMPORT +{ + Text [ en-US ] = "PowerPoint Import"; +}; + +String STR_POOLSHEET_ARROW +{ + Text [ en-US ] = "Arrow" ; +}; + + +String STR_LOAD_DOC +{ + Text [ en-US ] = "Load Document" ; +}; +String STR_SAVE_DOC +{ + Text [ en-US ] = "Save Document" ; +}; + +#define ERR_CODE( class, err ) (class | (err - ERROR_SD_BASE)) +#define WARN_CODE( class, err ) (class | ( err - WARN_SD_BASE)) + +Resource RID_SD_ERRHDL +{ + String ERR_CODE ( ERRCODE_CLASS_READ , ERR_FORMAT_ROWCOL ) + { + Text [ en-US ] = "File format error found at $(ARG1)(row,col)." ; + }; + String ERR_CODE ( ERRCODE_CLASS_READ , ERR_FORMAT_FILE_ROWCOL ) + { + Text [ en-US ] = "Format error discovered in the file in sub-document $(ARG1) at position $(ARG2)(row,col)."; + }; + String ERR_CODE ( ERRCODE_CLASS_READ , WARN_FORMAT_FILE_ROWCOL ) + { + Text [ en-US ] = "Format error discovered in the file in sub-document $(ARG1) at position $(ARG2)(row,col)."; + }; +}; + +String STR_3DOBJECTBARSHELL +{ + Text [ en-US ] = "3-D Settings" ; +}; +String STR_FONTWORKOBJECTBARSHELL +{ + Text [ en-US ] = "Fontwork" ; +}; + +String STR_POOLSHEET_BANDED_CELL +{ + Text [ en-US ] = "Banding cell" ; +}; + +String STR_POOLSHEET_HEADER +{ + Text [ en-US ] = "Header" ; +}; + +String STR_POOLSHEET_TOTAL +{ + Text [ en-US ] = "Total line" ; +}; + +String STR_POOLSHEET_FIRST_COLUMN +{ + Text [ en-US ] = "First column" ; +}; + +String STR_POOLSHEET_LAST_COLUMN +{ + Text [ en-US ] = "Last column" ; +}; diff --git a/sd/source/core/makefile.mk b/sd/source/core/makefile.mk new file mode 100644 index 000000000000..4100edf49434 --- /dev/null +++ b/sd/source/core/makefile.mk @@ -0,0 +1,78 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PROJECTPCH=sd +PROJECTPCHSOURCE=$(PRJ)$/util$/sd +PRJNAME=sd +TARGET=core +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +IENV+=-I..\ui\inc + +# --- Files -------------------------------------------------------- + +SRS1NAME=$(TARGET) +SRC1FILES = glob.src + +SLOFILES = $(SLO)$/stlsheet.obj \ + $(SLO)$/stlfamily.obj \ + $(SLO)$/stlpool.obj \ + $(SLO)$/drawdoc.obj \ + $(SLO)$/drawdoc2.obj \ + $(SLO)$/drawdoc3.obj \ + $(SLO)$/drawdoc4.obj \ + $(SLO)$/drawdoc_animations.obj\ + $(SLO)$/sdpage.obj \ + $(SLO)$/sdpage2.obj \ + $(SLO)$/sdattr.obj \ + $(SLO)$/sdobjfac.obj \ + $(SLO)$/anminfo.obj \ + $(SLO)$/sdiocmpt.obj \ + $(SLO)$/typemap.obj \ + $(SLO)$/pglink.obj \ + $(SLO)$/cusshow.obj \ + $(SLO)$/PageListWatcher.obj \ + $(SLO)$/sdpage_animations.obj\ + $(SLO)$/CustomAnimationPreset.obj\ + $(SLO)$/CustomAnimationEffect.obj\ + $(SLO)$/TransitionPreset.obj\ + $(SLO)$/undoanim.obj\ + $(SLO)$/EffectMigration.obj\ + $(SLO)$/CustomAnimationCloner.obj\ + $(SLO)$/shapelist.obj + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sd/source/core/pglink.cxx b/sd/source/core/pglink.cxx new file mode 100644 index 000000000000..6c19008f6c16 --- /dev/null +++ b/sd/source/core/pglink.cxx @@ -0,0 +1,147 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include <sfx2/linkmgr.hxx> + +#include "pglink.hxx" +#include "sdpage.hxx" +#include "drawdoc.hxx" + + +/************************************************************************* +|* +|* Ctor +|* +\************************************************************************/ + +SdPageLink::SdPageLink(SdPage* pPg, const String& rFileName, + const String& rBookmarkName) : + ::sfx2::SvBaseLink( ::sfx2::LINKUPDATE_ONCALL, FORMAT_FILE), + pPage(pPg) +{ + pPage->SetFileName(rFileName); + pPage->SetBookmarkName(rBookmarkName); +} + + +/************************************************************************* +|* +|* Dtor +|* +\************************************************************************/ + + +SdPageLink::~SdPageLink() +{ +} + +/************************************************************************* +|* +|* Daten haben sich geaendert +|* +\************************************************************************/ + +void SdPageLink::DataChanged( const String& , + const ::com::sun::star::uno::Any& ) +{ + SdDrawDocument* pDoc = (SdDrawDocument*) pPage->GetModel(); + sfx2::LinkManager* pLinkManager = pDoc!=NULL ? pDoc->GetLinkManager() : NULL; + + if (pLinkManager) + { + /********************************************************************** + * Nur Standardseiten duerfen gelinkt sein + * Die entsprechenden Notizseiten werden automatisch aktualisiert + **********************************************************************/ + String aFileName; + String aBookmarkName; + String aFilterName; + pLinkManager->GetDisplayNames( this,0, &aFileName, &aBookmarkName, + &aFilterName); + pPage->SetFileName(aFileName); + pPage->SetBookmarkName(aBookmarkName); + + SdDrawDocument* pBookmarkDoc = pDoc->OpenBookmarkDoc(aFileName); + + if (pBookmarkDoc) + { + /****************************************************************** + * Die gelinkte Seite wird im Model replaced + ******************************************************************/ + if (aBookmarkName.Len() == 0) + { + // Kein Seitenname angegeben: es wird die erste Seite genommen + aBookmarkName = pBookmarkDoc->GetSdPage(0, PK_STANDARD)->GetName(); + pPage->SetBookmarkName(aBookmarkName); + } + + List aBookmarkList; + aBookmarkList.Insert(&aBookmarkName); + USHORT nInsertPos = pPage->GetPageNum(); + BOOL bLink = TRUE; + BOOL bReplace = TRUE; + BOOL bNoDialogs = FALSE; + BOOL bCopy = FALSE; + + if( pDoc->pDocLockedInsertingLinks ) + { + // resolving links while loading pDoc + bNoDialogs = TRUE; + bCopy = TRUE; + } + + pDoc->InsertBookmarkAsPage(&aBookmarkList, NULL, bLink, bReplace, + nInsertPos, bNoDialogs, NULL, bCopy, TRUE, TRUE); + + if( !pDoc->pDocLockedInsertingLinks ) + pDoc->CloseBookmarkDoc(); + } + } +} + +/************************************************************************* +|* +|* Link an oder abmelden +|* +\************************************************************************/ + +void SdPageLink::Closed() +{ + // Die Verbindung wird aufgehoben + pPage->SetFileName(String()); + pPage->SetBookmarkName(String()); + + SvBaseLink::Closed(); +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/sdattr.cxx b/sd/source/core/sdattr.cxx new file mode 100644 index 000000000000..f1e5fd073ea8 --- /dev/null +++ b/sd/source/core/sdattr.cxx @@ -0,0 +1,156 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + + +#include "sdattr.hxx" + +using namespace ::com::sun::star; + +/************************************************************************* +|* +|* DiaEffectItem +|* +*************************************************************************/ +TYPEINIT1_AUTOFACTORY( DiaEffectItem, SfxEnumItem ); + + +DiaEffectItem::DiaEffectItem( presentation::FadeEffect eFE ) : + SfxEnumItem( ATTR_DIA_EFFECT, (USHORT)eFE ) +{ +} + + +DiaEffectItem::DiaEffectItem( SvStream& rIn ) : + SfxEnumItem( ATTR_DIA_EFFECT, rIn ) +{ +} + + +SfxPoolItem* DiaEffectItem::Clone( SfxItemPool* ) const +{ + return new DiaEffectItem( *this ); +} + + +SfxPoolItem* DiaEffectItem::Create( SvStream& rIn, USHORT ) const +{ + return new DiaEffectItem( rIn ); +} + +/************************************************************************* +|* +|* DiaSpeedItem +|* +*************************************************************************/ +TYPEINIT1_AUTOFACTORY( DiaSpeedItem, SfxEnumItem ); + + +DiaSpeedItem::DiaSpeedItem( FadeSpeed eFS ) : + SfxEnumItem( ATTR_DIA_SPEED, (USHORT)eFS ) +{ +} + + +DiaSpeedItem::DiaSpeedItem( SvStream& rIn ) : + SfxEnumItem( ATTR_DIA_SPEED, rIn ) +{ +} + + +SfxPoolItem* DiaSpeedItem::Clone( SfxItemPool* ) const +{ + return new DiaSpeedItem( *this ); +} + + +SfxPoolItem* DiaSpeedItem::Create( SvStream& rIn, USHORT ) const +{ + return new DiaSpeedItem( rIn ); +} + +/************************************************************************* +|* +|* DiaAutoItem +|* +*************************************************************************/ +TYPEINIT1_AUTOFACTORY( DiaAutoItem, SfxEnumItem ); + +DiaAutoItem::DiaAutoItem( PresChange eChange ) : + SfxEnumItem( ATTR_DIA_AUTO, (USHORT)eChange ) +{ +} + + +DiaAutoItem::DiaAutoItem( SvStream& rIn ) : + SfxEnumItem( ATTR_DIA_AUTO, rIn ) +{ +} + + +SfxPoolItem* DiaAutoItem::Clone( SfxItemPool* ) const +{ + return new DiaAutoItem( *this ); +} + + +SfxPoolItem* DiaAutoItem::Create( SvStream& rIn, USHORT ) const +{ + return new DiaAutoItem( rIn ); +} + +/************************************************************************* +|* +|* DiaTimeItem +|* +*************************************************************************/ +TYPEINIT1_AUTOFACTORY( DiaTimeItem, SfxUInt32Item ); + + +DiaTimeItem::DiaTimeItem( UINT32 nValue ) : + SfxUInt32Item( ATTR_DIA_TIME, nValue ) +{ +} + + +SfxPoolItem* DiaTimeItem::Clone( SfxItemPool* ) const +{ + return new DiaTimeItem( *this ); +} + + +int DiaTimeItem::operator==( const SfxPoolItem& rItem ) const +{ + return( ( (DiaTimeItem&) rItem ).GetValue() == GetValue() ); +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/sdiocmpt.cxx b/sd/source/core/sdiocmpt.cxx new file mode 100644 index 000000000000..f67f550b984c --- /dev/null +++ b/sd/source/core/sdiocmpt.cxx @@ -0,0 +1,139 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + + +#include <tools/debug.hxx> + +#include "sdiocmpt.hxx" + +////////////////////////////////////////////////////////////////////////////// + +old_SdrDownCompat::old_SdrDownCompat(SvStream& rNewStream, UINT16 nNewMode) +: rStream(rNewStream), + nSubRecSiz(0), + nSubRecPos(0), + nMode(nNewMode), + bOpen(FALSE) +{ + OpenSubRecord(); +} + +old_SdrDownCompat::~old_SdrDownCompat() +{ + if(bOpen) + CloseSubRecord(); +} + +void old_SdrDownCompat::Read() +{ + rStream >> nSubRecSiz; +} + +void old_SdrDownCompat::Write() +{ + rStream << nSubRecSiz; +} + +void old_SdrDownCompat::OpenSubRecord() +{ + if(rStream.GetError()) + return; + + nSubRecPos = rStream.Tell(); + + if(nMode == STREAM_READ) + { + Read(); + } + else if(nMode == STREAM_WRITE) + { + Write(); + } + + bOpen = TRUE; +} + +void old_SdrDownCompat::CloseSubRecord() +{ + if(rStream.GetError()) + return; + + UINT32 nAktPos(rStream.Tell()); + + if(nMode == STREAM_READ) + { + UINT32 nReadAnz(nAktPos - nSubRecPos); + if(nReadAnz != nSubRecSiz) + { + rStream.Seek(nSubRecPos + nSubRecSiz); + } + } + else if(nMode == STREAM_WRITE) + { + nSubRecSiz = nAktPos - nSubRecPos; + rStream.Seek(nSubRecPos); + Write(); + rStream.Seek(nAktPos); + } + + bOpen = FALSE; +} + +/************************************************************************* +|* +|* Konstruktor, schreibt bzw. liest Versionsnummer +|* +\************************************************************************/ + +SdIOCompat::SdIOCompat(SvStream& rNewStream, USHORT nNewMode, UINT16 nVer) +: old_SdrDownCompat(rNewStream, nNewMode), nVersion(nVer) +{ + if (nNewMode == STREAM_WRITE) + { + DBG_ASSERT(nVer != SDIOCOMPAT_VERSIONDONTKNOW, + "kann unbekannte Version nicht schreiben"); + rNewStream << nVersion; + } + else if (nNewMode == STREAM_READ) + { + DBG_ASSERT(nVer == SDIOCOMPAT_VERSIONDONTKNOW, + "Lesen mit Angabe der Version ist Quatsch!"); + rNewStream >> nVersion; + } +} + +SdIOCompat::~SdIOCompat() +{ +} + +// eof + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/sdobjfac.cxx b/sd/source/core/sdobjfac.cxx new file mode 100644 index 000000000000..637fb501822d --- /dev/null +++ b/sd/source/core/sdobjfac.cxx @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + + +#include <basic/sbx.hxx> + +#include <app.hxx> +#include "sdpage.hxx" +#include "sdobjfac.hxx" +#include "glob.hxx" +#include "anminfo.hxx" +#include "imapinfo.hxx" +#include "drawdoc.hxx" + + +SdObjectFactory aSdObjectFactory; + +/************************************************************************* +|* +|* void SdObjectFactory::MakeUserData() +|* +\************************************************************************/ + +IMPL_LINK( SdObjectFactory, MakeUserData, SdrObjFactory *, pObjFactory ) +{ + if ( pObjFactory->nInventor == SdUDInventor ) + { + switch( pObjFactory->nIdentifier ) + { + case( SD_ANIMATIONINFO_ID ): + pObjFactory->pNewData = new SdAnimationInfo( *pObjFactory->pObj ); + break; + + case( SD_IMAPINFO_ID ): + pObjFactory->pNewData = new SdIMapInfo; + break; + + default: + break; + } + } + + if ( pObjFactory->pNewData ) + return 0; + + if( aOldMakeUserDataLink.IsSet() ) + aOldMakeUserDataLink.Call( this ); + + return 0; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/sdpage.cxx b/sd/source/core/sdpage.cxx new file mode 100644 index 000000000000..c614712a4737 --- /dev/null +++ b/sd/source/core/sdpage.cxx @@ -0,0 +1,3076 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include <algorithm> + +#include <comphelper/classids.hxx> + +#include <vcl/svapp.hxx> +#include "eetext.hxx" +#include <editeng/eeitem.hxx> +#include <svx/svdoutl.hxx> +#include <editeng/editdata.hxx> +#include <svx/pageitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/bulitem.hxx> +#include <svx/svdpagv.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/outlobj.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdopage.hxx> +#include <svx/svdopage.hxx> +#include <sfx2/printer.hxx> +#include <basic/basmgr.hxx> +#include <editeng/pbinitem.hxx> +#include <svx/svdundo.hxx> +#include <svl/smplhint.hxx> +#include <editeng/adjitem.hxx> +#include <editeng/editobj.hxx> +#include <editeng/scripttypeitem.hxx> +#include <svx/unopage.hxx> +#include <editeng/flditem.hxx> +#include <svx/sdr/contact/displayinfo.hxx> +#include <svx/svditer.hxx> + +#include <editeng/adjitem.hxx> + +#include "../ui/inc/DrawDocShell.hxx" +#include "Outliner.hxx" + +#include "misc.hxx" +#include "eetext.hxx" +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include "pglink.hxx" +#include "sdresid.hxx" +#include "stlsheet.hxx" +#include "glob.hrc" +#include "glob.hxx" +#include "helpids.h" +#include "anminfo.hxx" +#include "undo/undomanager.hxx" +#include "undo/undoobjects.hxx" +#include <svx/sdr/contact/displayinfo.hxx> +#include <svx/sdr/contact/viewobjectcontact.hxx> +#include <svx/sdr/contact/viewcontact.hxx> +#include <svx/sdr/contact/objectcontact.hxx> +#include <svx/unoapi.hxx> + +#include <set> + +using namespace ::sd; +using namespace ::com::sun::star; + +TYPEINIT2( SdPage, FmFormPage, SdrObjUserCall ); + +/************************************************************************* +|* +|* Ctor +|* +\************************************************************************/ + +SdPage::SdPage(SdDrawDocument& rNewDoc, StarBASIC* pBasic, BOOL bMasterPage) +: FmFormPage(rNewDoc, pBasic, bMasterPage) +, SdrObjUserCall() +, mePageKind(PK_STANDARD) +, meAutoLayout(AUTOLAYOUT_NONE) +, mbSelected(FALSE) +, mePresChange(PRESCHANGE_MANUAL) +, mnTime(1) +, mbSoundOn(FALSE) +, mbExcluded(FALSE) +, mbLoopSound(FALSE) +, mbStopSound(FALSE) +, mbScaleObjects(TRUE) +, mbBackgroundFullSize( FALSE ) +, meCharSet(gsl_getSystemTextEncoding()) +, mnPaperBin(PAPERBIN_PRINTER_SETTINGS) +, mpPageLink(NULL) +, mpItems(NULL) +, mnTransitionType(0) +, mnTransitionSubtype(0) +, mbTransitionDirection(sal_True) +, mnTransitionFadeColor(0) +, mfTransitionDuration(2.0) +, mbIsPrecious(true) +{ + // Der Layoutname der Seite wird von SVDRAW benutzt, um die Praesentations- + // vorlagen der Gliederungsobjekte zu ermitteln. Darum enthaelt er bereits + // den Bezeichner fuer die Gliederung (STR_LAYOUT_OUTLINE). + maLayoutName = String(SdResId(STR_LAYOUT_DEFAULT_NAME)); + maLayoutName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( SD_LT_SEPARATOR )); + maLayoutName += String(SdResId(STR_LAYOUT_OUTLINE)); + + Size aPageSize(GetSize()); + + if (aPageSize.Width() > aPageSize.Height()) + { + meOrientation = ORIENTATION_LANDSCAPE; + } + else + { + meOrientation = ORIENTATION_PORTRAIT; + } +} + +/************************************************************************* +|* +|* Dtor +|* +\************************************************************************/ + +SdPage::~SdPage() +{ + DisconnectLink(); + + EndListenOutlineText(); + + if( mpItems ) + delete mpItems; +} + +struct OrdNumSorter +{ + bool operator()( SdrObject* p1, SdrObject* p2 ) + { + return p1->GetOrdNum() < p2->GetOrdNum(); + } +}; + +/** returns the nIndex'th object from the given PresObjKind, index starts with 1 */ +SdrObject* SdPage::GetPresObj(PresObjKind eObjKind, int nIndex, bool bFuzzySearch /* = false */ ) +{ + // first sort all matching shapes with z-order + std::vector< SdrObject* > aMatches; + + SdrObject* pObj = 0; + while( (pObj = maPresentationShapeList.getNextShape(pObj)) != 0 ) + { + SdAnimationInfo* pInfo = SdDrawDocument::GetShapeUserData(*pObj); + if( pInfo ) + { + bool bFound = false; + if( pInfo->mePresObjKind == eObjKind ) + { + bFound = true; + } + else if( bFuzzySearch && (eObjKind == PRESOBJ_OUTLINE) ) + { + switch( pInfo->mePresObjKind ) + { + case PRESOBJ_GRAPHIC: + case PRESOBJ_OBJECT: + case PRESOBJ_CHART: + case PRESOBJ_ORGCHART: + case PRESOBJ_TABLE: + case PRESOBJ_CALC: + case PRESOBJ_IMAGE: + case PRESOBJ_MEDIA: + bFound = TRUE; + break; + default: + break; + } + } + if( bFound ) + { + aMatches.push_back( pObj ); + } + } + } + + if( aMatches.size() > 1 ) + { + OrdNumSorter aSortHelper; + std::sort( aMatches.begin(), aMatches.end(), aSortHelper ); + } + + if( nIndex > 0 ) + nIndex--; + + if( (nIndex >= 0) && ( aMatches.size() > static_cast<unsigned int>(nIndex)) ) + return aMatches[nIndex]; + + return 0; +} + +/** create background properties */ +void SdPage::EnsureMasterPageDefaultBackground() +{ + if(mbMaster) + { + // no hard attributes on MasterPage attributes + getSdrPageProperties().ClearItem(); + SfxStyleSheet* pSheetForPresObj = GetStyleSheetForMasterPageBackground(); + + if(pSheetForPresObj) + { + // set StyleSheet for background fill attributes + getSdrPageProperties().SetStyleSheet(pSheetForPresObj); + } + else + { + // no style found, assert and set at least XFILL_NONE + OSL_ENSURE(false, "No Style for MasterPageBackground fill found (!)"); + getSdrPageProperties().PutItem(XFillStyleItem(XFILL_NONE)); + } + } +} + +/** creates a presentation object with the given PresObjKind on this page. A user call will be set +*/ +SdrObject* SdPage::CreatePresObj(PresObjKind eObjKind, BOOL bVertical, const Rectangle& rRect, BOOL /* bInsert */ ) +{ + sd::UndoManager* pUndoManager = pModel ? static_cast<SdDrawDocument*>(pModel)->GetUndoManager() : 0; + const bool bUndo = pUndoManager && pUndoManager->isInListAction() && IsInserted(); + + SdrObject* pSdrObj = NULL; + + bool bForceText = false; // forces the shape text to be set even if its empty + bool bEmptyPresObj = true; + + switch( eObjKind ) + { + case PRESOBJ_TITLE: + { + pSdrObj = new SdrRectObj(OBJ_TITLETEXT); + + if (mbMaster) + { + pSdrObj->SetNotVisibleAsMaster(TRUE); + } + } + break; + + case PRESOBJ_OUTLINE: + { + pSdrObj = new SdrRectObj(OBJ_OUTLINETEXT); + + if (mbMaster) + { + pSdrObj->SetNotVisibleAsMaster(TRUE); + } + } + break; + + case PRESOBJ_NOTES: + { + pSdrObj = new SdrRectObj(OBJ_TEXT); + + if (mbMaster) + { + pSdrObj->SetNotVisibleAsMaster(TRUE); + } + } + break; + + case PRESOBJ_TEXT: + { + pSdrObj = new SdrRectObj(OBJ_TEXT); + } + break; + + case PRESOBJ_GRAPHIC: + { + BitmapEx aBmpEx( SdResId( BMP_PRESOBJ_GRAPHIC ) ); + Graphic aGraphic( aBmpEx ); + OutputDevice &aOutDev = *Application::GetDefaultDevice(); + aOutDev.Push(); + + aOutDev.SetMapMode( aGraphic.GetPrefMapMode() ); + Size aSizePix = aOutDev.LogicToPixel( aGraphic.GetPrefSize() ); + aOutDev.SetMapMode(MAP_100TH_MM); + + Size aSize = aOutDev.PixelToLogic(aSizePix); + Point aPnt (0, 0); + Rectangle aRect (aPnt, aSize); + pSdrObj = new SdrGrafObj(aGraphic, aRect); + aOutDev.Pop(); + } + break; + + case PRESOBJ_MEDIA: + case PRESOBJ_OBJECT: + { + pSdrObj = new SdrOle2Obj(); + BitmapEx aBmpEx( SdResId( BMP_PRESOBJ_OBJECT ) ); + Graphic aGraphic( aBmpEx ); + ( (SdrOle2Obj*) pSdrObj)->SetGraphic(&aGraphic); + } + break; + + case PRESOBJ_CHART: + { + pSdrObj = new SdrOle2Obj(); + ( (SdrOle2Obj*) pSdrObj)->SetProgName( String( RTL_CONSTASCII_USTRINGPARAM( "StarChart" ))); + BitmapEx aBmpEx( SdResId( BMP_PRESOBJ_CHART ) ); + Graphic aGraphic( aBmpEx ); + ( (SdrOle2Obj*) pSdrObj)->SetGraphic(&aGraphic); + } + break; + + case PRESOBJ_ORGCHART: + { + pSdrObj = new SdrOle2Obj(); + ( (SdrOle2Obj*) pSdrObj)->SetProgName( String( RTL_CONSTASCII_USTRINGPARAM( "StarOrg" ))); + BitmapEx aBmpEx( SdResId( BMP_PRESOBJ_ORGCHART ) ); + Graphic aGraphic( aBmpEx ); + ( (SdrOle2Obj*) pSdrObj)->SetGraphic(&aGraphic); + } + + case PRESOBJ_TABLE: + case PRESOBJ_CALC: + { + pSdrObj = new SdrOle2Obj(); + ( (SdrOle2Obj*) pSdrObj)->SetProgName( String( RTL_CONSTASCII_USTRINGPARAM( "StarCalc" ))); + BitmapEx aBmpEx( SdResId( BMP_PRESOBJ_TABLE ) ); + Graphic aGraphic( aBmpEx ); + ( (SdrOle2Obj*) pSdrObj)->SetGraphic(&aGraphic); + } + break; + + case PRESOBJ_HANDOUT: + { + //Erste Standardseite am SdrPageObj vermerken + // #i105146# We want no content to be displayed for PK_HANDOUT, + // so just never set a page as content + pSdrObj = new SdrPageObj(0); + } + break; + + case PRESOBJ_PAGE: + { + //Notizseite am SdrPageObj vermerken + sal_uInt16 nDestPageNum(GetPageNum()); + + if(nDestPageNum) + { + // decrement only when != 0, else we get a 0xffff + nDestPageNum -= 1; + } + + if(nDestPageNum < pModel->GetPageCount()) + { + pSdrObj = new SdrPageObj(pModel->GetPage(nDestPageNum)); + } + else + { + pSdrObj = new SdrPageObj(); + } + + pSdrObj->SetResizeProtect(TRUE); + } + break; + + case PRESOBJ_HEADER: + case PRESOBJ_FOOTER: + case PRESOBJ_DATETIME: + case PRESOBJ_SLIDENUMBER: + { + pSdrObj = new SdrRectObj(OBJ_TEXT); + bEmptyPresObj = false; + bForceText = true; + } + break; + default: + break; + } + + if (pSdrObj) + { + pSdrObj->SetEmptyPresObj(bEmptyPresObj); + pSdrObj->SetLogicRect(rRect); + + InsertObject(pSdrObj); + + if ( pSdrObj->ISA(SdrTextObj) ) + { + // #96243# Tell the object EARLY that it is vertical to have the + // defaults for AutoGrowWidth/Height reversed + if(bVertical) + ((SdrTextObj*)pSdrObj)->SetVerticalWriting(TRUE); + + SfxItemSet aTempAttr( ((SdDrawDocument*) pModel)->GetPool() ); + if( bVertical ) + aTempAttr.Put( SdrTextMinFrameWidthItem( rRect.GetSize().Width() ) ); + else + aTempAttr.Put( SdrTextMinFrameHeightItem( rRect.GetSize().Height() ) ); + + if (mbMaster) + { + // Bei Praesentationsobjekten auf der MasterPage soll die + // Groesse vom Benutzwer frei waehlbar sein + + // #96243# potential problem: This action was still NOT + // adapted for vertical text. This sure needs to be done. + if(bVertical) + aTempAttr.Put(SdrTextAutoGrowWidthItem(FALSE)); + else + aTempAttr.Put(SdrTextAutoGrowHeightItem(FALSE)); + } + + // check if we need another vertical adjustement than the default + SdrTextVertAdjust eV = SDRTEXTVERTADJUST_TOP; + + if( (eObjKind == PRESOBJ_FOOTER) && (mePageKind != PK_STANDARD) ) + { + eV = SDRTEXTVERTADJUST_BOTTOM; + } + else if( (eObjKind == PRESOBJ_SLIDENUMBER) && (mePageKind != PK_STANDARD) ) + { + eV = SDRTEXTVERTADJUST_BOTTOM; + } + + if( eV != SDRTEXTVERTADJUST_TOP ) + aTempAttr.Put(SdrTextVertAdjustItem(eV)); + + pSdrObj->SetMergedItemSet(aTempAttr); + + pSdrObj->SetLogicRect(rRect); + } + + String aString = GetPresObjText(eObjKind); + if( (aString.Len() || bForceText) && pSdrObj->ISA(SdrTextObj) ) + { + SdrOutliner* pOutliner = ( (SdDrawDocument*) GetModel() )->GetInternalOutliner(); + + USHORT nOutlMode = pOutliner->GetMode(); + pOutliner->Init( OUTLINERMODE_TEXTOBJECT ); + pOutliner->SetStyleSheet( 0, NULL ); + pOutliner->SetVertical( bVertical ); + + String aEmptyStr; + SetObjText( (SdrTextObj*) pSdrObj, (SdrOutliner*)pOutliner, eObjKind, aString ); + + pOutliner->Init( nOutlMode ); + pOutliner->SetStyleSheet( 0, NULL ); + } + + if( (eObjKind == PRESOBJ_HEADER) || (eObjKind == PRESOBJ_FOOTER) || (eObjKind == PRESOBJ_SLIDENUMBER) || (eObjKind == PRESOBJ_DATETIME) ) + { + SfxItemSet aTempAttr( ((SdDrawDocument*) pModel)->GetPool() ); + aTempAttr.Put( SvxFontHeightItem( 493, 100, EE_CHAR_FONTHEIGHT ) ); + aTempAttr.Put( SvxFontHeightItem( 493, 100, EE_CHAR_FONTHEIGHT_CTL ) ); + aTempAttr.Put( SvxFontHeightItem( 493, 100, EE_CHAR_FONTHEIGHT_CJK ) ); + + SvxAdjust eH = SVX_ADJUST_LEFT; + + if( (eObjKind == PRESOBJ_DATETIME) && (mePageKind != PK_STANDARD ) ) + { + eH = SVX_ADJUST_RIGHT; + } + else if( (eObjKind == PRESOBJ_FOOTER) && (mePageKind == PK_STANDARD ) ) + { + eH = SVX_ADJUST_CENTER; + } + else if( eObjKind == PRESOBJ_SLIDENUMBER ) + { + eH = SVX_ADJUST_RIGHT; + } + + if( eH != SVX_ADJUST_LEFT ) + aTempAttr.Put(SvxAdjustItem(eH, EE_PARA_JUST )); + + pSdrObj->SetMergedItemSet(aTempAttr); + } + + if (mbMaster) + { + SdrLayerAdmin& rLayerAdmin = pModel->GetLayerAdmin(); + + // Hintergrundobjekte der MasterPage + pSdrObj->SetLayer( rLayerAdmin. + GetLayerID(String(SdResId(STR_LAYER_BCKGRNDOBJ)), FALSE) ); + } + + // Objekt am StyleSheet anmelden + // #95114# Set style only when one was found (as in 5.2) + if( mePageKind != PK_HANDOUT ) + { + SfxStyleSheet* pSheetForPresObj = GetStyleSheetForPresObj(eObjKind); + if(pSheetForPresObj) + pSdrObj->SetStyleSheet(pSheetForPresObj, FALSE); + } + + if (eObjKind == PRESOBJ_OUTLINE) + { + for (USHORT nLevel = 1; nLevel < 10; nLevel++) + { + String aName(maLayoutName); + aName += sal_Unicode( ' ' ); + aName += String::CreateFromInt32( nLevel ); + SfxStyleSheet* pSheet = (SfxStyleSheet*)pModel->GetStyleSheetPool()->Find(aName, SD_STYLE_FAMILY_MASTERPAGE); + DBG_ASSERT(pSheet, "Vorlage fuer Gliederungsobjekt nicht gefunden"); + if (pSheet) + pSdrObj->StartListening(*pSheet); + } + } + + if ( eObjKind == PRESOBJ_OBJECT || + eObjKind == PRESOBJ_CHART || + eObjKind == PRESOBJ_ORGCHART || + eObjKind == PRESOBJ_CALC || + eObjKind == PRESOBJ_GRAPHIC ) + { + SfxItemSet aSet( ((SdDrawDocument*) pModel)->GetPool() ); + aSet.Put( SdrTextContourFrameItem( TRUE ) ); + aSet.Put( SvxAdjustItem( SVX_ADJUST_CENTER, EE_PARA_JUST ) ); + + pSdrObj->SetMergedItemSet(aSet); + } + + if( bUndo ) + { + pUndoManager->AddUndoAction(pModel->GetSdrUndoFactory().CreateUndoNewObject(*pSdrObj)); + } + + if( bUndo ) + { + pUndoManager->AddUndoAction( new UndoObjectPresentationKind( *pSdrObj ) ); + pUndoManager->AddUndoAction( new UndoObjectUserCall(*pSdrObj) ); + } + + InsertPresObj(pSdrObj, eObjKind); + pSdrObj->SetUserCall(this); + + pSdrObj->RecalcBoundRect(); + } + + return(pSdrObj); +} + +/************************************************************************* +|* +|* Es werden Praesentationsobjekte auf der Page erzeugt. +|* Alle Praesentationsobjekte erhalten einen UserCall auf die Page. +|* +\************************************************************************/ + +SfxStyleSheet* SdPage::GetStyleSheetForMasterPageBackground() const +{ + String aName(GetLayoutName()); + String aSep( RTL_CONSTASCII_USTRINGPARAM( SD_LT_SEPARATOR )); + USHORT nPos = aName.Search(aSep); + + if (nPos != STRING_NOTFOUND) + { + nPos = nPos + aSep.Len(); + aName.Erase(nPos); + } + + aName += String(SdResId(STR_LAYOUT_BACKGROUND)); + + SfxStyleSheetBasePool* pStShPool = pModel->GetStyleSheetPool(); + SfxStyleSheetBase* pResult = pStShPool->Find(aName, SD_STYLE_FAMILY_MASTERPAGE); + return (SfxStyleSheet*)pResult; +} + +SfxStyleSheet* SdPage::GetStyleSheetForPresObj(PresObjKind eObjKind) const +{ + String aName(GetLayoutName()); + String aSep( RTL_CONSTASCII_USTRINGPARAM( SD_LT_SEPARATOR )); + USHORT nPos = aName.Search(aSep); + if (nPos != STRING_NOTFOUND) + { + nPos = nPos + aSep.Len(); + aName.Erase(nPos); + } + + switch (eObjKind) + { + case PRESOBJ_OUTLINE: + { + aName = GetLayoutName(); + aName += sal_Unicode( ' ' ); + aName += String::CreateFromInt32( 1 ); + } + break; + + case PRESOBJ_TITLE: + aName += String(SdResId(STR_LAYOUT_TITLE)); + break; + + case PRESOBJ_NOTES: + aName += String(SdResId(STR_LAYOUT_NOTES)); + break; + + case PRESOBJ_TEXT: + aName += String(SdResId(STR_LAYOUT_SUBTITLE)); + break; + + case PRESOBJ_HEADER: + case PRESOBJ_FOOTER: + case PRESOBJ_DATETIME: + case PRESOBJ_SLIDENUMBER: + aName += String(SdResId(STR_LAYOUT_BACKGROUNDOBJECTS)); + break; + + default: + break; + } + + SfxStyleSheetBasePool* pStShPool = pModel->GetStyleSheetPool(); + SfxStyleSheetBase* pResult = pStShPool->Find(aName, SD_STYLE_FAMILY_MASTERPAGE); + return (SfxStyleSheet*)pResult; +} + +/** returns the presentation style with the given helpid from this masterpage or this + slides masterpage */ +SdStyleSheet* SdPage::getPresentationStyle( sal_uInt32 nHelpId ) const +{ + String aStyleName( pPage->GetLayoutName() ); + const String aSep( RTL_CONSTASCII_USTRINGPARAM( SD_LT_SEPARATOR )); + aStyleName.Erase(aStyleName.Search(aSep) + aSep.Len()); + + sal_uInt16 nNameId; + switch( nHelpId ) + { + case HID_PSEUDOSHEET_TITLE: nNameId = STR_LAYOUT_TITLE; break; + case HID_PSEUDOSHEET_SUBTITLE: nNameId = STR_LAYOUT_SUBTITLE; break; + case HID_PSEUDOSHEET_OUTLINE1: + case HID_PSEUDOSHEET_OUTLINE2: + case HID_PSEUDOSHEET_OUTLINE3: + case HID_PSEUDOSHEET_OUTLINE4: + case HID_PSEUDOSHEET_OUTLINE5: + case HID_PSEUDOSHEET_OUTLINE6: + case HID_PSEUDOSHEET_OUTLINE7: + case HID_PSEUDOSHEET_OUTLINE8: + case HID_PSEUDOSHEET_OUTLINE9: nNameId = STR_LAYOUT_OUTLINE; break; + case HID_PSEUDOSHEET_BACKGROUNDOBJECTS: nNameId = STR_LAYOUT_BACKGROUNDOBJECTS; break; + case HID_PSEUDOSHEET_BACKGROUND: nNameId = STR_LAYOUT_BACKGROUND; break; + case HID_PSEUDOSHEET_NOTES: nNameId = STR_LAYOUT_NOTES; break; + + default: + DBG_ERROR( "SdPage::getPresentationStyle(), illegal argument!" ); + return 0; + } + aStyleName.Append( String( SdResId( nNameId ) ) ); + if( nNameId == STR_LAYOUT_OUTLINE ) + { + aStyleName.Append( sal_Unicode( ' ' )); + aStyleName.Append( String::CreateFromInt32( sal_Int32( nHelpId - HID_PSEUDOSHEET_OUTLINE ))); + } + + SfxStyleSheetBasePool* pStShPool = pModel->GetStyleSheetPool(); + SfxStyleSheetBase* pResult = pStShPool->Find(aStyleName, SD_STYLE_FAMILY_MASTERPAGE); + return dynamic_cast<SdStyleSheet*>(pResult); +} + +/************************************************************************* +|* +|* Das Praesentationsobjekt rObj hat sich geaendert und wird nicht mehr +|* durch das Praesentationsobjekt der MasterPage referenziert. +|* Der UserCall wird geloescht. +|* +\************************************************************************/ + +void SdPage::Changed(const SdrObject& rObj, SdrUserCallType eType, const Rectangle& ) +{ + if (!maLockAutoLayoutArrangement.isLocked()) + { + switch (eType) + { + case SDRUSERCALL_MOVEONLY: + case SDRUSERCALL_RESIZE: + { + if( pModel->isLocked() ) + break; + + SdrObject* pObj = (SdrObject*) &rObj; + + if (pObj) + { + if (!mbMaster) + { + if( pObj->GetUserCall() ) + { + sd::UndoManager* pUndoManager = pModel ? static_cast<SdDrawDocument*>(pModel)->GetUndoManager() : 0; + const bool bUndo = pUndoManager && pUndoManager->isInListAction() && IsInserted(); + + if( bUndo ) + pUndoManager->AddUndoAction( new UndoObjectUserCall(*pObj) ); + + // Objekt was resized by user and does not listen to its slide anymore + pObj->SetUserCall(0); + } + } + else if (pModel) + { + // MasterPage-Objekt wurde veraendert, daher + // Objekte auf allen Seiten anpassen + USHORT nPageCount = ((SdDrawDocument*) pModel)->GetSdPageCount(mePageKind); + + for (USHORT i = 0; i < nPageCount; i++) + { + SdPage* pLoopPage = ((SdDrawDocument*) pModel)->GetSdPage(i, mePageKind); + + if (pLoopPage && this == &(pLoopPage->TRG_GetMasterPage())) + { + // Seite hoert auf diese MasterPage, daher + // AutoLayout anpassen + pLoopPage->SetAutoLayout(pLoopPage->GetAutoLayout()); + } + } + } + } + } + break; + + case SDRUSERCALL_DELETE: + case SDRUSERCALL_REMOVED: + default: + break; + } + } +} + +/************************************************************************* +|* +|* Erzeugt auf einer MasterPage Hintergrund, Titel- und Layout-Bereich +|* +\************************************************************************/ + +void SdPage::CreateTitleAndLayout(BOOL bInit, BOOL bCreate ) +{ + sd::UndoManager* pUndoManager = pModel ? static_cast<SdDrawDocument*>(pModel)->GetUndoManager() : 0; + const bool bUndo = pUndoManager && pUndoManager->isInListAction() && IsInserted(); + + SdPage* pMasterPage = this; + + if (!mbMaster) + { + pMasterPage = (SdPage*)(&(TRG_GetMasterPage())); + } + + if (!pMasterPage) + { + return; + } + + /************************************************************************** + * Hintergrund, Titel- und Layout-Bereich werden angelegt + **************************************************************************/ + if( mePageKind == PK_STANDARD ) + { + pMasterPage->EnsureMasterPageDefaultBackground(); + } + + if( ( (SdDrawDocument*) GetModel() )->GetDocumentType() == DOCUMENT_TYPE_IMPRESS ) + { + if( mePageKind == PK_HANDOUT && bInit ) + { + // handout template + + // delete all available handout presentation objects + SdrObject* pObj; + while( (pObj = pMasterPage->GetPresObj(PRESOBJ_HANDOUT)) != 0 ) + { + if( bUndo ) + pUndoManager->AddUndoAction(pModel->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj)); + + pMasterPage->RemoveObject(pObj->GetOrdNum()); + } + + std::vector< Rectangle > aAreas; + CalculateHandoutAreas( *static_cast< SdDrawDocument* >(GetModel() ), pMasterPage->GetAutoLayout(), false, aAreas ); + + const bool bSkip = pMasterPage->GetAutoLayout() == AUTOLAYOUT_HANDOUT3; + std::vector< Rectangle >::iterator iter( aAreas.begin() ); + + while( iter != aAreas.end() ) + { + SdrPageObj* pPageObj = static_cast<SdrPageObj*>(pMasterPage->CreatePresObj(PRESOBJ_HANDOUT, FALSE, (*iter++), TRUE) ); + // #i105146# We want no content to be displayed for PK_HANDOUT, + // so just never set a page as content + pPageObj->SetReferencedPage(0L); + + if( bSkip && iter != aAreas.end() ) + ++iter; + } + } + + if( mePageKind != PK_HANDOUT ) + { + SdrObject* pMasterTitle = pMasterPage->GetPresObj( PRESOBJ_TITLE ); + if( pMasterTitle == NULL ) + pMasterPage->CreateDefaultPresObj(PRESOBJ_TITLE, true); + + SdrObject* pMasterOutline = pMasterPage->GetPresObj( mePageKind==PK_NOTES ? PRESOBJ_NOTES : PRESOBJ_OUTLINE ); + if( pMasterOutline == NULL ) + pMasterPage->CreateDefaultPresObj( mePageKind == PK_STANDARD ? PRESOBJ_OUTLINE : PRESOBJ_NOTES, true ); + } + + // create header&footer objects + + if( bCreate ) + { + if( mePageKind != PK_STANDARD ) + { + SdrObject* pHeader = pMasterPage->GetPresObj( PRESOBJ_HEADER ); + if( pHeader == NULL ) + pMasterPage->CreateDefaultPresObj( PRESOBJ_HEADER, true ); + } + + SdrObject* pDate = pMasterPage->GetPresObj( PRESOBJ_DATETIME ); + if( pDate == NULL ) + pMasterPage->CreateDefaultPresObj( PRESOBJ_DATETIME, true ); + + SdrObject* pFooter = pMasterPage->GetPresObj( PRESOBJ_FOOTER ); + if( pFooter == NULL ) + pMasterPage->CreateDefaultPresObj( PRESOBJ_FOOTER, true ); + + SdrObject* pNumber = pMasterPage->GetPresObj( PRESOBJ_SLIDENUMBER ); + if( pNumber == NULL ) + pMasterPage->CreateDefaultPresObj( PRESOBJ_SLIDENUMBER, true ); + } + } +} + +SdrObject* SdPage::CreateDefaultPresObj(PresObjKind eObjKind, bool bInsert) +{ + if( eObjKind == PRESOBJ_TITLE ) + { + Rectangle aTitleRect( GetTitleRect() ); + return CreatePresObj(PRESOBJ_TITLE, FALSE, aTitleRect, bInsert); + } + else if( eObjKind == PRESOBJ_OUTLINE ) + { + Rectangle aLayoutRect( GetLayoutRect() ); + return CreatePresObj( PRESOBJ_OUTLINE, FALSE, aLayoutRect, bInsert); + } + else if( eObjKind == PRESOBJ_NOTES ) + { + Rectangle aLayoutRect( GetLayoutRect() ); + return CreatePresObj( PRESOBJ_NOTES, FALSE, aLayoutRect, bInsert); + } + else if( (eObjKind == PRESOBJ_FOOTER) || (eObjKind == PRESOBJ_DATETIME) || (eObjKind == PRESOBJ_SLIDENUMBER) || (eObjKind == PRESOBJ_HEADER ) ) + { + // create footer objects for standard master page + if( mePageKind == PK_STANDARD ) + { + const long nLftBorder = GetLftBorder(); + const long nUppBorder = GetUppBorder(); + + Point aTitlePos ( nLftBorder, nUppBorder ); + Size aPageSize ( GetSize() ); + aPageSize.Width() -= nLftBorder + GetRgtBorder(); + aPageSize.Height() -= nUppBorder + GetLwrBorder(); + + const int Y = long(nUppBorder + aPageSize.Height() * 0.911); + const int W1 = long(aPageSize.Width() * 0.233); + const int W2 = long(aPageSize.Width() * 0.317); + const int H = long(aPageSize.Height() * 0.069); + + if( eObjKind == PRESOBJ_DATETIME ) + { + Point aPos( long(nLftBorder+(aPageSize.Width()*0.05)), Y ); + Size aSize( W1, H ); + Rectangle aRect( aPos, aSize ); + return CreatePresObj( PRESOBJ_DATETIME, FALSE, aRect, bInsert ); + } + else if( eObjKind == PRESOBJ_FOOTER ) + { + Point aPos( long(nLftBorder+ aPageSize.Width() * 0.342), Y ); + Size aSize( W2, H ); + Rectangle aRect( aPos, aSize ); + return CreatePresObj( PRESOBJ_FOOTER, FALSE, aRect, bInsert ); + } + else if( eObjKind == PRESOBJ_SLIDENUMBER ) + { + Point aPos( long(nLftBorder+(aPageSize.Width()*0.717)), Y ); + Size aSize( W1, H ); + Rectangle aRect( aPos, aSize ); + return CreatePresObj( PRESOBJ_SLIDENUMBER, FALSE, aRect, bInsert ); + } + else + { + DBG_ERROR( "SdPage::CreateDefaultPresObj() - can't create a header placeholder for a slide master" ); + return NULL; + } + } + else + { + // create header&footer objects for handout and notes master + Point aTitlePos ( GetLftBorder(), GetUppBorder() ); + Size aPageSize ( GetSize() ); + aPageSize.Width() -= GetLftBorder() + GetRgtBorder(); + aPageSize.Height() -= GetUppBorder() + GetLwrBorder(); + + + const int NOTES_HEADER_FOOTER_WIDTH = long(aPageSize.Width() * 0.434); + const int NOTES_HEADER_FOOTER_HEIGHT = long(aPageSize.Height() * 0.05); + + Size aSize( NOTES_HEADER_FOOTER_WIDTH, NOTES_HEADER_FOOTER_HEIGHT ); + + const int X1 = GetLftBorder(); + const int X2 = GetLftBorder() + long(aPageSize.Width() - NOTES_HEADER_FOOTER_WIDTH); + const int Y1 = GetUppBorder(); + const int Y2 = GetUppBorder() + long(aPageSize.Height() - NOTES_HEADER_FOOTER_HEIGHT ); + + if( eObjKind == PRESOBJ_HEADER ) + { + Point aPos( X1, Y1 ); + Rectangle aRect( aPos, aSize ); + return CreatePresObj( PRESOBJ_HEADER, FALSE, aRect, bInsert ); + } + else if( eObjKind == PRESOBJ_DATETIME ) + { + Point aPos( X2, Y1 ); + Rectangle aRect( aPos, aSize ); + return CreatePresObj( PRESOBJ_DATETIME, FALSE, aRect, bInsert ); + } + else if( eObjKind == PRESOBJ_FOOTER ) + { + Point aPos( X1, Y2 ); + Rectangle aRect( aPos, aSize ); + return CreatePresObj( PRESOBJ_FOOTER, FALSE, aRect, bInsert ); + } + else if( eObjKind == PRESOBJ_SLIDENUMBER ) + { + Point aPos( X2, Y2 ); + Rectangle aRect( aPos, aSize ); + return CreatePresObj( PRESOBJ_SLIDENUMBER, FALSE, aRect, bInsert ); + } + + DBG_ERROR("SdPage::CreateDefaultPresObj() - this should not happen!"); + return NULL; + } + } + else + { + DBG_ERROR("SdPage::CreateDefaultPresObj() - unknown PRESOBJ kind" ); + return NULL; + } +} + +/************************************************************************* +|* +|* Titelbereich zurueckgeben +|* +\************************************************************************/ + +Rectangle SdPage::GetTitleRect() const +{ + Rectangle aTitleRect; + + if (mePageKind != PK_HANDOUT) + { + /****************************************************************** + * Standard- oder Notiz-Seite: Titelbereich + ******************************************************************/ + Point aTitlePos ( GetLftBorder(), GetUppBorder() ); + Size aTitleSize ( GetSize() ); + aTitleSize.Width() -= GetLftBorder() + GetRgtBorder(); + aTitleSize.Height() -= GetUppBorder() + GetLwrBorder(); + + if (mePageKind == PK_STANDARD) + { + aTitlePos.X() += long( aTitleSize.Width() * 0.05 ); + aTitlePos.Y() += long( aTitleSize.Height() * 0.0399 ); + aTitleSize.Width() = long( aTitleSize.Width() * 0.9 ); + aTitleSize.Height() = long( aTitleSize.Height() * 0.167 ); + } + else if (mePageKind == PK_NOTES) + { + Point aPos = aTitlePos; + aPos.Y() += long( aTitleSize.Height() * 0.076 ); + + // Hoehe beschraenken + aTitleSize.Height() = (long) (aTitleSize.Height() * 0.375); + + Size aPartArea = aTitleSize; + Size aSize; + sal_uInt16 nDestPageNum(GetPageNum()); + SdrPage* pRefPage = 0L; + + if(nDestPageNum) + { + // only decrement if != 0, else we get 0xffff + nDestPageNum -= 1; + } + + if(nDestPageNum < pModel->GetPageCount()) + { + pRefPage = pModel->GetPage(nDestPageNum); + } + + if ( pRefPage ) + { + // tatsaechliche Seitengroesse in das Handout-Rechteck skalieren + double fH = (double) aPartArea.Width() / pRefPage->GetWdt(); + double fV = (double) aPartArea.Height() / pRefPage->GetHgt(); + + if ( fH > fV ) + fH = fV; + aSize.Width() = (long) (fH * pRefPage->GetWdt()); + aSize.Height() = (long) (fH * pRefPage->GetHgt()); + + aPos.X() += (aPartArea.Width() - aSize.Width()) / 2; + aPos.Y() += (aPartArea.Height()- aSize.Height())/ 2; + } + + aTitlePos = aPos; + aTitleSize = aSize; + } + + aTitleRect.SetPos(aTitlePos); + aTitleRect.SetSize(aTitleSize); + } + + return aTitleRect; +} + + +/************************************************************************* +|* +|* Gliederungsbereich zurueckgeben +|* +\************************************************************************/ + +Rectangle SdPage::GetLayoutRect() const +{ + Rectangle aLayoutRect; + + if (mePageKind != PK_HANDOUT) + { + Point aLayoutPos ( GetLftBorder(), GetUppBorder() ); + Size aLayoutSize ( GetSize() ); + aLayoutSize.Width() -= GetLftBorder() + GetRgtBorder(); + aLayoutSize.Height() -= GetUppBorder() + GetLwrBorder(); + + if (mePageKind == PK_STANDARD) + { + aLayoutPos.X() += long( aLayoutSize.Width() * 0.05 ); + aLayoutPos.Y() += long( aLayoutSize.Height() * 0.234 ); + aLayoutSize.Width() = long( aLayoutSize.Width() * 0.9 ); + aLayoutSize.Height() = long( aLayoutSize.Height() * 0.66 ); + aLayoutRect.SetPos(aLayoutPos); + aLayoutRect.SetSize(aLayoutSize); + } + else if (mePageKind == PK_NOTES) + { + aLayoutPos.X() += long( aLayoutSize.Width() * 0.1 ); + aLayoutPos.Y() += long( aLayoutSize.Height() * 0.475 ); + aLayoutSize.Width() = long( aLayoutSize.Width() * 0.8 ); + aLayoutSize.Height() = long( aLayoutSize.Height() * 0.45 ); + aLayoutRect.SetPos(aLayoutPos); + aLayoutRect.SetSize(aLayoutSize); + } + } + + return aLayoutRect; +} + + +/************************************************************************** +|* +|* Diese Methode weist ein AutoLayout zu +|* +\*************************************************************************/ + +const int MAX_PRESOBJS = 7; // maximum number of presentation objects per layout +const int VERTICAL = 0x8000; + +struct LayoutDescriptor +{ + int mnLayout; + PresObjKind meKind[MAX_PRESOBJS]; + bool mbVertical[MAX_PRESOBJS]; + + LayoutDescriptor( int nLayout, int k0 = 0, int k1 = 0, int k2 = 0, int k3 = 0, int k4 = 0, int k5 = 0, int k6 = 0 ); +}; + +LayoutDescriptor::LayoutDescriptor( int nLayout, int k0, int k1, int k2, int k3, int k4, int k5, int k6 ) +: mnLayout( nLayout ) +{ + meKind[0] = static_cast<PresObjKind>(k0 & (~VERTICAL)); mbVertical[0] = (k0 & VERTICAL) == VERTICAL; + meKind[1] = static_cast<PresObjKind>(k1 & (~VERTICAL)); mbVertical[1] = (k1 & VERTICAL) == VERTICAL; + meKind[2] = static_cast<PresObjKind>(k2 & (~VERTICAL)); mbVertical[2] = (k2 & VERTICAL) == VERTICAL; + meKind[3] = static_cast<PresObjKind>(k3 & (~VERTICAL)); mbVertical[3] = (k3 & VERTICAL) == VERTICAL; + meKind[4] = static_cast<PresObjKind>(k4 & (~VERTICAL)); mbVertical[4] = (k4 & VERTICAL) == VERTICAL; + meKind[5] = static_cast<PresObjKind>(k5 & (~VERTICAL)); mbVertical[5] = (k5 & VERTICAL) == VERTICAL; + meKind[6] = static_cast<PresObjKind>(k6 & (~VERTICAL)); mbVertical[6] = (k6 & VERTICAL) == VERTICAL; +} + +static const LayoutDescriptor& GetLayoutDescriptor( AutoLayout eLayout ) +{ + static LayoutDescriptor aLayouts[AUTOLAYOUT__END-AUTOLAYOUT__START] = + { + LayoutDescriptor( 0, PRESOBJ_TITLE, PRESOBJ_TEXT ), // AUTOLAYOUT_TITLE + LayoutDescriptor( 0, PRESOBJ_TITLE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_ENUM + LayoutDescriptor( 0, PRESOBJ_TITLE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_CHART + LayoutDescriptor( 1, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_2TEXT + LayoutDescriptor( 1, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_TEXTCHART + LayoutDescriptor( 0, PRESOBJ_TITLE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_ORG + LayoutDescriptor( 1, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_TEXTCLbIP + LayoutDescriptor( 1, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_CHARTTEXT + LayoutDescriptor( 0, PRESOBJ_TITLE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_TAB + LayoutDescriptor( 1, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_CLIPTEXT + LayoutDescriptor( 1, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_TEXTOBJ + LayoutDescriptor( 0, PRESOBJ_TITLE, PRESOBJ_OBJECT ), // AUTOLAYOUT_OBJ + LayoutDescriptor( 2, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_TEXT2OBJ + LayoutDescriptor( 1, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_TEXTOBJ + LayoutDescriptor( 4, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_OBJOVERTEXT + LayoutDescriptor( 3, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_2OBJTEXT + LayoutDescriptor( 5, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_2OBJOVERTEXT + LayoutDescriptor( 4, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), // AUTOLAYOUT_TEXTOVEROBJ + LayoutDescriptor( 6, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE, // AUTOLAYOUT_4OBJ + PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ), + LayoutDescriptor( 0, PRESOBJ_TITLE, PRESOBJ_NONE ), // AUTOLAYOUT_ONLY_TITLE + LayoutDescriptor( 0, PRESOBJ_NONE ), // AUTOLAYOUT_NONE + LayoutDescriptor( 0, PRESOBJ_PAGE, PRESOBJ_NOTES ), // AUTOLAYOUT_NOTES + LayoutDescriptor( 0 ), // AUTOLAYOUT_HANDOUT1 + LayoutDescriptor( 0 ), // AUTOLAYOUT_HANDOUT2 + LayoutDescriptor( 0 ), // AUTOLAYOUT_HANDOUT3 + LayoutDescriptor( 0 ), // AUTOLAYOUT_HANDOUT4 + LayoutDescriptor( 0 ), // AUTOLAYOUT_HANDOUT6 + LayoutDescriptor( 7, PRESOBJ_TITLE|VERTICAL, PRESOBJ_OUTLINE|VERTICAL, PRESOBJ_OUTLINE ),// AUTOLAYOUT_VERTICAL_TITLE_TEXT_CHART + LayoutDescriptor( 8, PRESOBJ_TITLE|VERTICAL, PRESOBJ_OUTLINE|VERTICAL ), // AUTOLAYOUT_VERTICAL_TITLE_VERTICAL_OUTLINE + LayoutDescriptor( 0, PRESOBJ_TITLE, PRESOBJ_OUTLINE|VERTICAL ), // AUTOLAYOUT_TITLE_VERTICAL_OUTLINE + LayoutDescriptor( 9, PRESOBJ_TITLE, PRESOBJ_OUTLINE|VERTICAL, PRESOBJ_OUTLINE|VERTICAL ), // AUTOLAYOUT_TITLE_VERTICAL_OUTLINE_CLIPART + LayoutDescriptor( 0 ), // AUTOLAYOUT_HANDOUT9 + LayoutDescriptor( 10, PRESOBJ_TEXT, PRESOBJ_NONE ), // AUTOLAYOUT_ONLY_TEXT + LayoutDescriptor( 6, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE, // AUTOLAYOUT_4CLIPART + PRESOBJ_GRAPHIC, PRESOBJ_GRAPHIC ), + LayoutDescriptor( 11, PRESOBJ_TITLE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE, // AUTOLAYOUT_6CLIPART + PRESOBJ_OUTLINE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE, PRESOBJ_OUTLINE ) + }; + + if( (eLayout < AUTOLAYOUT__START) || (eLayout >= AUTOLAYOUT__END) ) + eLayout = AUTOLAYOUT_NONE; + + return aLayouts[ eLayout - AUTOLAYOUT__START ]; +} + +static void CalcAutoLayoutRectangles( SdPage& rPage, int nLayout, Rectangle* rRectangle ) +{ + Rectangle aTitleRect; + Rectangle aLayoutRect; + + if( rPage.GetPageKind() != PK_HANDOUT ) + { + SdPage& rMasterPage = static_cast<SdPage&>(rPage.TRG_GetMasterPage()); + SdrObject* pMasterTitle = rMasterPage.GetPresObj( PRESOBJ_TITLE ); + SdrObject* pMasterOutline = rMasterPage.GetPresObj( rPage.GetPageKind()==PK_NOTES ? PRESOBJ_NOTES : PRESOBJ_OUTLINE ); + + if( pMasterTitle ) + aTitleRect = pMasterTitle->GetLogicRect(); + + if (aTitleRect.IsEmpty() ) + aTitleRect = rPage.GetTitleRect(); + + if( pMasterOutline ) + aLayoutRect = pMasterOutline->GetLogicRect(); + + if (aLayoutRect.IsEmpty() ) + aLayoutRect = rPage.GetLayoutRect(); + } + + rRectangle[0] = aTitleRect; + + int i; + for( i = 1; i < MAX_PRESOBJS; i++ ) + rRectangle[i] = aLayoutRect; + + Size aTitleSize( aTitleRect.GetSize() ); + Point aTitlePos( aTitleRect.TopLeft() ); + Size aLayoutSize( aLayoutRect.GetSize() ); + Point aLayoutPos( aLayoutRect.TopLeft() ); + Size aTempSize; + Point aTempPnt; + + sal_Bool bRightToLeft = ( rPage.GetModel() && static_cast< SdDrawDocument* >( rPage.GetModel() )->GetDefaultWritingMode() == ::com::sun::star::text::WritingMode_RL_TB ); + + switch( nLayout ) + { + case 0: // default layout using only the title and layout area + break; // do nothing + case 1: // title, 2 shapes + case 9: // title, 2 vertical shapes + aLayoutSize.Width() = long (aLayoutSize.Width() * 0.488); + rRectangle[1] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.X() = long (aLayoutPos.X() + aLayoutSize.Width() * 1.05); + rRectangle[2] = Rectangle (aLayoutPos, aLayoutSize); + + if( bRightToLeft && (nLayout != 9) ) + ::std::swap< Rectangle >( rRectangle[1], rRectangle[2] ); + break; + case 2: // title, shape, 2 shapes + aTempPnt = aLayoutPos; + aTempSize = aLayoutSize; + aLayoutSize.Height() = long (aLayoutSize.Height() * 0.477); + aLayoutSize.Width() = long (aLayoutSize.Width() * 0.488); + aLayoutPos.X() = long (aLayoutPos.X() + aLayoutSize.Width() * 1.05); + rRectangle[2] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.Y() = long (aLayoutPos.Y() + aLayoutSize.Height() * 1.095); + rRectangle[3] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos = aTempPnt; + aLayoutSize = aTempSize; + aLayoutSize.Width() = long (aLayoutSize.Width() * 0.488); + rRectangle[1] = Rectangle (aLayoutPos, aLayoutSize); + + if( bRightToLeft ) + { + ::std::swap< long >( rRectangle[1].Left(), rRectangle[2].Left() ); + rRectangle[3].Left() = rRectangle[2].Left(); + } + break; + case 3: // title, 2 shapes, shape + aTempPnt = aLayoutPos; + aTempSize = aLayoutSize; + aLayoutSize.Height() = long (aLayoutSize.Height() * 0.477); + aLayoutSize.Width() = long (aLayoutSize.Width() * 0.488); + rRectangle[1] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.Y() = long (aLayoutPos.Y() + aLayoutSize.Height() * 1.095); + rRectangle[2] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos = aTempPnt; + aLayoutSize = aTempSize; + aLayoutSize.Width() = long (aLayoutSize.Width() * 0.488); + aLayoutPos.X() = long (aLayoutPos.X() + aLayoutSize.Width() * 1.05); + rRectangle[3] = Rectangle (aLayoutPos, aLayoutSize); + + if( bRightToLeft ) + { + ::std::swap< long >( rRectangle[1].Left(), rRectangle[2].Left() ); + rRectangle[3].Left() = rRectangle[2].Left(); + } + break; + case 4: // title, shape above shape + aLayoutSize.Height() = long (aLayoutSize.Height() * 0.477); + rRectangle[1] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.Y() = long (aLayoutPos.Y() + aLayoutSize.Height() * 1.095); + rRectangle[2] = Rectangle (aLayoutPos, aLayoutSize); + break; + + case 5: // title, 2 shapes above shape + aLayoutSize.Height() = long (aLayoutSize.Height() * 0.477); + aLayoutSize.Width() = long (aLayoutSize.Width() * 0.488); + rRectangle[1] = Rectangle (aLayoutPos, aLayoutSize); + + aTempPnt = aLayoutPos; + aLayoutPos.X() = long (aLayoutPos.X() + aLayoutSize.Width() * 1.05); + rRectangle[2] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.X() = aTempPnt.X(); + aLayoutPos.Y() = long (aLayoutPos.Y() + aLayoutSize.Height() * 1.095); + aLayoutSize.Width() = long (aLayoutSize.Width() / 0.488); + rRectangle[3] = Rectangle (aLayoutPos, aLayoutSize); + break; + case 6: // title, 4 shapes + { + ULONG nX = long (aLayoutPos.X()); + + aLayoutSize.Height() = long (aLayoutSize.Height() * 0.477); + aLayoutSize.Width() = long (aLayoutSize.Width() * 0.488); + rRectangle[1] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.X() = long (nX + aLayoutSize.Width() * 1.05); + rRectangle[2] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.Y() = long (aLayoutPos.Y() + aLayoutSize.Height() * 1.095); + rRectangle[3] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.X() = nX; + rRectangle[4] = Rectangle (aLayoutPos, aLayoutSize); + break; + } + case 7: // vertical title, shape above shape + { + Size aSize( rRectangle[0].GetSize().Height(), rRectangle[1].BottomLeft().Y() - rRectangle[0].TopLeft().Y() ); + rRectangle[0].SetSize( aSize ); + rRectangle[0].SetPos( aTitleRect.TopRight() - Point( aSize.Width(), 0 ) ); + + Size aPageSize ( rPage.GetSize() ); + aPageSize.Height() -= rPage.GetUppBorder() + rPage.GetLwrBorder(); + aSize.Height() = long ( rRectangle[0].GetSize().Height() * 0.47 ); + aSize.Width() = long( aPageSize.Width() * 0.7 ); + rRectangle[1].SetPos( aTitleRect.TopLeft() ); + rRectangle[1].SetSize( aSize ); + + aSize.Height() = rRectangle[0].GetSize().Height(); + Point aPos( aTitleRect.TopLeft() ); + aPos.Y() += long ( aSize.Height() * 0.53 ); + rRectangle[2].SetPos( aPos ); + aSize.Height() = long ( rRectangle[0].GetSize().Height() * 0.47 ); + rRectangle[2].SetSize( aSize ); + break; + } + case 8: // vertical title, shape + { + Size aSize( rRectangle[0].GetSize().Height(), rRectangle[1].BottomLeft().Y() - rRectangle[0].TopLeft().Y() ); + rRectangle[0].SetSize( aSize ); + rRectangle[0].SetPos( aTitleRect.TopRight() - Point( aSize.Width(), 0 ) ); + + Size aPageSize ( rPage.GetSize() ); + aPageSize.Height() -= rPage.GetUppBorder() + rPage.GetLwrBorder(); + aSize.Height() = rRectangle[0].GetSize().Height(); + aSize.Width() = long( aPageSize.Width() * 0.7 ); + rRectangle[1].SetPos( aTitleRect.TopLeft() ); + rRectangle[1].SetSize( aSize ); + break; + } + case 10: // onlytext + { + Size aSize( rRectangle[0].GetSize().Width(), rRectangle[1].BottomLeft().Y() - rRectangle[0].TopLeft().Y() ); + rRectangle[0].SetSize( aSize ); + rRectangle[0].SetPos( aTitlePos); + break; + } + case 11: // title, 6 shapes + { + ULONG nX = long (aLayoutPos.X()); + + aLayoutSize.Height() = long (aLayoutSize.Height() * 0.477); + aLayoutSize.Width() = long (aLayoutSize.Width() * 0.322); + rRectangle[1] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.X() = long (nX + aLayoutSize.Width() * 1.05); + rRectangle[2] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.X() = long (nX + aLayoutSize.Width() * 2 * 1.05); + rRectangle[3] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.Y() = long (aLayoutPos.Y() + aLayoutSize.Height() * 1.095); + rRectangle[4] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.X() = long (nX + aLayoutSize.Width() * 1.05); + rRectangle[5] = Rectangle (aLayoutPos, aLayoutSize); + + aLayoutPos.X() = nX; + rRectangle[6] = Rectangle (aLayoutPos, aLayoutSize); + + break; + } + + } +} + + +void findAutoLayoutShapesImpl( SdPage& rPage, const LayoutDescriptor& rDescriptor, std::vector< SdrObject* >& rShapes, bool bInit, bool bSwitchLayout ) +{ + int i; + + // init list of indexes for each presentation shape kind + // this is used to find subsequent shapes with the same presentation shape kind + int PresObjIndex[PRESOBJ_MAX]; + for( i = 0; i < PRESOBJ_MAX; i++ ) PresObjIndex[i] = 1; + + bool bMissing = false; + + // for each entry in the layoutdescriptor, arrange a presentation shape + for( i = 0; (i < PRESOBJ_MAX) && (rDescriptor.meKind[i] != PRESOBJ_NONE); i++ ) + { + PresObjKind eKind = rDescriptor.meKind[i]; + SdrObject* pObj = 0; + while( (pObj = rPage.GetPresObj( eKind, PresObjIndex[eKind], true )) != 0 ) + { + PresObjIndex[eKind]++; // on next search for eKind, find next shape with same eKind + + if( !bSwitchLayout || !pObj->IsEmptyPresObj() ) + { + rShapes[i] = pObj; + break; + } + } + + if( !pObj ) + bMissing = true; + } + + if( bMissing && bInit ) + { + // for each entry in the layoutdescriptor, look for an alternative shape + for( i = 0; (i < PRESOBJ_MAX) && (rDescriptor.meKind[i] != PRESOBJ_NONE); i++ ) + { + if( rShapes[i] ) + continue; + + PresObjKind eKind = rDescriptor.meKind[i]; + + SdrObject* pObj = 0; + bool bFound = false; + + const int nShapeCount = rPage.GetObjCount(); + int nShapeIndex = 0; + while((nShapeIndex < nShapeCount) && !bFound ) + { + pObj = rPage.GetObj(nShapeIndex++); + + if( pObj->IsEmptyPresObj() ) + continue; + + if( pObj->GetObjInventor() != SdrInventor ) + continue; + + // do not reuse shapes that are already part of the layout + if( std::find( rShapes.begin(), rShapes.end(), pObj ) != rShapes.end() ) + continue; + + bool bPresStyle = pObj->GetStyleSheet() && (pObj->GetStyleSheet()->GetFamily() == SD_STYLE_FAMILY_MASTERPAGE); + SdrObjKind eSdrObjKind = static_cast< SdrObjKind >( pObj->GetObjIdentifier() ); + + switch( eKind ) + { + case PRESOBJ_TITLE: + bFound = eSdrObjKind == OBJ_TITLETEXT; + break; + case PRESOBJ_TABLE: + bFound = eSdrObjKind == OBJ_TABLE; + break; + case PRESOBJ_MEDIA: + bFound = eSdrObjKind == OBJ_MEDIA; + break; + case PRESOBJ_OUTLINE: + bFound = (eSdrObjKind == OBJ_OUTLINETEXT) || + ((eSdrObjKind == OBJ_TEXT) && bPresStyle) || + (eSdrObjKind == OBJ_TABLE) || (eSdrObjKind == OBJ_MEDIA) || (eSdrObjKind == OBJ_GRAF) || (eSdrObjKind == OBJ_OLE2); + break; + case PRESOBJ_GRAPHIC: + bFound = eSdrObjKind == OBJ_GRAF; + break; + case PRESOBJ_OBJECT: + if( eSdrObjKind == OBJ_OLE2 ) + { + SdrOle2Obj* pOle2 = dynamic_cast< SdrOle2Obj* >( pObj ); + if( pOle2 ) + { + if( pOle2->IsEmpty() ) + bFound = true; + else if( rPage.GetModel() ) + { + SdrModel* pSdrModel = rPage.GetModel(); + ::comphelper::IEmbeddedHelper *pPersist = pSdrModel->GetPersist(); + if( pPersist ) + { + uno::Reference < embed::XEmbeddedObject > xObject = pPersist->getEmbeddedObjectContainer(). + GetEmbeddedObject( static_cast< SdrOle2Obj* >( pObj )->GetPersistName() ); + + // TODO CL->KA: Why is this not working anymore? + if( xObject.is() ) + { + SvGlobalName aClassId( xObject->getClassID() ); + + const SvGlobalName aAppletClassId( SO3_APPLET_CLASSID ); + const SvGlobalName aPluginClassId( SO3_PLUGIN_CLASSID ); + const SvGlobalName aIFrameClassId( SO3_IFRAME_CLASSID ); + + if( aPluginClassId != aClassId && aAppletClassId != aClassId && aIFrameClassId != aClassId ) + { + bFound = true; + } + } + } + } + } + } + break; + case PRESOBJ_CHART: + case PRESOBJ_CALC: + if( eSdrObjKind == OBJ_OLE2 ) + { + SdrOle2Obj* pOle2 = dynamic_cast< SdrOle2Obj* >( pObj ); + if( pOle2 ) + { + if( + ((eKind == PRESOBJ_CHART) && + ( pOle2->GetProgName().EqualsAscii( "StarChart" ) || pOle2->IsChart() ) ) + || + ((eKind == PRESOBJ_CALC) && + ( pOle2->GetProgName().EqualsAscii( "StarCalc" ) || pOle2->IsCalc() ) ) ) + { + bFound = true; + } + } + break; + } + else if( eSdrObjKind == OBJ_TABLE ) + { + bFound = true; + } + break; + case PRESOBJ_PAGE: + case PRESOBJ_HANDOUT: + bFound = eSdrObjKind == OBJ_PAGE; + break; + case PRESOBJ_NOTES: + case PRESOBJ_TEXT: + bFound = (bPresStyle && (eSdrObjKind == OBJ_TEXT)) || (eSdrObjKind == OBJ_OUTLINETEXT); + break; + default: + break; + } + } + + if( bFound ) + rShapes[i] = pObj; + } + } +} + +void SdPage::SetAutoLayout(AutoLayout eLayout, BOOL bInit, BOOL bCreate ) +{ + sd::ScopeLockGuard aGuard( maLockAutoLayoutArrangement ); + + const bool bSwitchLayout = eLayout != GetAutoLayout(); + + sd::UndoManager* pUndoManager = pModel ? static_cast<SdDrawDocument*>(pModel)->GetUndoManager() : 0; + const bool bUndo = pUndoManager && pUndoManager->isInListAction() && IsInserted(); + + meAutoLayout = eLayout; + + // if needed, creates and initialises the presentation shapes on this slides master page + CreateTitleAndLayout(bInit, bCreate); + + if((meAutoLayout == AUTOLAYOUT_NONE && maPresentationShapeList.isEmpty()) || mbMaster) + { + // MasterPage or no layout and no presentation shapes available, noting to do + return; + } + + Rectangle aRectangle[MAX_PRESOBJS]; + const LayoutDescriptor& aDescriptor = GetLayoutDescriptor( meAutoLayout ); + CalcAutoLayoutRectangles( *this, aDescriptor.mnLayout, aRectangle ); + + std::set< SdrObject* > aUsedPresentationObjects; + + + std::vector< SdrObject* > aLayoutShapes(PRESOBJ_MAX, 0); + findAutoLayoutShapesImpl( *this, aDescriptor, aLayoutShapes, bInit, bSwitchLayout ); + + int i; + + // for each entry in the layoutdescriptor, arrange a presentation shape + for( i = 0; (i < PRESOBJ_MAX) && (aDescriptor.meKind[i] != PRESOBJ_NONE); i++ ) + { + PresObjKind eKind = aDescriptor.meKind[i]; + SdrObject* pObj = InsertAutoLayoutShape( aLayoutShapes[i], eKind, aDescriptor.mbVertical[i], aRectangle[i], bInit ); + if( pObj ) + aUsedPresentationObjects.insert(pObj); // remember that we used this empty shape + } + + // now delete all empty presentation objects that are no longer used by the new layout + if( bInit ) + { + SdrObject* pObj = maPresentationShapeList.getNextShape(0); + + while( pObj ) + { + SdrObject* pNext = maPresentationShapeList.getNextShape(pObj); + if( aUsedPresentationObjects.count(pObj) == 0 ) + { + + if( pObj->IsEmptyPresObj() ) + { + if( bUndo ) + pUndoManager->AddUndoAction(pModel->GetSdrUndoFactory().CreateUndoDeleteObject(*pObj)); + + RemoveObject( pObj->GetOrdNum() ); + + if( !bUndo ) + SdrObject::Free( pObj ); + } +/* #i108541# keep non empty pres obj as pres obj even if they are not part of the current layout */ + } + pObj = pNext; + } + } +} + +/************************************************************************* +|* +|* Objekt einfuegen +|* +\************************************************************************/ + +void SdPage::NbcInsertObject(SdrObject* pObj, ULONG nPos, const SdrInsertReason* pReason) +{ + FmFormPage::NbcInsertObject(pObj, nPos, pReason); + + ((SdDrawDocument*) pModel)->InsertObject(pObj, this); + + SdrLayerID nId = pObj->GetLayer(); + if( mbMaster ) + { + if( nId == 0 ) + pObj->NbcSetLayer( 2 ); // wrong layer. corrected to BackgroundObj layer + } + else + { + if( nId == 2 ) + pObj->NbcSetLayer( 0 ); // wrong layer. corrected to layout layer + } +} + +/************************************************************************* +|* +|* Objekt loeschen +|* +\************************************************************************/ + +SdrObject* SdPage::RemoveObject(ULONG nObjNum) +{ + onRemoveObject(GetObj( nObjNum )); + return FmFormPage::RemoveObject(nObjNum); +} + +/************************************************************************* +|* +|* Objekt loeschen, ohne Broadcast +|* +\************************************************************************/ + +SdrObject* SdPage::NbcRemoveObject(ULONG nObjNum) +{ + onRemoveObject(GetObj( nObjNum )); + return FmFormPage::NbcRemoveObject(nObjNum); +} + +// #95876# Also overload ReplaceObject methods to realize when +// objects are removed with this mechanism instead of RemoveObject +SdrObject* SdPage::NbcReplaceObject(SdrObject* pNewObj, ULONG nObjNum) +{ + onRemoveObject(GetObj( nObjNum )); + return FmFormPage::NbcReplaceObject(pNewObj, nObjNum); +} + +// #95876# Also overload ReplaceObject methods to realize when +// objects are removed with this mechanism instead of RemoveObject +SdrObject* SdPage::ReplaceObject(SdrObject* pNewObj, ULONG nObjNum) +{ + onRemoveObject(GetObj( nObjNum )); + return FmFormPage::ReplaceObject(pNewObj, nObjNum); +} + +// ------------------------------------------------------------------------- + +// called after a shape is removed or replaced from this slide + +void SdPage::onRemoveObject( SdrObject* pObject ) +{ + if( pObject ) + { + RemovePresObj(pObject); + + if( pModel ) + static_cast<SdDrawDocument*>(pModel)->RemoveObject(pObject, this); + + removeAnimations( pObject ); + } +} + +void SdPage::SetSize(const Size& aSize) +{ + Size aOldSize = GetSize(); + + if (aSize != aOldSize) + { + FmFormPage::SetSize(aSize); + + if (aOldSize.Height() == 10 && aOldSize.Width() == 10) + { + // Die Seite bekommt erstmalig eine gueltige Groesse gesetzt, + // daher wird nun die Orientation initialisiert + if (aSize.Width() > aSize.Height()) + { + meOrientation = ORIENTATION_LANDSCAPE; + } + else + { + meOrientation = ORIENTATION_PORTRAIT; + } + } + } +} + +void SdPage::SetBorder(INT32 nLft, INT32 nUpp, INT32 nRgt, INT32 nLwr) +{ + if (nLft != GetLftBorder() || nUpp != GetUppBorder() || + nRgt != GetRgtBorder() || nLwr != GetLwrBorder() ) + { + FmFormPage::SetBorder(nLft, nUpp, nRgt, nLwr); + } +} + +void SdPage::SetLftBorder(INT32 nBorder) +{ + if (nBorder != GetLftBorder() ) + { + FmFormPage::SetLftBorder(nBorder); + } +} + +void SdPage::SetRgtBorder(INT32 nBorder) +{ + if (nBorder != GetRgtBorder() ) + { + FmFormPage::SetRgtBorder(nBorder); + } +} + +void SdPage::SetUppBorder(INT32 nBorder) +{ + if (nBorder != GetUppBorder() ) + { + FmFormPage::SetUppBorder(nBorder); + } +} + +void SdPage::SetLwrBorder(INT32 nBorder) +{ + if (nBorder != GetLwrBorder() ) + { + FmFormPage::SetLwrBorder(nBorder); + } +} + +/************************************************************************* +|* +|* Setzt BackgroundFullSize und ruft dann AdjustBackground auf +|* +\************************************************************************/ + +void SdPage::SetBackgroundFullSize( BOOL bIn ) +{ + if( bIn != mbBackgroundFullSize ) + { + mbBackgroundFullSize = bIn; + } +} + +/************************************************************************* +|* +|* Alle Objekte an neue Seitengroesse anpassen +|* +|* bScaleAllObj: Alle Objekte werden in die neue Flaeche innerhalb der +|* Seitenraender skaliert. Dabei werden die Position, Groesse und bei +|* Praesentationsobjekten auf der MasterPage auch die Schrifthoehe der +|* Praesentationsvorlagen skaliert. +|* +\************************************************************************/ + +void SdPage::ScaleObjects(const Size& rNewPageSize, const Rectangle& rNewBorderRect, BOOL bScaleAllObj) +{ + sd::ScopeLockGuard aGuard( maLockAutoLayoutArrangement ); + + mbScaleObjects = bScaleAllObj; + SdrObject* pObj = NULL; + Point aRefPnt(0, 0); + Size aNewPageSize(rNewPageSize); + INT32 nLeft = rNewBorderRect.Left(); + INT32 nRight = rNewBorderRect.Right(); + INT32 nUpper = rNewBorderRect.Top(); + INT32 nLower = rNewBorderRect.Bottom(); + + // Negative Werte stehen fuer nicht zu aendernde Werte + // -> aktuelle Werte verwenden + if (aNewPageSize.Width() < 0) + { + aNewPageSize.Width() = GetWdt(); + } + if (aNewPageSize.Height() < 0) + { + aNewPageSize.Height() = GetHgt(); + } + if (nLeft < 0) + { + nLeft = GetLftBorder(); + } + if (nRight < 0) + { + nRight = GetRgtBorder(); + } + if (nUpper < 0) + { + nUpper = GetUppBorder(); + } + if (nLower < 0) + { + nLower = GetLwrBorder(); + } + + Point aBackgroundPos(nLeft, nUpper); + Size aBackgroundSize(aNewPageSize); + Rectangle aBorderRect (aBackgroundPos, aBackgroundSize); + + if (mbScaleObjects) + { + aBackgroundSize.Width() -= nLeft + nRight; + aBackgroundSize.Height() -= nUpper + nLower; + aBorderRect.SetSize(aBackgroundSize); + aNewPageSize = aBackgroundSize; + } + + long nOldWidth = GetWdt() - GetLftBorder() - GetRgtBorder(); + long nOldHeight = GetHgt() - GetUppBorder() - GetLwrBorder(); + + Fraction aFractX = Fraction(aNewPageSize.Width(), nOldWidth); + Fraction aFractY = Fraction(aNewPageSize.Height(), nOldHeight); + + ULONG nObjCnt = (mbScaleObjects ? GetObjCount() : 0); + + for (ULONG nObj = 0; nObj < nObjCnt; nObj++) + { + BOOL bIsPresObjOnMaster = FALSE; + + // Alle Objekte + pObj = GetObj(nObj); + + if (mbMaster && IsPresObj(pObj)) + { + // Es ist ein Praesentationsobjekt auf der MasterPage + bIsPresObjOnMaster = TRUE; + } + + if (pObj) + { + // #88084# remember aTopLeft as original TopLeft + Point aTopLeft(pObj->GetCurrentBoundRect().TopLeft()); + + if (!pObj->IsEdgeObj()) + { + /************************************************************** + * Objekt skalieren + **************************************************************/ + if (mbScaleObjects) + { + // #88084# use aTopLeft as original TopLeft + aRefPnt = aTopLeft; + } + + pObj->Resize(aRefPnt, aFractX, aFractY); + + if (mbScaleObjects) + { + SdrObjKind eObjKind = (SdrObjKind) pObj->GetObjIdentifier(); + + if (bIsPresObjOnMaster) + { + /********************************************************** + * Praesentationsvorlage: Texthoehe anpassen + **********************************************************/ + USHORT nIndexTitle = 0; + USHORT nIndexOutline = 0; + USHORT nIndexNotes = 0; + + if (pObj == GetPresObj(PRESOBJ_TITLE, nIndexTitle)) + { + SfxStyleSheet* pTitleSheet = GetStyleSheetForPresObj(PRESOBJ_TITLE); + + if (pTitleSheet) + { + SfxItemSet& rSet = pTitleSheet->GetItemSet(); + + SvxFontHeightItem& rOldHgt = (SvxFontHeightItem&) rSet.Get(EE_CHAR_FONTHEIGHT); + ULONG nFontHeight = rOldHgt.GetHeight(); + nFontHeight = long(nFontHeight * (double) aFractY); + rSet.Put(SvxFontHeightItem(nFontHeight, 100, EE_CHAR_FONTHEIGHT)); + + if( SFX_ITEM_AVAILABLE == rSet.GetItemState( EE_CHAR_FONTHEIGHT_CJK ) ) + { + rOldHgt = (SvxFontHeightItem&) rSet.Get(EE_CHAR_FONTHEIGHT_CJK); + nFontHeight = rOldHgt.GetHeight(); + nFontHeight = long(nFontHeight * (double) aFractY); + rSet.Put(SvxFontHeightItem(nFontHeight, 100, EE_CHAR_FONTHEIGHT_CJK)); + } + + if( SFX_ITEM_AVAILABLE == rSet.GetItemState( EE_CHAR_FONTHEIGHT_CTL ) ) + { + rOldHgt = (SvxFontHeightItem&) rSet.Get(EE_CHAR_FONTHEIGHT_CTL); + nFontHeight = rOldHgt.GetHeight(); + nFontHeight = long(nFontHeight * (double) aFractY); + rSet.Put(SvxFontHeightItem(nFontHeight, 100, EE_CHAR_FONTHEIGHT_CTL)); + } + + pTitleSheet->Broadcast(SfxSimpleHint(SFX_HINT_DATACHANGED)); + } + } + else if (pObj == GetPresObj(PRESOBJ_OUTLINE, nIndexOutline)) + { + String aName(GetLayoutName()); + aName += sal_Unicode( ' ' ); + + for (USHORT i=1; i<=9; i++) + { + String sLayoutName(aName); + sLayoutName += String::CreateFromInt32( (sal_Int32)i ); + SfxStyleSheet* pOutlineSheet = (SfxStyleSheet*)((SdDrawDocument*) pModel)->GetStyleSheetPool()->Find(sLayoutName, SD_STYLE_FAMILY_MASTERPAGE); + + if (pOutlineSheet) + { + // Neue Fonthoehe berechnen + SfxItemSet aTempSet(pOutlineSheet->GetItemSet()); + + SvxFontHeightItem& rOldHgt = (SvxFontHeightItem&) aTempSet.Get(EE_CHAR_FONTHEIGHT); + ULONG nFontHeight = rOldHgt.GetHeight(); + nFontHeight = long(nFontHeight * (double) aFractY); + aTempSet.Put(SvxFontHeightItem(nFontHeight, 100, EE_CHAR_FONTHEIGHT)); + + if( SFX_ITEM_AVAILABLE == aTempSet.GetItemState( EE_CHAR_FONTHEIGHT_CJK ) ) + { + rOldHgt = (SvxFontHeightItem&) aTempSet.Get(EE_CHAR_FONTHEIGHT_CJK); + nFontHeight = rOldHgt.GetHeight(); + nFontHeight = long(nFontHeight * (double) aFractY); + aTempSet.Put(SvxFontHeightItem(nFontHeight, 100, EE_CHAR_FONTHEIGHT_CJK)); + } + + if( SFX_ITEM_AVAILABLE == aTempSet.GetItemState( EE_CHAR_FONTHEIGHT_CTL ) ) + { + rOldHgt = (SvxFontHeightItem&) aTempSet.Get(EE_CHAR_FONTHEIGHT_CTL); + nFontHeight = rOldHgt.GetHeight(); + nFontHeight = long(nFontHeight * (double) aFractY); + aTempSet.Put(SvxFontHeightItem(nFontHeight, 100, EE_CHAR_FONTHEIGHT_CTL)); + } + + // Bullet anpassen + ((SdStyleSheet*) pOutlineSheet)->AdjustToFontHeight(aTempSet, FALSE); + + // Sonderbehandlung: die INVALIDS auf NULL-Pointer + // zurueckgesetzen (sonst landen INVALIDs oder + // Pointer auf die DefaultItems in der Vorlage; + // beides wuerde die Attribut-Vererbung unterbinden) + aTempSet.ClearInvalidItems(); + + // Sonderbehandlung: nur die gueltigen Anteile des + // BulletItems + if (aTempSet.GetItemState(EE_PARA_BULLET) == SFX_ITEM_AVAILABLE) + { + SvxBulletItem aOldBulItem((SvxBulletItem&) pOutlineSheet->GetItemSet().Get(EE_PARA_BULLET)); + SvxBulletItem& rNewBulItem = (SvxBulletItem&) aTempSet.Get(EE_PARA_BULLET); + aOldBulItem.CopyValidProperties(rNewBulItem); + aTempSet.Put(aOldBulItem); + } + + pOutlineSheet->GetItemSet().Put(aTempSet); + pOutlineSheet->Broadcast(SfxSimpleHint(SFX_HINT_DATACHANGED)); + } + } + } + else if (pObj == GetPresObj(PRESOBJ_NOTES, nIndexNotes)) + { + SfxStyleSheet* pNotesSheet = GetStyleSheetForPresObj(PRESOBJ_NOTES); + + if (pNotesSheet) + { + ULONG nHeight = pObj->GetLogicRect().GetSize().Height(); + ULONG nFontHeight = (ULONG) (nHeight * 0.0741); + SfxItemSet& rSet = pNotesSheet->GetItemSet(); + rSet.Put( SvxFontHeightItem(nFontHeight, 100, EE_CHAR_FONTHEIGHT )); + rSet.Put( SvxFontHeightItem(nFontHeight, 100, EE_CHAR_FONTHEIGHT_CJK )); + rSet.Put( SvxFontHeightItem(nFontHeight, 100, EE_CHAR_FONTHEIGHT_CTL )); + pNotesSheet->Broadcast(SfxSimpleHint(SFX_HINT_DATACHANGED)); + } + } + } + else if ( eObjKind != OBJ_TITLETEXT && + eObjKind != OBJ_OUTLINETEXT && + pObj->ISA(SdrTextObj) && + pObj->GetOutlinerParaObject() ) + { + /****************************************************** + * Normales Textobjekt: Texthoehe anpassen + ******************************************************/ + ULONG nScriptType = pObj->GetOutlinerParaObject()->GetTextObject().GetScriptType(); + USHORT nWhich = EE_CHAR_FONTHEIGHT; + if ( nScriptType == SCRIPTTYPE_ASIAN ) + nWhich = EE_CHAR_FONTHEIGHT_CJK; + else if ( nScriptType == SCRIPTTYPE_COMPLEX ) + nWhich = EE_CHAR_FONTHEIGHT_CTL; + + // #88084# use more modern method to scale the text height + sal_uInt32 nFontHeight = ((SvxFontHeightItem&)pObj->GetMergedItem(nWhich)).GetHeight(); + sal_uInt32 nNewFontHeight = sal_uInt32((double)nFontHeight * (double)aFractY); + + pObj->SetMergedItem(SvxFontHeightItem(nNewFontHeight, 100, nWhich)); + } + } + } + + if (mbScaleObjects && !pObj->IsEdgeObj()) + { + /************************************************************** + * Objektposition skalieren + **************************************************************/ + Point aNewPos; + + // #76447# corrected scaling; only distances may be scaled + // #88084# use aTopLeft as original TopLeft + aNewPos.X() = long((aTopLeft.X() - GetLftBorder()) * (double)aFractX) + nLeft; + aNewPos.Y() = long((aTopLeft.Y() - GetUppBorder()) * (double)aFractY) + nUpper; + + Size aVec(aNewPos.X() - aTopLeft.X(), aNewPos.Y() - aTopLeft.Y()); + + if (aVec.Height() != 0 || aVec.Width() != 0) + { + pObj->NbcMove(aVec); + } + + pObj->SetChanged(); + pObj->BroadcastObjectChange(); + } + } + } +} + +SdrObject* convertPresentationObjectImpl( SdPage& rPage, SdrObject* pSourceObj, PresObjKind& eObjKind, bool bVertical, Rectangle aRect ) +{ + SdDrawDocument* pModel = static_cast< SdDrawDocument* >( rPage.GetModel() ); + DBG_ASSERT( pModel, "sd::convertPresentationObjectImpl(), no model on page!" ); + if( !pModel || !pSourceObj ) + return pSourceObj; + + sd::UndoManager* pUndoManager = pModel ? static_cast<SdDrawDocument*>(pModel)->GetUndoManager() : 0; + const bool bUndo = pUndoManager && pUndoManager->isInListAction() && rPage.IsInserted(); + + SdrObject* pNewObj = pSourceObj; + if((eObjKind == PRESOBJ_OUTLINE) && (pSourceObj->GetObjIdentifier() == OBJ_TEXT) ) + { + pNewObj = rPage.CreatePresObj(PRESOBJ_OUTLINE, bVertical, aRect); + + // Text des Untertitels in das PRESOBJ_OUTLINE setzen + OutlinerParaObject* pOutlParaObj = pSourceObj->GetOutlinerParaObject(); + + if(pOutlParaObj) + { + // Text umsetzen + ::sd::Outliner* pOutl = pModel->GetInternalOutliner( TRUE ); + pOutl->Clear(); + pOutl->SetText( *pOutlParaObj ); + pOutlParaObj = pOutl->CreateParaObject(); + pNewObj->SetOutlinerParaObject( pOutlParaObj ); + pOutl->Clear(); + pNewObj->SetEmptyPresObj(FALSE); + + for (USHORT nLevel = 1; nLevel < 10; nLevel++) + { + // Neue Vorlage zuweisen + String aName(rPage.GetLayoutName()); + aName += sal_Unicode( ' ' ); + aName += String::CreateFromInt32( nLevel ); + SfxStyleSheet* pSheet = static_cast<SfxStyleSheet*>( pModel->GetStyleSheetPool()->Find(aName, SD_STYLE_FAMILY_MASTERPAGE) ); + + if (pSheet) + { + if (nLevel == 1) + { + SfxStyleSheet* pSubtitleSheet = rPage.GetStyleSheetForPresObj(PRESOBJ_TEXT); + + if (pSubtitleSheet) + pOutlParaObj->ChangeStyleSheetName(SD_STYLE_FAMILY_MASTERPAGE, pSubtitleSheet->GetName(), pSheet->GetName()); + } + + pNewObj->StartListening(*pSheet); + } + } + + // LRSpace-Item loeschen + SfxItemSet aSet(pModel->GetPool(), EE_PARA_LRSPACE, EE_PARA_LRSPACE ); + + aSet.Put(pNewObj->GetMergedItemSet()); + + aSet.ClearItem(EE_PARA_LRSPACE); + + pNewObj->SetMergedItemSet(aSet); + + if( bUndo ) + pUndoManager->AddUndoAction( pModel->GetSdrUndoFactory().CreateUndoDeleteObject(*pSourceObj) ); + + // Remove outline shape from page + rPage.RemoveObject( pSourceObj->GetOrdNum() ); + + if( !bUndo ) + SdrObject::Free( pSourceObj ); + } + } + else if((eObjKind == PRESOBJ_TEXT) && (pSourceObj->GetObjIdentifier() == OBJ_OUTLINETEXT) ) + { + // is there an outline shape we can use to replace empty subtitle shape? + pNewObj = rPage.CreatePresObj(PRESOBJ_TEXT, bVertical, aRect); + + // Text des Gliederungsobjekts in das PRESOBJ_TITLE setzen + OutlinerParaObject* pOutlParaObj = pSourceObj->GetOutlinerParaObject(); + + if(pOutlParaObj) + { + // Text umsetzen + ::sd::Outliner* pOutl = pModel->GetInternalOutliner(); + pOutl->Clear(); + pOutl->SetText( *pOutlParaObj ); + pOutlParaObj = pOutl->CreateParaObject(); + pNewObj->SetOutlinerParaObject( pOutlParaObj ); + pOutl->Clear(); + pNewObj->SetEmptyPresObj(FALSE); + + // Linken Einzug zuruecksetzen + SfxItemSet aSet(pModel->GetPool(), EE_PARA_LRSPACE, EE_PARA_LRSPACE ); + + aSet.Put(pNewObj->GetMergedItemSet()); + + const SvxLRSpaceItem& rLRItem = (const SvxLRSpaceItem&) aSet.Get(EE_PARA_LRSPACE); + SvxLRSpaceItem aNewLRItem(rLRItem); + aNewLRItem.SetTxtLeft(0); + aSet.Put(aNewLRItem); + + pNewObj->SetMergedItemSet(aSet); + + SfxStyleSheet* pSheet = rPage.GetStyleSheetForPresObj(PRESOBJ_TEXT); + if (pSheet) + pNewObj->SetStyleSheet(pSheet, TRUE); + + // Remove subtitle shape from page + if( bUndo ) + pUndoManager->AddUndoAction(pModel->GetSdrUndoFactory().CreateUndoDeleteObject(*pSourceObj)); + + rPage.RemoveObject( pSourceObj->GetOrdNum() ); + + if( !bUndo ) + SdrObject::Free( pSourceObj ); + } + } + else if((eObjKind == PRESOBJ_OUTLINE) && (pSourceObj->GetObjIdentifier() != OBJ_OUTLINETEXT) ) + { + switch( pSourceObj->GetObjIdentifier() ) + { + case OBJ_TABLE: eObjKind = PRESOBJ_TABLE; break; + case OBJ_MEDIA: eObjKind = PRESOBJ_MEDIA; break; + case OBJ_GRAF: eObjKind = PRESOBJ_GRAPHIC; break; + case OBJ_OLE2: eObjKind = PRESOBJ_OBJECT; break; + } + } + + return pNewObj; +} + +/** reuses or creates a presentation shape for an auto layout that fits the given parameter + + @param eObjKind + The kind of presentation shape we like to have + @param nIndex + If > 1 we skip the first nIndex-1 shapes with the presentation shape kind eObjKind while + looking for an existing presentation shape + @param bVertical + If true, the shape is created vertical if bInit is true + @param aRect + The rectangle that should be used to transform the shape + @param bInit + If true the shape is created if not found + @returns + A presentation shape that was either found or created with the given parameters +*/ +SdrObject* SdPage::InsertAutoLayoutShape( SdrObject* pObj, PresObjKind eObjKind, bool bVertical, Rectangle aRect, bool bInit ) +{ + sd::UndoManager* pUndoManager = pModel ? static_cast<SdDrawDocument*>(pModel)->GetUndoManager() : 0; + const bool bUndo = pUndoManager && pUndoManager->isInListAction() && IsInserted(); + + if (!pObj && bInit) + { + pObj = CreatePresObj(eObjKind, bVertical, aRect); + } + else if ( pObj && (pObj->GetUserCall() || bInit) ) + { + // convert object if shape type does not match kind (f.e. converting outline text to subtitle text) + if( bInit ) + pObj = convertPresentationObjectImpl( *this, pObj, eObjKind, bVertical, aRect ); + + if( bUndo ) + { + pUndoManager->AddUndoAction( pModel->GetSdrUndoFactory().CreateUndoGeoObject( *pObj ) ); + pUndoManager->AddUndoAction( pModel->GetSdrUndoFactory().CreateUndoAttrObject( *pObj, TRUE, TRUE ) ); + pUndoManager->AddUndoAction( new UndoObjectUserCall( *pObj ) ); + } + + ( /*(SdrGrafObj*)*/ pObj)->AdjustToMaxRect( aRect ); + + pObj->SetUserCall(this); + + SdrTextObj* pTextObject = dynamic_cast< SdrTextObj* >(pObj); + if( pTextObject ) + { + if( pTextObject->IsVerticalWriting() != (bVertical ? sal_True : sal_False) ) + { + pTextObject->SetVerticalWriting( bVertical ); + + // #94826# here make sure the correct anchoring is used when the object + // is re-used but orientation is changed + if(PRESOBJ_OUTLINE == eObjKind) + pTextObject->SetMergedItem(SdrTextHorzAdjustItem( bVertical ? SDRTEXTHORZADJUST_RIGHT : SDRTEXTHORZADJUST_BLOCK )); + } + + if( !mbMaster && (pTextObject->GetObjIdentifier() != OBJ_TABLE) ) + { + if ( pTextObject->IsAutoGrowHeight() ) + { + // switch off AutoGrowHeight, set new MinHeight + SfxItemSet aTempAttr( ((SdDrawDocument*) pModel)->GetPool() ); + SdrTextMinFrameHeightItem aMinHeight( aRect.GetSize().Height() ); + aTempAttr.Put( aMinHeight ); + aTempAttr.Put( SdrTextAutoGrowHeightItem(FALSE) ); + pTextObject->SetMergedItemSet(aTempAttr); + pTextObject->SetLogicRect(aRect); + + // switch on AutoGrowHeight + SfxItemSet aAttr( ((SdDrawDocument*) pModel)->GetPool() ); + aAttr.Put( SdrTextAutoGrowHeightItem(TRUE) ); + + pTextObject->SetMergedItemSet(aAttr); + } + + if ( pTextObject->IsAutoGrowWidth() ) + { + // switch off AutoGrowWidth , set new MinWidth + SfxItemSet aTempAttr( ((SdDrawDocument*) pModel)->GetPool() ); + SdrTextMinFrameWidthItem aMinWidth( aRect.GetSize().Width() ); + aTempAttr.Put( aMinWidth ); + aTempAttr.Put( SdrTextAutoGrowWidthItem(FALSE) ); + pTextObject->SetMergedItemSet(aTempAttr); + pTextObject->SetLogicRect(aRect); + + // switch on AutoGrowWidth + SfxItemSet aAttr( ((SdDrawDocument*) pModel)->GetPool() ); + aAttr.Put( SdrTextAutoGrowWidthItem(TRUE) ); + pTextObject->SetMergedItemSet(aAttr); + } + } + } + } + + if(pObj && bInit ) + { + if( !IsPresObj( pObj ) ) + { + if( bUndo ) + pUndoManager->AddUndoAction( new UndoObjectPresentationKind( *pObj ) ); + + InsertPresObj( pObj, eObjKind ); + } + + // make adjustments for vertical title and outline shapes + if( bVertical && (( eObjKind == PRESOBJ_TITLE) || (eObjKind == PRESOBJ_OUTLINE))) + { + SfxItemSet aNewSet(pObj->GetMergedItemSet()); + aNewSet.Put( SdrTextAutoGrowWidthItem(TRUE) ); + aNewSet.Put( SdrTextAutoGrowHeightItem(FALSE) ); + if( eObjKind == PRESOBJ_OUTLINE ) + { + aNewSet.Put( SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP) ); + aNewSet.Put( SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT) ); + } + pObj->SetMergedItemSet(aNewSet); + } + } + + if ( pObj && (pObj->GetUserCall() || bInit) && ( pObj->IsEmptyPresObj() || !pObj->ISA(SdrGrafObj) ) ) + pObj->AdjustToMaxRect( aRect ); + + return pObj; +} + + +/************************************************************************* +|* +|* Liefert den PresObjKind eines Objektes zurueck +|* +\************************************************************************/ + +PresObjKind SdPage::GetPresObjKind(SdrObject* pObj) const +{ + PresObjKind eKind = PRESOBJ_NONE; + if( (pObj != 0) && (maPresentationShapeList.hasShape(*pObj)) ) + { + SdAnimationInfo* pInfo = SdDrawDocument::GetShapeUserData(*pObj); + if( pInfo ) + eKind = pInfo->mePresObjKind; + } + + return eKind; +} + +bool SdPage::IsPresObj(const SdrObject* pObj) +{ + return pObj && maPresentationShapeList.hasShape( const_cast<SdrObject&>(*pObj) ); +} + +void SdPage::RemovePresObj(const SdrObject* pObj) +{ + if( pObj && maPresentationShapeList.hasShape(const_cast<SdrObject&>(*pObj)) ) + { + SdAnimationInfo* pInfo = SdDrawDocument::GetShapeUserData(const_cast<SdrObject&>(*pObj)); + if( pInfo ) + pInfo->mePresObjKind = PRESOBJ_NONE; + maPresentationShapeList.removeShape(const_cast<SdrObject&>(*pObj)); + } +} + +void SdPage::InsertPresObj(SdrObject* pObj, PresObjKind eKind ) +{ + DBG_ASSERT( pObj, "sd::SdPage::InsertPresObj(), invalid presentation object inserted!" ); + DBG_ASSERT( !IsPresObj(pObj), "sd::SdPage::InsertPresObj(), presentation object inserted twice!" ); + if( pObj ) + { + SdAnimationInfo* pInfo = SdDrawDocument::GetShapeUserData(*pObj, true); + if( pInfo ) + pInfo->mePresObjKind = eKind; + maPresentationShapeList.addShape(*pObj); + } +} + +/************************************************************************* +|* +|* Text des Objektes setzen +|* +\************************************************************************/ + +void SdPage::SetObjText(SdrTextObj* pObj, SdrOutliner* pOutliner, PresObjKind eObjKind, const String& rString ) +{ + if ( pObj ) + { + DBG_ASSERT( pObj->ISA(SdrTextObj), "SetObjText: Kein SdrTextObj!" ); + ::Outliner* pOutl = pOutliner; + + if (!pOutliner) + { + SfxItemPool* pPool = ((SdDrawDocument*) GetModel())->GetDrawOutliner().GetEmptyItemSet().GetPool(); + pOutl = new ::Outliner( pPool, OUTLINERMODE_OUTLINEOBJECT ); + pOutl->SetRefDevice( SD_MOD()->GetRefDevice( *( (SdDrawDocument*) GetModel() )->GetDocSh() ) ); + pOutl->SetEditTextObjectPool(pPool); + pOutl->SetStyleSheetPool((SfxStyleSheetPool*)GetModel()->GetStyleSheetPool()); + pOutl->EnableUndo(FALSE); + pOutl->SetUpdateMode( FALSE ); + } + + USHORT nOutlMode = pOutl->GetMode(); + Size aPaperSize = pOutl->GetPaperSize(); + BOOL bUpdateMode = pOutl->GetUpdateMode(); + pOutl->SetUpdateMode(FALSE); + pOutl->SetParaAttribs( 0, pOutl->GetEmptyItemSet() ); + + // #95114# Always set the object's StyleSheet at the Outliner to + // use the current objects StyleSheet. Thus it's the same as in + // SetText(...). + // #95114# Moved this implementation from where SetObjText(...) was called + // to inside this method to work even when outliner is fetched here. + pOutl->SetStyleSheet(0, pObj->GetStyleSheet()); + + String aString; + + switch( eObjKind ) + { + case PRESOBJ_OUTLINE: + { + pOutl->Init( OUTLINERMODE_OUTLINEOBJECT ); + + aString += sal_Unicode( '\t' ); + aString += rString; + + if (mbMaster) + { + pOutl->SetStyleSheet( 0, GetStyleSheetForPresObj(eObjKind) ); + aString += String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\n\t\t" )); + aString += String ( SdResId( STR_PRESOBJ_MPOUTLLAYER2 ) ); + + aString += String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\n\t\t\t" )); + aString += String ( SdResId( STR_PRESOBJ_MPOUTLLAYER3 ) ); + + aString += String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\n\t\t\t\t" )); + aString += String ( SdResId( STR_PRESOBJ_MPOUTLLAYER4 ) ); + + aString += String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\n\t\t\t\t\t" )); + aString += String ( SdResId( STR_PRESOBJ_MPOUTLLAYER5 ) ); + + aString += String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\n\t\t\t\t\t\t" )); + aString += String ( SdResId( STR_PRESOBJ_MPOUTLLAYER6 ) ); + + aString += String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\n\t\t\t\t\t\t\t" )); + aString += String ( SdResId( STR_PRESOBJ_MPOUTLLAYER7 ) ); + + aString += String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\n\t\t\t\t\t\t\t\t" )); + aString += String ( SdResId( STR_PRESOBJ_MPOUTLLAYER8 ) ); + + aString += String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "\n\t\t\t\t\t\t\t\t\t" )); + aString += String ( SdResId( STR_PRESOBJ_MPOUTLLAYER9 ) ); + } + } + break; + + case PRESOBJ_TITLE: + { + pOutl->Init( OUTLINERMODE_TITLEOBJECT ); + aString += rString; + } + break; + + default: + { + pOutl->Init( OUTLINERMODE_TEXTOBJECT ); + aString += rString; + + // check if we need to add a text field + SvxFieldData* pData = NULL; + + switch( eObjKind ) + { + case PRESOBJ_HEADER: + pData = new SvxHeaderField(); + break; + case PRESOBJ_FOOTER: + pData = new SvxFooterField(); + break; + case PRESOBJ_SLIDENUMBER: + pData = new SvxPageField(); + break; + case PRESOBJ_DATETIME: + pData = new SvxDateTimeField(); + break; + default: + break; + } + + if( pData ) + { + ESelection e; + SvxFieldItem aField( *pData, EE_FEATURE_FIELD ); + pOutl->QuickInsertField(aField,e); + delete pData; + } + } + break; + } + + pOutl->SetPaperSize( pObj->GetLogicRect().GetSize() ); + + if( aString.Len() ) + pOutl->SetText( aString, pOutl->GetParagraph( 0 ) ); + + ( (SdrTextObj*) pObj)->SetOutlinerParaObject( pOutl->CreateParaObject() ); + + if (!pOutliner) + { + delete pOutl; + pOutl = NULL; + } + else + { + // Outliner restaurieren + pOutl->Init( nOutlMode ); + pOutl->SetParaAttribs( 0, pOutl->GetEmptyItemSet() ); + pOutl->SetUpdateMode( bUpdateMode ); + pOutl->SetPaperSize( aPaperSize ); + } + } +} + +/************************************************************************* +|* +|* Link & Daten von einem VControl empfangen +|* +\************************************************************************/ + +void SdPage::SetLinkData(const String&, const String& ) +{ +} + +/************************************************************************* +|* +|* Layoutname setzen +|* +\************************************************************************/ +void SdPage::SetLayoutName(String aName) +{ + maLayoutName = aName; + + if( mbMaster ) + { + String aSep( RTL_CONSTASCII_USTRINGPARAM(SD_LT_SEPARATOR) ); + USHORT nPos = maLayoutName.Search( aSep ); + if ( nPos != STRING_NOTFOUND ) + { + FmFormPage::SetName(maLayoutName.Copy(0, nPos)); + } + } +} + + +/************************************************************************* +|* +|* Seitenname zurueckgeben und ggf. generieren +|* +\************************************************************************/ + +const String& SdPage::GetName() const +{ + String aCreatedPageName( maCreatedPageName ); + if (GetRealName().Len() == 0) + { + if ((mePageKind == PK_STANDARD || mePageKind == PK_NOTES) && !mbMaster) + { + // default name for handout pages + USHORT nNum = (GetPageNum() + 1) / 2; + + aCreatedPageName = String(SdResId(STR_PAGE)); + aCreatedPageName += sal_Unicode( ' ' ); + if( GetModel()->GetPageNumType() == SVX_NUMBER_NONE ) + { + // if the document has number none as a formating + // for page numbers we still default to arabic numbering + // to keep the default page names unique + aCreatedPageName += String::CreateFromInt32( (sal_Int32)nNum ); + } + else + { + aCreatedPageName += ((SdDrawDocument*) GetModel())->CreatePageNumValue(nNum); + } + } + else + { + /****************************************************************** + * Defaultname fuer Handzettelseiten + ******************************************************************/ + aCreatedPageName = String(SdResId(STR_LAYOUT_DEFAULT_NAME)); + } + } + else + { + aCreatedPageName = GetRealName(); + } + + if (mePageKind == PK_NOTES) + { + aCreatedPageName += sal_Unicode( ' ' ); + aCreatedPageName += String(SdResId(STR_NOTES)); + } + else if (mePageKind == PK_HANDOUT && mbMaster) + { + aCreatedPageName += String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( " (" )); + aCreatedPageName += String(SdResId(STR_HANDOUT)); + aCreatedPageName += sal_Unicode( ')' ); + } + + const_cast< SdPage* >(this)->maCreatedPageName = aCreatedPageName; + return maCreatedPageName; +} + +void SdPage::SetOrientation( Orientation eOrient) +{ + meOrientation = eOrient; +} + +Orientation SdPage::GetOrientation() const +{ + return meOrientation; +} + +/************************************************************************* +|* +|* Liefert den Default-Text eines PresObjektes zurueck +|* +\************************************************************************/ + +String SdPage::GetPresObjText(PresObjKind eObjKind) const +{ + String aString; + + if (eObjKind == PRESOBJ_TITLE) + { + if (mbMaster) + { + if (mePageKind != PK_NOTES) + { + aString = String ( SdResId( STR_PRESOBJ_MPTITLE ) ); + } + else + { + aString = String ( SdResId( STR_PRESOBJ_MPNOTESTITLE ) ); + } + } + else + { + aString = String ( SdResId( STR_PRESOBJ_TITLE ) ); + } + } + else if (eObjKind == PRESOBJ_OUTLINE) + { + if (mbMaster) + { + aString = String ( SdResId( STR_PRESOBJ_MPOUTLINE ) ); + } + else + { + aString = String ( SdResId( STR_PRESOBJ_OUTLINE ) ); + } + } + else if (eObjKind == PRESOBJ_NOTES) + { + if (mbMaster) + { + aString = String ( SdResId( STR_PRESOBJ_MPNOTESTEXT ) ); + } + else + { + aString = String ( SdResId( STR_PRESOBJ_NOTESTEXT ) ); + } + } + else if (eObjKind == PRESOBJ_TEXT) + { + aString = String ( SdResId( STR_PRESOBJ_TEXT ) ); + } + else if (eObjKind == PRESOBJ_GRAPHIC) + { + aString = String ( SdResId( STR_PRESOBJ_GRAPHIC ) ); + } + else if (eObjKind == PRESOBJ_OBJECT) + { + aString = String ( SdResId( STR_PRESOBJ_OBJECT ) ); + } + else if (eObjKind == PRESOBJ_CHART) + { + aString = String ( SdResId( STR_PRESOBJ_CHART ) ); + } + else if (eObjKind == PRESOBJ_ORGCHART) + { + aString = String ( SdResId( STR_PRESOBJ_ORGCHART ) ); + } + else if (eObjKind == PRESOBJ_CALC) + { + aString = String ( SdResId( STR_PRESOBJ_TABLE ) ); + } + + return(aString); +} + +extern uno::Reference< uno::XInterface > createUnoPageImpl( SdPage* pPage ); + +uno::Reference< uno::XInterface > SdPage::createUnoPage() +{ + return createUnoPageImpl( this ); +} + +/** returns the SdPage implementation for the given XDrawPage or 0 if not available */ +SdPage* SdPage::getImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& xPage ) +{ + try + { + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xUnoTunnel( xPage, ::com::sun::star::uno::UNO_QUERY ); + if( xUnoTunnel.is() ) + { + SvxDrawPage* pUnoPage = reinterpret_cast<SvxDrawPage*>(sal::static_int_cast<sal_uIntPtr>(xUnoTunnel->getSomething( SvxDrawPage::getUnoTunnelId()) ) ); + if( pUnoPage ) + return static_cast< SdPage* >( pUnoPage->GetSdrPage() ); + } + } + catch( ::com::sun::star::uno::Exception& e ) + { + (void)e; + DBG_ERROR("sd::SdPage::getImplementation(), exception cathced!" ); + } + + return 0; +} + +void SdPage::SetName (const String& rName) +{ + String aOldName = GetName(); + FmFormPage::SetName (rName); + static_cast<SdDrawDocument*>(pModel)->UpdatePageRelativeURLs(aOldName, rName); + ActionChanged(); +} + +const HeaderFooterSettings& SdPage::getHeaderFooterSettings() const +{ + if( mePageKind == PK_HANDOUT && !mbMaster ) + { + return (((SdPage&)TRG_GetMasterPage()).maHeaderFooterSettings); + } + else + { + return maHeaderFooterSettings; + } +} + +void SdPage::setHeaderFooterSettings( const sd::HeaderFooterSettings& rNewSettings ) +{ + if( mePageKind == PK_HANDOUT && !mbMaster ) + { + (((SdPage&)TRG_GetMasterPage()).maHeaderFooterSettings) = rNewSettings; + } + else + { + maHeaderFooterSettings = rNewSettings; + } + + SetChanged(); + if(TRG_HasMasterPage()) + { + TRG_GetMasterPageDescriptorViewContact().ActionChanged(); + } +} + +bool SdPage::checkVisibility( + const sdr::contact::ViewObjectContact& rOriginal, + const sdr::contact::DisplayInfo& rDisplayInfo, + bool bEdit ) +{ + if( !FmFormPage::checkVisibility( rOriginal, rDisplayInfo, bEdit ) ) + return false; + + SdrObject* pObj = rOriginal.GetViewContact().TryToGetSdrObject(); + if( pObj == NULL ) + return false; + + const SdrPage* pVisualizedPage = GetSdrPageFromXDrawPage(rOriginal.GetObjectContact().getViewInformation2D().getVisualizedPage()); + const bool bIsPrinting(rOriginal.GetObjectContact().isOutputToPrinter() || rOriginal.GetObjectContact().isOutputToPDFFile()); + const SdrPageView* pPageView = rOriginal.GetObjectContact().TryToGetSdrPageView(); + const bool bIsInsidePageObj(pPageView && pPageView->GetPage() != pVisualizedPage); + + // empty presentation objects only visible during edit mode + if( (bIsPrinting || !bEdit || bIsInsidePageObj ) && pObj->IsEmptyPresObj() ) + { + if( (pObj->GetObjInventor() != SdrInventor) || ( (pObj->GetObjIdentifier() != OBJ_RECT) && (pObj->GetObjIdentifier() != OBJ_PAGE) ) ) + return false; + } + + if( ( pObj->GetObjInventor() == SdrInventor ) && ( pObj->GetObjIdentifier() == OBJ_TEXT ) ) + { + const SdPage* pCheckPage = dynamic_cast< const SdPage* >(pObj->GetPage()); + + if( pCheckPage ) + { + PresObjKind eKind = pCheckPage->GetPresObjKind(pObj); + + if((eKind == PRESOBJ_FOOTER) || (eKind == PRESOBJ_HEADER) || (eKind == PRESOBJ_DATETIME) || (eKind == PRESOBJ_SLIDENUMBER) ) + { + const bool bSubContentProcessing(rDisplayInfo.GetSubContentActive()); + + if( bSubContentProcessing || ( pCheckPage->GetPageKind() == PK_HANDOUT && bIsPrinting ) ) + { + // use the page that is currently processed + const SdPage* pVisualizedSdPage = dynamic_cast< const SdPage* >(pVisualizedPage); + + if( pVisualizedSdPage ) + { + // if we are not on a masterpage, see if we have to draw this header&footer object at all + const sd::HeaderFooterSettings& rSettings = pVisualizedSdPage->getHeaderFooterSettings(); + + switch( eKind ) + { + case PRESOBJ_FOOTER: + return rSettings.mbFooterVisible; + case PRESOBJ_HEADER: + return rSettings.mbHeaderVisible; + case PRESOBJ_DATETIME: + return rSettings.mbDateTimeVisible; + case PRESOBJ_SLIDENUMBER: + return rSettings.mbSlideNumberVisible; + default: + break; + } + } + } + } // check for placeholders on master + else if( (eKind != PRESOBJ_NONE) && pCheckPage->IsMasterPage() && ( pVisualizedPage != pCheckPage ) ) + { + // presentation objects on master slide are always invisible if slide is shown. + return false; + } + } + } + + // i63977, do not print SdrpageObjs from master pages + if( ( pObj->GetObjInventor() == SdrInventor ) && ( pObj->GetObjIdentifier() == OBJ_PAGE ) ) + { + if( pObj->GetPage() && pObj->GetPage()->IsMasterPage() ) + return false; + } + + return true; +} + +bool SdPage::RestoreDefaultText( SdrObject* pObj ) +{ + bool bRet = false; + + SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( pObj ); + + if( pTextObj ) + { + PresObjKind ePresObjKind = GetPresObjKind(pTextObj); + + if (ePresObjKind == PRESOBJ_TITLE || + ePresObjKind == PRESOBJ_OUTLINE || + ePresObjKind == PRESOBJ_NOTES || + ePresObjKind == PRESOBJ_TEXT) + { + String aString( GetPresObjText(ePresObjKind) ); + + if (aString.Len()) + { + BOOL bVertical = FALSE; + OutlinerParaObject* pOldPara = pTextObj->GetOutlinerParaObject(); + if( pOldPara ) + bVertical = pOldPara->IsVertical(); // is old para object vertical? + + SetObjText( pTextObj, 0, ePresObjKind, aString ); + + if( pOldPara ) + { + // #94826# Here, only the vertical flag for the + // OutlinerParaObjects needs to be changed. The + // AutoGrowWidth/Height items still exist in the + // not changed object. + if(pTextObj + && pTextObj->GetOutlinerParaObject() + && pTextObj->GetOutlinerParaObject()->IsVertical() != (bool)bVertical) + { + Rectangle aObjectRect = pTextObj->GetSnapRect(); + pTextObj->GetOutlinerParaObject()->SetVertical(bVertical); + pTextObj->SetSnapRect(aObjectRect); + } + } + + pTextObj->SetTextEditOutliner( NULL ); // to make stylesheet settings work + pTextObj->NbcSetStyleSheet( GetStyleSheetForPresObj(ePresObjKind), TRUE ); + pTextObj->SetEmptyPresObj(TRUE); + bRet = true; + } + } + } + return bRet; +} + +void SdPage::CalculateHandoutAreas( SdDrawDocument& rModel, AutoLayout eLayout, bool bHorizontal, std::vector< Rectangle >& rAreas ) +{ + SdPage& rHandoutMaster = *rModel.GetMasterSdPage( 0, PK_HANDOUT ); + + if( eLayout == AUTOLAYOUT_NONE ) + { + // use layout from handout master + SdrObjListIter aShapeIter (rHandoutMaster); + while (aShapeIter.IsMore()) + { + SdrPageObj* pPageObj = dynamic_cast<SdrPageObj*>(aShapeIter.Next()); + if (pPageObj) + rAreas.push_back( pPageObj->GetCurrentBoundRect() ); + } + } + else + { + Size aArea = rHandoutMaster.GetSize(); + + const long nGapW = 1000; // gap is 1cm + const long nGapH = 1000; + + long nLeftBorder = rHandoutMaster.GetLftBorder(); + long nRightBorder = rHandoutMaster.GetRgtBorder(); + long nTopBorder = rHandoutMaster.GetUppBorder(); + long nBottomBorder = rHandoutMaster.GetLwrBorder(); + + const long nHeaderFooterHeight = static_cast< long >( (aArea.Height() - nTopBorder - nLeftBorder) * 0.05 ); + + nTopBorder += nHeaderFooterHeight; + nBottomBorder += nHeaderFooterHeight; + + long nX = nGapW + nLeftBorder; + long nY = nGapH + nTopBorder; + + aArea.Width() -= nGapW * 2 + nLeftBorder + nRightBorder; + aArea.Height() -= nGapH * 2 + nTopBorder + nBottomBorder; + + const bool bLandscape = aArea.Width() > aArea.Height(); + + static sal_uInt16 aOffsets[5][9] = + { + { 0, 1, 2, 3, 4, 5, 6, 7, 8 }, // AUTOLAYOUT_HANDOUT9, Portrait, Horizontal order + { 0, 2, 4, 1, 3, 5, 0, 0, 0 }, // AUTOLAYOUT_HANDOUT3, Landscape, Vertical + { 0, 2, 1, 3, 0, 0, 0, 0, 0 }, // AUTOLAYOUT_HANDOUT4, Landscape, Vertical + { 0, 3, 1, 4, 2, 5, 0, 0, 0 }, // AUTOLAYOUT_HANDOUT4, Portrait, Vertical + { 0, 3, 6, 1, 4, 7, 2, 5, 8 }, // AUTOLAYOUT_HANDOUT9, Landscape, Vertical + }; + + sal_uInt16* pOffsets = aOffsets[0]; + USHORT nColCnt = 0, nRowCnt = 0; + switch ( eLayout ) + { + case AUTOLAYOUT_HANDOUT1: + nColCnt = 1; nRowCnt = 1; + break; + + case AUTOLAYOUT_HANDOUT2: + if( bLandscape ) + { + nColCnt = 2; nRowCnt = 1; + } + else + { + nColCnt = 1; nRowCnt = 2; + } + break; + + case AUTOLAYOUT_HANDOUT3: + if( bLandscape ) + { + nColCnt = 3; nRowCnt = 2; + } + else + { + nColCnt = 2; nRowCnt = 3; + } + pOffsets = aOffsets[ bLandscape ? 1 : 0 ]; + break; + + case AUTOLAYOUT_HANDOUT4: + nColCnt = 2; nRowCnt = 2; + pOffsets = aOffsets[ bHorizontal ? 0 : 2 ]; + break; + + case AUTOLAYOUT_HANDOUT6: + if( bLandscape ) + { + nColCnt = 3; nRowCnt = 2; + } + else + { + nColCnt = 2; nRowCnt = 3; + } + if( !bHorizontal ) + pOffsets = aOffsets[ bLandscape ? 1 : 3 ]; + break; + + default: + case AUTOLAYOUT_HANDOUT9: + nColCnt = 3; nRowCnt = 3; + + if( !bHorizontal ) + pOffsets = aOffsets[4]; + break; + } + + rAreas.resize( nColCnt * nRowCnt ); + + Size aPartArea, aSize; + aPartArea.Width() = ((aArea.Width() - ((nColCnt-1) * nGapW) ) / nColCnt); + aPartArea.Height() = ((aArea.Height() - ((nRowCnt-1) * nGapH) ) / nRowCnt); + + SdrPage* pFirstPage = rModel.GetMasterSdPage(0, PK_STANDARD); + if ( pFirstPage ) + { + // scale actual size into handout rect + double fScale = (double)aPartArea.Width() / (double)pFirstPage->GetWdt(); + + aSize.Height() = (long)(fScale * pFirstPage->GetHgt() ); + if( aSize.Height() > aPartArea.Height() ) + { + fScale = (double)aPartArea.Height() / (double)pFirstPage->GetHgt(); + aSize.Height() = aPartArea.Height(); + aSize.Width() = (long)(fScale * pFirstPage->GetWdt()); + } + else + { + aSize.Width() = aPartArea.Width(); + } + + nX += (aPartArea.Width() - aSize.Width()) / 2; + nY += (aPartArea.Height()- aSize.Height())/ 2; + } + else + { + aSize = aPartArea; + } + + Point aPos( nX, nY ); + + const bool bRTL = rModel.GetDefaultWritingMode() == ::com::sun::star::text::WritingMode_RL_TB; + + const long nOffsetX = (aPartArea.Width() + nGapW) * (bRTL ? -1 : 1); + const long nOffsetY = aPartArea.Height() + nGapH; + const long nStartX = bRTL ? nOffsetX*(1 - nColCnt) - nX : nX; + + for(sal_uInt16 nRow = 0; nRow < nRowCnt; nRow++) + { + aPos.X() = nStartX; + for(sal_uInt16 nCol = 0; nCol < nColCnt; nCol++) + { + rAreas[*pOffsets++] = Rectangle(aPos, aSize); + aPos.X() += nOffsetX; + } + + aPos.Y() += nOffsetY; + } + } +} + + + + +void SdPage::SetPrecious (const bool bIsPrecious) +{ + mbIsPrecious = bIsPrecious; +} + + + + +bool SdPage::IsPrecious (void) const +{ + return mbIsPrecious; +} + + + + +HeaderFooterSettings::HeaderFooterSettings() +{ + mbHeaderVisible = true; + mbFooterVisible = true; + mbSlideNumberVisible = false; + mbDateTimeVisible = true; + mbDateTimeIsFixed = true; + meDateTimeFormat = SVXDATEFORMAT_A; +} + +bool HeaderFooterSettings::operator==( const HeaderFooterSettings& rSettings ) const +{ + return (mbHeaderVisible == rSettings.mbHeaderVisible) && + (maHeaderText == rSettings.maHeaderText) && + (mbFooterVisible == rSettings.mbFooterVisible) && + (maFooterText == rSettings.maFooterText) && + (mbSlideNumberVisible == rSettings.mbSlideNumberVisible) && + (mbDateTimeVisible == rSettings.mbDateTimeVisible) && + (mbDateTimeIsFixed == rSettings.mbDateTimeIsFixed) && + (meDateTimeFormat == rSettings.meDateTimeFormat) && + (maDateTimeText == rSettings.maDateTimeText); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/sdpage2.cxx b/sd/source/core/sdpage2.cxx new file mode 100644 index 000000000000..0afbca62c771 --- /dev/null +++ b/sd/source/core/sdpage2.cxx @@ -0,0 +1,647 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <sfx2/docfile.hxx> +#include <vcl/svapp.hxx> +#include <editeng/outliner.hxx> +#include <sfx2/linkmgr.hxx> +#include <svx/svdotext.hxx> +#include <tools/urlobj.hxx> +#include <editeng/outlobj.hxx> +#include <svl/urihelper.hxx> +#include <editeng/xmlcnitm.hxx> +#include <svx/svditer.hxx> +#include <tools/list.hxx> + +#include "sdresid.hxx" +#include "sdpage.hxx" +#include "glob.hxx" +#include "glob.hrc" +#include "drawdoc.hxx" +#include "stlpool.hxx" +#include "pglink.hxx" +#include "anminfo.hxx" + +#include "../ui/inc/strings.hrc" +#include "../ui/inc/DrawDocShell.hxx" + +// #90477# +#include <tools/tenccvt.hxx> +#include <svl/itemset.hxx> + +using namespace ::sd; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::office; + +extern void NotifyDocumentEvent( SdDrawDocument* pDocument, const rtl::OUString& rEventName, const Reference< XInterface >& xSource ); + +/************************************************************************* +|* +|* SetPresentationLayout, setzt: Layoutnamen, Masterpage-Verknpfung und +|* Vorlagen fuer Praesentationsobjekte +|* +|* Vorraussetzungen: - Die Seite muss bereits das richtige Model kennen! +|* - Die entsprechende Masterpage muss bereits im Model sein. +|* - Die entsprechenden StyleSheets muessen bereits im +|* im StyleSheetPool sein. +|* +|* bReplaceStyleSheets = TRUE : Benannte StyleSheets werden ausgetauscht +|* FALSE: Alle StyleSheets werden neu zugewiesen +|* +|* bSetMasterPage = TRUE : MasterPage suchen und zuweisen +|* +|* bReverseOrder = FALSE: MasterPages von vorn nach hinten suchen +|* TRUE : MasterPages von hinten nach vorn suchen (fuer Undo-Action) +|* +\************************************************************************/ + +void SdPage::SetPresentationLayout(const String& rLayoutName, + BOOL bReplaceStyleSheets, + BOOL bSetMasterPage, + BOOL bReverseOrder) +{ + /********************************************************************* + |* Layoutname der Seite + \********************************************************************/ + String aOldLayoutName(maLayoutName); // merken + maLayoutName = rLayoutName; + maLayoutName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( SD_LT_SEPARATOR )); + maLayoutName += String(SdResId(STR_LAYOUT_OUTLINE)); + + /********************************************************************* + |* ggf. Masterpage suchen und setzen + \********************************************************************/ + if (bSetMasterPage && !IsMasterPage()) + { + SdPage* pMaster; + SdPage* pFoundMaster = 0; + USHORT nMaster = 0; + USHORT nMasterCount = pModel->GetMasterPageCount(); + + if( !bReverseOrder ) + { + for ( nMaster = 0; nMaster < nMasterCount; nMaster++ ) + { + pMaster = static_cast<SdPage*>(pModel->GetMasterPage(nMaster)); + if (pMaster->GetPageKind() == mePageKind && pMaster->GetLayoutName() == maLayoutName) + { + pFoundMaster = pMaster; + break; + } + } + } + else + { + for ( nMaster = nMasterCount; nMaster > 0; nMaster-- ) + { + pMaster = static_cast<SdPage*>(pModel->GetMasterPage(nMaster - 1)); + if (pMaster->GetPageKind() == mePageKind && pMaster->GetLayoutName() == maLayoutName) + { + pFoundMaster = pMaster; + break; + } + } + } + + DBG_ASSERT(pFoundMaster, "Masterpage for presentation layout not found!"); + + // this should never happen, but we play failsafe here + if( pFoundMaster == 0 ) + pFoundMaster = static_cast< SdDrawDocument *>(pModel)->GetSdPage( 0, mePageKind ); + + if( pFoundMaster ) + TRG_SetMasterPage(*pFoundMaster); + } + + /********************************************************************* + |* Vorlagen fuer Praesentationsobjekte + \********************************************************************/ + // Listen mit: + // - Vorlagenzeigern fuer Gliederungstextobjekt (alte und neue Vorlagen) + // -Replacedaten fuer OutlinerParaObject + List aOutlineStyles; + List aOldOutlineStyles; + List aReplList; + BOOL bListsFilled = FALSE; + + ULONG nObjCount = GetObjCount(); + + for (ULONG nObj = 0; nObj < nObjCount; nObj++) + { + SdrTextObj* pObj = (SdrTextObj*) GetObj(nObj); + + if (pObj->GetObjInventor() == SdrInventor && + pObj->GetObjIdentifier() == OBJ_OUTLINETEXT) + { + if (!bListsFilled || !bReplaceStyleSheets) + { + String aFullName; + String aOldFullName; + SfxStyleSheetBase* pSheet = NULL; + SfxStyleSheetBasePool* pStShPool = pModel->GetStyleSheetPool(); + + for (sal_Int16 i = -1; i < 9; i++) + { + aFullName = maLayoutName; + aOldFullName = aOldLayoutName; + aFullName += sal_Unicode( ' ' ); + aFullName += String::CreateFromInt32( (sal_Int32) (i <= 0 ) ? 1 : i + 1); + aOldFullName += sal_Unicode( ' ' ); + aOldFullName += String::CreateFromInt32( (sal_Int32) (i <= 0 ) ? 1 : i + 1 ); + + pSheet = pStShPool->Find(aOldFullName, SD_STYLE_FAMILY_MASTERPAGE); + DBG_ASSERT(pSheet, "alte Gliederungsvorlage nicht gefunden"); + aOldOutlineStyles.Insert(pSheet, LIST_APPEND); + + pSheet = pStShPool->Find(aFullName, SD_STYLE_FAMILY_MASTERPAGE); + DBG_ASSERT(pSheet, "neue Gliederungsvorlage nicht gefunden"); + aOutlineStyles.Insert(pSheet, LIST_APPEND); + + if (bReplaceStyleSheets && pSheet) + { + // Replace anstatt Set + StyleReplaceData* pReplData = new StyleReplaceData; + pReplData->nNewFamily = pSheet->GetFamily(); + pReplData->nFamily = pSheet->GetFamily(); + pReplData->aNewName = aFullName; + pReplData->aName = aOldFullName; + aReplList.Insert(pReplData, LIST_APPEND); + } + else + { + OutlinerParaObject* pOPO = ((SdrTextObj*)pObj)->GetOutlinerParaObject(); + + if( pOPO ) + pOPO->SetStyleSheets( i, aFullName, SD_STYLE_FAMILY_MASTERPAGE ); + } + } + + bListsFilled = TRUE; + } + + SfxStyleSheet* pSheet = (SfxStyleSheet*)aOutlineStyles.First(); + SfxStyleSheet* pOldSheet = (SfxStyleSheet*)aOldOutlineStyles.First(); + while (pSheet) + { + if (pSheet != pOldSheet) + { + pObj->EndListening(*pOldSheet); + + if (!pObj->IsListening(*pSheet)) + pObj->StartListening(*pSheet); + } + + pSheet = (SfxStyleSheet*)aOutlineStyles.Next(); + pOldSheet = (SfxStyleSheet*)aOldOutlineStyles.Next(); + } + + OutlinerParaObject* pOPO = ((SdrTextObj*)pObj)->GetOutlinerParaObject(); + if ( bReplaceStyleSheets && pOPO ) + { + StyleReplaceData* pReplData = (StyleReplaceData*) aReplList.First(); + + while( pReplData ) + { + pOPO->ChangeStyleSheets( pReplData->aName, pReplData->nFamily, pReplData->aNewName, pReplData->nNewFamily ); + pReplData = (StyleReplaceData*) aReplList.Next(); + } + } + } + else if (pObj->GetObjInventor() == SdrInventor && + pObj->GetObjIdentifier() == OBJ_TITLETEXT) + { + // PresObjKind nicht ueber GetPresObjKind() holen, da dort nur + // die PresObjListe beruecksichtigt wird. Es sollen aber alle + // "Titelobjekte" hier beruecksichtigt werden (Paste aus Clipboard usw.) + SfxStyleSheet* pSheet = GetStyleSheetForPresObj(PRESOBJ_TITLE); + + if (pSheet) + pObj->SetStyleSheet(pSheet, TRUE); + } + else + { + SfxStyleSheet* pSheet = GetStyleSheetForPresObj(GetPresObjKind(pObj)); + + if (pSheet) + pObj->SetStyleSheet(pSheet, TRUE); + } + } + + for (ULONG i = 0; i < aReplList.Count(); i++) + { + delete (StyleReplaceData*) aReplList.GetObject(i); + } +} + + +/************************************************************************* +|* +|* das Gliederungstextobjekt bei den Vorlagen fuer die Gliederungsebenen +|* abmelden +|* +\************************************************************************/ + +void SdPage::EndListenOutlineText() +{ + SdrObject* pOutlineTextObj = GetPresObj(PRESOBJ_OUTLINE); + + if (pOutlineTextObj) + { + SdStyleSheetPool* pSPool = (SdStyleSheetPool*)pModel->GetStyleSheetPool(); + DBG_ASSERT(pSPool, "StyleSheetPool nicht gefunden"); + String aTrueLayoutName(maLayoutName); + aTrueLayoutName.Erase( aTrueLayoutName.SearchAscii( SD_LT_SEPARATOR )); + List* pOutlineStyles = pSPool->CreateOutlineSheetList(aTrueLayoutName); + for (SfxStyleSheet* pSheet = (SfxStyleSheet*)pOutlineStyles->First(); + pSheet; + pSheet = (SfxStyleSheet*)pOutlineStyles->Next()) + { + pOutlineTextObj->EndListening(*pSheet); + } + + delete pOutlineStyles; + } +} + +/************************************************************************* +|* +|* Neues Model setzen +|* +\************************************************************************/ + +void SdPage::SetModel(SdrModel* pNewModel) +{ + DisconnectLink(); + + // Model umsetzen + FmFormPage::SetModel(pNewModel); + + ConnectLink(); +} + +/************************************************************************* +|* +|* Ist die Seite read-only? +|* +\************************************************************************/ + +bool SdPage::IsReadOnly() const +{ + return false; +} + +/************************************************************************* +|* +|* Beim sfx2::LinkManager anmelden +|* +\************************************************************************/ + +void SdPage::ConnectLink() +{ + sfx2::LinkManager* pLinkManager = pModel!=NULL ? pModel->GetLinkManager() : NULL; + + if (pLinkManager && !mpPageLink && maFileName.Len() && maBookmarkName.Len() && + mePageKind==PK_STANDARD && !IsMasterPage() && + ( (SdDrawDocument*) pModel)->IsNewOrLoadCompleted()) + { + /********************************************************************** + * Anmelden + * Nur Standardseiten duerfen gelinkt sein + **********************************************************************/ + ::sd::DrawDocShell* pDocSh = ((SdDrawDocument*) pModel)->GetDocSh(); + + if (!pDocSh || pDocSh->GetMedium()->GetOrigURL() != maFileName) + { + // Keine Links auf Dokument-eigene Seiten! + mpPageLink = new SdPageLink(this, maFileName, maBookmarkName); + String aFilterName(SdResId(STR_IMPRESS)); + pLinkManager->InsertFileLink(*mpPageLink, OBJECT_CLIENT_FILE, + maFileName, &aFilterName, &maBookmarkName); + mpPageLink->Connect(); + } + } +} + + +/************************************************************************* +|* +|* Beim sfx2::LinkManager abmelden +|* +\************************************************************************/ + +void SdPage::DisconnectLink() +{ + sfx2::LinkManager* pLinkManager = pModel!=NULL ? pModel->GetLinkManager() : NULL; + + if (pLinkManager && mpPageLink) + { + /********************************************************************** + * Abmelden + * (Bei Remove wird *pGraphicLink implizit deleted) + **********************************************************************/ + pLinkManager->Remove(mpPageLink); + mpPageLink=NULL; + } +} + +/************************************************************************* +|* +|* Copy-Ctor +|* +\************************************************************************/ + +SdPage::SdPage(const SdPage& rSrcPage) +: FmFormPage(rSrcPage) +, SdrObjUserCall() +, mpItems(NULL) +{ + mePageKind = rSrcPage.mePageKind; + meAutoLayout = rSrcPage.meAutoLayout; + + SdrObject* pObj = 0; + while((pObj = rSrcPage.maPresentationShapeList.getNextShape(pObj)) != 0) + InsertPresObj(GetObj(pObj->GetOrdNum()), rSrcPage.GetPresObjKind(pObj)); + + mbSelected = FALSE; + mnTransitionType = rSrcPage.mnTransitionType; + mnTransitionSubtype = rSrcPage.mnTransitionSubtype; + mbTransitionDirection = rSrcPage.mbTransitionDirection; + mnTransitionFadeColor = rSrcPage.mnTransitionFadeColor; + mfTransitionDuration = rSrcPage.mfTransitionDuration; + mePresChange = rSrcPage.mePresChange; + mnTime = rSrcPage.mnTime; + mbSoundOn = rSrcPage.mbSoundOn; + mbExcluded = rSrcPage.mbExcluded; + + maLayoutName = rSrcPage.maLayoutName; + maSoundFile = rSrcPage.maSoundFile; + mbLoopSound = rSrcPage.mbLoopSound; + mbStopSound = rSrcPage.mbStopSound; + maCreatedPageName = String(); + maFileName = rSrcPage.maFileName; + maBookmarkName = rSrcPage.maBookmarkName; + mbScaleObjects = rSrcPage.mbScaleObjects; + mbBackgroundFullSize = rSrcPage.mbBackgroundFullSize; + meCharSet = rSrcPage.meCharSet; + mnPaperBin = rSrcPage.mnPaperBin; + meOrientation = rSrcPage.meOrientation; + + // header footer + setHeaderFooterSettings( rSrcPage.getHeaderFooterSettings() ); + + mpPageLink = NULL; // Wird beim Einfuegen ueber ConnectLink() gesetzt +} + + + +/************************************************************************* +|* +|* Clone +|* +\************************************************************************/ + +SdrPage* SdPage::Clone() const +{ + return Clone(NULL); +} + +SdrPage* SdPage::Clone(SdrModel* pNewModel) const +{ + DBG_ASSERT( pNewModel == 0, "sd::SdPage::Clone(), new page ignored, please check code! CL" ); + (void)pNewModel; + + SdPage* pNewPage = new SdPage(*this); + + cloneAnimations( *pNewPage ); + + // fix user calls for duplicated slide + SdrObjListIter aSourceIter( *this, IM_DEEPWITHGROUPS ); + SdrObjListIter aTargetIter( *pNewPage, IM_DEEPWITHGROUPS ); + + while( aSourceIter.IsMore() && aTargetIter.IsMore() ) + { + SdrObject* pSource = aSourceIter.Next(); + SdrObject* pTarget = aTargetIter.Next(); + + if( pSource->GetUserCall() ) + pTarget->SetUserCall( pNewPage ); + } + + return pNewPage; +} + +/************************************************************************* +|* +|* GetTextStyleSheetForObject +|* +\************************************************************************/ + + +SfxStyleSheet* SdPage::GetTextStyleSheetForObject( SdrObject* pObj ) const +{ + const PresObjKind eKind = ((SdPage*)this)->GetPresObjKind(pObj); + if( eKind != PRESOBJ_NONE ) + { + return ((SdPage*)this)->GetStyleSheetForPresObj(eKind); + } + + return FmFormPage::GetTextStyleSheetForObject( pObj ); +} + +SfxItemSet* SdPage::getOrCreateItems() +{ + if( mpItems == NULL ) + mpItems = new SfxItemSet( pModel->GetItemPool(), SDRATTR_XMLATTRIBUTES, SDRATTR_XMLATTRIBUTES ); + + return mpItems; +} + + +sal_Bool SdPage::setAlienAttributes( const com::sun::star::uno::Any& rAttributes ) +{ + SfxItemSet* pSet = getOrCreateItems(); + + SvXMLAttrContainerItem aAlienAttributes( SDRATTR_XMLATTRIBUTES ); + if( aAlienAttributes.PutValue( rAttributes, 0 ) ) + { + pSet->Put( aAlienAttributes ); + return sal_True; + } + + return sal_False; +} + +void SdPage::getAlienAttributes( com::sun::star::uno::Any& rAttributes ) +{ + const SfxPoolItem* pItem; + + if( (mpItems == NULL) || ( SFX_ITEM_SET != mpItems->GetItemState( SDRATTR_XMLATTRIBUTES, sal_False, &pItem ) ) ) + { + SvXMLAttrContainerItem aAlienAttributes; + aAlienAttributes.QueryValue( rAttributes, 0 ); + } + else + { + ((SvXMLAttrContainerItem*)pItem)->QueryValue( rAttributes, 0 ); + } +} + +void SdPage::RemoveEmptyPresentationObjects() +{ + SdrObjListIter aShapeIter( *this, IM_DEEPWITHGROUPS ); + + SdrObject* pShape; + for( pShape = aShapeIter.Next(); pShape; pShape = aShapeIter.Next() ) + { + if( pShape && pShape->IsEmptyPresObj() ) + { + RemoveObject( pShape->GetOrdNum() ); + SdrObject::Free( pShape ); + } + + } +} + +sal_Int16 SdPage::getTransitionType (void) const +{ + return mnTransitionType; +} + +void SdPage::setTransitionType( sal_Int16 nTransitionType ) +{ + mnTransitionType = nTransitionType; + ActionChanged(); +} + +sal_Int16 SdPage::getTransitionSubtype (void) const +{ + return mnTransitionSubtype; +} + +void SdPage::setTransitionSubtype ( sal_Int16 nTransitionSubtype ) +{ + mnTransitionSubtype = nTransitionSubtype; + ActionChanged(); +} + +sal_Bool SdPage::getTransitionDirection (void) const +{ + return mbTransitionDirection; +} + +void SdPage::setTransitionDirection ( sal_Bool bTransitionbDirection ) +{ + mbTransitionDirection = bTransitionbDirection; + ActionChanged(); +} + +sal_Int32 SdPage::getTransitionFadeColor (void) const +{ + return mnTransitionFadeColor; +} + +void SdPage::setTransitionFadeColor ( sal_Int32 nTransitionFadeColor ) +{ + mnTransitionFadeColor = nTransitionFadeColor; + ActionChanged(); +} + +double SdPage::getTransitionDuration (void) const +{ + return mfTransitionDuration; +} + +void SdPage::setTransitionDuration ( double fTranstionDuration ) +{ + mfTransitionDuration = fTranstionDuration; + ActionChanged(); +} + +namespace sd { +extern void createAnnotation( Reference< XAnnotation >& xAnnotation, SdPage* pPage ); +extern SdrUndoAction* CreateUndoInsertOrRemoveAnnotation( const Reference< XAnnotation >& xAnnotation, bool bInsert ); +} + +void SdPage::createAnnotation( ::com::sun::star::uno::Reference< ::com::sun::star::office::XAnnotation >& xAnnotation ) +{ + sd::createAnnotation( xAnnotation, this ); +} + +void SdPage::addAnnotation( const Reference< XAnnotation >& xAnnotation, int nIndex ) +{ + if( (nIndex == -1) || (nIndex > (int)maAnnotations.size()) ) + { + maAnnotations.push_back( xAnnotation ); + } + else + { + maAnnotations.insert( maAnnotations.begin() + nIndex, xAnnotation ); + } + + if( pModel && pModel->IsUndoEnabled() ) + { + SdrUndoAction* pAction = CreateUndoInsertOrRemoveAnnotation( xAnnotation, true ); + if( pAction ) + pModel->AddUndo( pAction ); + } + + SetChanged(); + + if( pModel ) + { + pModel->SetChanged(); + Reference< XInterface > xSource( xAnnotation, UNO_QUERY ); + NotifyDocumentEvent( static_cast< SdDrawDocument* >( pModel ), rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnAnnotationInserted" ) ), xSource ); + } +} + +void SdPage::removeAnnotation( const Reference< XAnnotation >& xAnnotation ) +{ + if( pModel && pModel->IsUndoEnabled() ) + { + SdrUndoAction* pAction = CreateUndoInsertOrRemoveAnnotation( xAnnotation, false ); + if( pAction ) + pModel->AddUndo( pAction ); + } + + AnnotationVector::iterator iter = std::find( maAnnotations.begin(), maAnnotations.end(), xAnnotation ); + if( iter != maAnnotations.end() ) + maAnnotations.erase( iter ); + + if( pModel ) + { + pModel->SetChanged(); + Reference< XInterface > xSource( xAnnotation, UNO_QUERY ); + NotifyDocumentEvent( static_cast< SdDrawDocument* >( pModel ), rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnAnnotationRemoved" ) ), xSource ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/sdpage_animations.cxx b/sd/source/core/sdpage_animations.cxx new file mode 100644 index 000000000000..e40de790cc99 --- /dev/null +++ b/sd/source/core/sdpage_animations.cxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <com/sun/star/presentation/ParagraphTarget.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/presentation/EffectNodeType.hpp> +#include <comphelper/processfactory.hxx> +#include <osl/mutex.hxx> +#include <editeng/outliner.hxx> +#include "CustomAnimationCloner.hxx" +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include <CustomAnimationPreset.hxx> +#include <TransitionPreset.hxx> +#include "undoanim.hxx" +#include "EffectMigration.hxx" + +using ::rtl::OUString; +using namespace ::sd; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::animations; +using namespace ::com::sun::star::presentation; + +using ::com::sun::star::drawing::XShape; + +/** returns a helper class to manipulate effects inside the main sequence */ +sd::MainSequencePtr SdPage::getMainSequence() +{ + if( 0 == mpMainSequence.get() ) + mpMainSequence.reset( new sd::MainSequence( getAnimationNode() ) ); + + return mpMainSequence; +} + +/** returns the main animation node */ +Reference< XAnimationNode > SdPage::getAnimationNode() throw (RuntimeException) +{ + if( !mxAnimationNode.is() ) + { + mxAnimationNode = Reference< XAnimationNode >::query(::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.ParallelTimeContainer")))); + if( mxAnimationNode.is() ) + { + Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 ); + aUserData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) ); + aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT; + mxAnimationNode->setUserData( aUserData ); + } + } + + return mxAnimationNode; +} + +void SdPage::setAnimationNode( Reference< XAnimationNode >& xNode ) throw (RuntimeException) +{ + mxAnimationNode = xNode; + if( mpMainSequence.get() ) + mpMainSequence->reset( xNode ); +} + +/** removes all custom animations for the given shape */ +void SdPage::removeAnimations( const SdrObject* pObj ) +{ + if( mxAnimationNode.is() ) + { + getMainSequence(); + + Reference< XShape > xShape( const_cast<SdrObject*>(pObj)->getUnoShape(), UNO_QUERY ); + + if( mpMainSequence->hasEffect( xShape ) ) + mpMainSequence->disposeShape( xShape ); + } +} + +bool SdPage::hasAnimationNode() const +{ + return mxAnimationNode.is(); +} + +void SdPage::SetFadeEffect(::com::sun::star::presentation::FadeEffect eNewEffect) +{ + EffectMigration::SetFadeEffect( this, eNewEffect ); +} + +FadeEffect SdPage::GetFadeEffect() const +{ + return EffectMigration::GetFadeEffect( this ); +} + +/** callback from the sd::View when a new paragraph for one object on this page is created */ +void SdPage::onParagraphInserted( ::Outliner* pOutliner, Paragraph* pPara, SdrObject* pObj ) +{ + if( mxAnimationNode.is() ) + { + ParagraphTarget aTarget; + aTarget.Shape = Reference< XShape >( pObj->getUnoShape(), UNO_QUERY ); + aTarget.Paragraph = (sal_Int16)pOutliner->GetAbsPos( pPara ); + + getMainSequence()->insertTextRange( makeAny( aTarget ) ); + } +} + +/** callback from the sd::View when a paragraph from one object on this page is removed */ +void SdPage::onParagraphRemoving( ::Outliner* pOutliner, Paragraph* pPara, SdrObject* pObj ) +{ + if( mxAnimationNode.is() ) + { + ParagraphTarget aTarget; + aTarget.Shape = Reference< XShape >( pObj->getUnoShape(), UNO_QUERY ); + aTarget.Paragraph = (sal_Int16)pOutliner->GetAbsPos( pPara ); + + getMainSequence()->disposeTextRange( makeAny( aTarget ) ); + } +} + +/** callback from the sd::View when an object just left text edit mode */ +void SdPage::onEndTextEdit( SdrObject* pObj ) +{ + if( pObj && mxAnimationNode.is() ) + { + Reference< XShape > xObj( pObj->getUnoShape(), UNO_QUERY ); + getMainSequence()->onTextChanged( xObj ); + } +} + +void SdPage::cloneAnimations( SdPage& rTargetPage ) const +{ + if( mxAnimationNode.is() ) + { + Reference< XAnimationNode > xClonedNode( + ::sd::Clone( mxAnimationNode, this, &rTargetPage ) ); + + if( xClonedNode.is() ) + rTargetPage.setAnimationNode( xClonedNode ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/shapelist.cxx b/sd/source/core/shapelist.cxx new file mode 100644 index 000000000000..09b9a5e5bc3c --- /dev/null +++ b/sd/source/core/shapelist.cxx @@ -0,0 +1,216 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <tools/debug.hxx> +#include <svx/svdobj.hxx> +#include "shapelist.hxx" + +#include <algorithm> + +using namespace sd; + +ShapeList::ShapeList() +{ + maIter = maShapeList.end(); +} + +ShapeList::~ShapeList() +{ + clear(); +} + +/** adds the given shape to this list */ +void ShapeList::addShape( SdrObject& rObject ) +{ + ListImpl::iterator aIter( std::find( maShapeList.begin(), maShapeList.end(), &rObject ) ); + if( aIter == maShapeList.end() ) + { + maShapeList.push_back(&rObject); + rObject.AddObjectUser( *this ); + } + else + { + DBG_ERROR("sd::ShapeList::addShape(), given shape already part of list!"); + } +} + +/** removes the given shape from this list */ +SdrObject* ShapeList::removeShape( SdrObject& rObject ) +{ + ListImpl::iterator aIter( std::find( maShapeList.begin(), maShapeList.end(), &rObject ) ); + if( aIter != maShapeList.end() ) + { + bool bIterErased = aIter == maIter; + + (*aIter)->RemoveObjectUser(*this); + aIter = maShapeList.erase( aIter ); + + if( bIterErased ) + maIter = aIter; + + if( aIter != maShapeList.end() ) + return (*aIter); + } + else + { + DBG_ERROR("sd::ShapeList::removeShape(), given shape not part of list!"); + } + return 0; +} + +void ShapeList::replaceShape( SdrObject& rOldObject, SdrObject& rNewObject ) +{ + if( &rOldObject == &rNewObject ) + return; + + ListImpl::iterator aIter( std::find( maShapeList.begin(), maShapeList.end(), &rNewObject ) ); + if( aIter != maShapeList.end() ) + { + bool bIterErased = aIter == maIter; + (*aIter)->RemoveObjectUser(*this); + aIter = maShapeList.erase( aIter ); + + if( bIterErased ) + maIter = aIter; + } + + aIter = std::find( maShapeList.begin(), maShapeList.end(), &rOldObject ); + if( aIter != maShapeList.end() ) + { + bool bIterErased = aIter == maIter; + + ListImpl::iterator iNew( maShapeList.insert( aIter, &rNewObject ) ); + + (*aIter)->RemoveObjectUser(*this); + aIter = maShapeList.erase( aIter ); + + rNewObject.AddObjectUser( *this ); + + if( bIterErased ) + maIter = iNew; + } + else + { + DBG_ERROR("sd::ShapeList::replaceShape(), given shape not part of list!"); + addShape( rNewObject ); + } +} + +/** removes all shapes from this list + NOTE: iterators will become invalid */ +void ShapeList::clear() +{ + ListImpl aShapeList; + aShapeList.swap( maShapeList ); + + ListImpl::iterator aIter( aShapeList.begin() ); + while( aIter != aShapeList.end() ) + (*aIter++)->RemoveObjectUser(*this); + + maIter = aShapeList.end(); +} + +/** returns true if this list is empty */ +bool ShapeList::isEmpty() const +{ + return maShapeList.empty(); +} + +/** returns true if given shape is part of this list */ +bool ShapeList::hasShape( SdrObject& rObject ) const +{ + return std::find( maShapeList.begin(), maShapeList.end(), &rObject ) != maShapeList.end(); +} + +SdrObject* ShapeList::getNextShape(SdrObject* pObj) const +{ + if( pObj ) + { + ListImpl::const_iterator aIter( std::find( maShapeList.begin(), maShapeList.end(), pObj ) ); + if( aIter != maShapeList.end() ) + { + aIter++; + if( aIter != maShapeList.end() ) + { + return (*aIter); + } + } + } + else if( !maShapeList.empty() ) + { + return (*maShapeList.begin()); + } + + return 0; +} + +void ShapeList::ObjectInDestruction(const SdrObject& rObject) +{ + ListImpl::iterator aIter( std::find( maShapeList.begin(), maShapeList.end(), &rObject ) ); + if( aIter != maShapeList.end() ) + { + bool bIterErased = aIter == maIter; + + aIter = maShapeList.erase( aIter ); + + if( bIterErased ) + maIter = aIter; + } + else + { + DBG_ERROR("sd::ShapeList::ObjectInDestruction(), got a call from an unknown friend!"); + } +} + +SdrObject* ShapeList::getNextShape() +{ + if( maIter != maShapeList.end() ) + { + return (*maIter++); + } + else + { + return 0; + } +} + +void ShapeList::seekShape( sal_uInt32 nIndex ) +{ + maIter = maShapeList.begin(); + while( nIndex-- && (maIter != maShapeList.end()) ) + maIter++; +} + +bool ShapeList::hasMore() const +{ + return maIter != maShapeList.end(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/stlfamily.cxx b/sd/source/core/stlfamily.cxx new file mode 100644 index 000000000000..be75d6f6cc9e --- /dev/null +++ b/sd/source/core/stlfamily.cxx @@ -0,0 +1,602 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/IllegalAccessException.hpp> +#include <comphelper/serviceinfohelper.hxx> + +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> + +#include <svl/style.hxx> + +#include <svx/unoprov.hxx> + +#include "../ui/inc/strings.hrc" +#include "stlfamily.hxx" +#include "stlsheet.hxx" +#include "sdresid.hxx" +#include "drawdoc.hxx" +#include "sdpage.hxx" +#include "glob.hxx" + +#include <map> + +using ::rtl::OUString; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::beans; + +// ---------------------------------------------------------- + +typedef std::map< rtl::OUString, rtl::Reference< SdStyleSheet > > PresStyleMap; + +struct SdStyleFamilyImpl +{ + SdrPageWeakRef mxMasterPage; + String maLayoutName; + + PresStyleMap& getStyleSheets(); + rtl::Reference< SfxStyleSheetPool > mxPool; + +private: + PresStyleMap maStyleSheets; +}; + +PresStyleMap& SdStyleFamilyImpl::getStyleSheets() +{ + if( mxMasterPage.is() && (mxMasterPage->GetLayoutName() != maLayoutName) ) + { + maLayoutName = mxMasterPage->GetLayoutName(); + + String aLayoutName( maLayoutName ); + const sal_uInt16 nLen = aLayoutName.Search(String( RTL_CONSTASCII_USTRINGPARAM(SD_LT_SEPARATOR)))+4; + aLayoutName.Erase( nLen ); + + if( (maStyleSheets.size() == 0) || !((*maStyleSheets.begin()).second->GetName().Equals( aLayoutName, 0, nLen )) ) + { + maStyleSheets.clear(); + + const SfxStyles& rStyles = mxPool->GetStyles(); + for( SfxStyles::const_iterator iter( rStyles.begin() ); iter != rStyles.end(); ++iter ) + { + SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( (*iter).get() ); + if( pStyle && (pStyle->GetFamily() == SD_STYLE_FAMILY_MASTERPAGE) && (pStyle->GetName().Equals( aLayoutName, 0, nLen )) ) + maStyleSheets[ pStyle->GetApiName() ] = rtl::Reference< SdStyleSheet >( pStyle ); + } + } + } + + return maStyleSheets; +} + +// ---------------------------------------------------------- + +SdStyleFamily::SdStyleFamily( const rtl::Reference< SfxStyleSheetPool >& xPool, SfxStyleFamily nFamily ) +: mnFamily( nFamily ) +, mxPool( xPool ) +, mpImpl( 0 ) +{ +} + +// ---------------------------------------------------------- + +SdStyleFamily::SdStyleFamily( const rtl::Reference< SfxStyleSheetPool >& xPool, const SdPage* pMasterPage ) +: mnFamily( SD_STYLE_FAMILY_MASTERPAGE ) +, mxPool( xPool ) +, mpImpl( new SdStyleFamilyImpl() ) +{ + mpImpl->mxMasterPage.reset( const_cast< SdPage* >( pMasterPage ) ); + mpImpl->mxPool = xPool; +} + +// ---------------------------------------------------------- + +SdStyleFamily::~SdStyleFamily() +{ + DBG_ASSERT( !mxPool.is(), "SdStyleFamily::~SdStyleFamily(), dispose me first!" ); + delete mpImpl; +} + +// ---------------------------------------------------------- + +void SdStyleFamily::throwIfDisposed() const throw(RuntimeException) +{ + if( !mxPool.is() ) + throw DisposedException(); +} + +// ---------------------------------------------------------- + +SdStyleSheet* SdStyleFamily::GetValidNewSheet( const Any& rElement ) throw(IllegalArgumentException) +{ + Reference< XStyle > xStyle( rElement, UNO_QUERY ); + SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( xStyle.get() ); + + if( pStyle == 0 || (pStyle->GetFamily() != mnFamily) || (&pStyle->GetPool() != mxPool.get()) || (mxPool->Find( pStyle->GetName(), mnFamily) != 0) ) + throw IllegalArgumentException(); + + return pStyle; +} + +// ---------------------------------------------------------- + +SdStyleSheet* SdStyleFamily::GetSheetByName( const OUString& rName ) throw(NoSuchElementException, WrappedTargetException ) +{ + SdStyleSheet* pRet = 0; + if( rName.getLength() ) + { + if( mnFamily == SD_STYLE_FAMILY_MASTERPAGE ) + { + PresStyleMap& rStyleMap = mpImpl->getStyleSheets(); + PresStyleMap::iterator iter( rStyleMap.find(rName) ); + if( iter != rStyleMap.end() ) + pRet = (*iter).second.get(); + } + else + { + const SfxStyles& rStyles = mxPool->GetStyles(); + for( SfxStyles::const_iterator iter( rStyles.begin() ); iter != rStyles.end(); ++iter ) + { + SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( (*iter).get() ); + if( pStyle && (pStyle->GetFamily() == mnFamily) && (pStyle->GetApiName() == rName) ) + { + pRet = pStyle; + break; + } + } + } + } + if( pRet ) + return pRet; + + throw NoSuchElementException(); +} + +// ---------------------------------------------------------- +// XServiceInfo +// ---------------------------------------------------------- + +OUString SAL_CALL SdStyleFamily::getImplementationName() throw(RuntimeException) +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM("SdStyleFamily") ); +} + +// ---------------------------------------------------------- + +sal_Bool SAL_CALL SdStyleFamily::supportsService( const OUString& ServiceName ) throw(RuntimeException) +{ + return comphelper::ServiceInfoHelper::supportsService( ServiceName, getSupportedServiceNames() ); +} + +// ---------------------------------------------------------- + +Sequence< OUString > SAL_CALL SdStyleFamily::getSupportedServiceNames() throw(RuntimeException) +{ + OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.style.StyleFamily") ); + Sequence< OUString > aSeq( &aServiceName, 1 ); + return aSeq; +} + +// ---------------------------------------------------------- +// XNamed +// ---------------------------------------------------------- + +OUString SAL_CALL SdStyleFamily::getName() throw (RuntimeException) +{ + if( mnFamily == SD_STYLE_FAMILY_MASTERPAGE ) + { + SdPage* pPage = static_cast< SdPage* >( mpImpl->mxMasterPage.get() ); + if( pPage == 0 ) + throw DisposedException(); + + String aLayoutName( pPage->GetLayoutName() ); + const String aSep( RTL_CONSTASCII_USTRINGPARAM( SD_LT_SEPARATOR )); + aLayoutName.Erase(aLayoutName.Search(aSep)); + + return OUString( aLayoutName ); + } + else + { + return SdStyleSheet::GetFamilyString( mnFamily ); + } +} + +// ---------------------------------------------------------- + +void SAL_CALL SdStyleFamily::setName( const ::rtl::OUString& ) throw (RuntimeException) +{ +} + +// ---------------------------------------------------------- +// XNameAccess +// ---------------------------------------------------------- + +Any SAL_CALL SdStyleFamily::getByName( const OUString& rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + return Any( Reference< XStyle >( static_cast<SfxUnoStyleSheet*>(GetSheetByName( rName )) ) ); +} + +// ---------------------------------------------------------- + +Sequence< OUString > SAL_CALL SdStyleFamily::getElementNames() throw(RuntimeException) +{ + SolarMutexGuard aGuard; + + throwIfDisposed(); + + if( mnFamily == SD_STYLE_FAMILY_MASTERPAGE ) + { + PresStyleMap& rStyleMap = mpImpl->getStyleSheets(); + Sequence< OUString > aNames( rStyleMap.size() ); + + PresStyleMap::iterator iter( rStyleMap.begin() ); + OUString* pNames = aNames.getArray(); + while( iter != rStyleMap.end() ) + { + const OUString sName( (*iter).first ); + rtl::Reference< SdStyleSheet > xStyle( (*iter++).second ); + if( xStyle.is() ) + { + *pNames++ = xStyle->GetApiName(); + } + else + { + int i = 0; + i++; + } + } + + return aNames; + } + else + { + std::vector< OUString > aNames; + const SfxStyles& rStyles = mxPool->GetStyles(); + for( SfxStyles::const_iterator iter( rStyles.begin() ); iter != rStyles.end(); ++iter ) + { + SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( (*iter).get() ); + if( pStyle && (pStyle->GetFamily() == mnFamily) ) + aNames.push_back( pStyle->GetApiName() ); + } + return Sequence< OUString >( &(*aNames.begin()), aNames.size() ); + } +} + +// ---------------------------------------------------------- + +sal_Bool SAL_CALL SdStyleFamily::hasByName( const OUString& aName ) throw(RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if( aName.getLength() ) + { + if( mnFamily == SD_STYLE_FAMILY_MASTERPAGE ) + { + PresStyleMap& rStyleSheets = mpImpl->getStyleSheets(); + PresStyleMap::iterator iter( rStyleSheets.find(aName) ); + return ( iter != rStyleSheets.end() ) ? sal_True : sal_False; + } + else + { + const SfxStyles& rStyles = mxPool->GetStyles(); + for( SfxStyles::const_iterator iter( rStyles.begin() ); iter != rStyles.end(); ++iter ) + { + SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( (*iter).get() ); + if( pStyle && (pStyle->GetFamily() == mnFamily) && ( pStyle->GetApiName() == aName ) ) + return sal_True; + } + } + } + + return sal_False; +} + +// ---------------------------------------------------------- +// XElementAccess +// ---------------------------------------------------------- + +Type SAL_CALL SdStyleFamily::getElementType() throw(RuntimeException) +{ + return XStyle::static_type(); +} + +// ---------------------------------------------------------- + +sal_Bool SAL_CALL SdStyleFamily::hasElements() throw(RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if( mnFamily == SD_STYLE_FAMILY_MASTERPAGE ) + { + return sal_True; + } + else + { + const SfxStyles& rStyles = mxPool->GetStyles(); + for( SfxStyles::const_iterator iter( rStyles.begin() ); iter != rStyles.end(); ++iter ) + { + SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( (*iter).get() ); + if( pStyle && (pStyle->GetFamily() == mnFamily) ) + return sal_True; + } + } + + return sal_False; +} + +// ---------------------------------------------------------- +// XIndexAccess +// ---------------------------------------------------------- + +sal_Int32 SAL_CALL SdStyleFamily::getCount() throw(RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + sal_Int32 nCount = 0; + if( mnFamily == SD_STYLE_FAMILY_MASTERPAGE ) + { + return mpImpl->getStyleSheets().size(); + } + else + { + const SfxStyles& rStyles = mxPool->GetStyles(); + for( SfxStyles::const_iterator iter( rStyles.begin() ); iter != rStyles.end(); ++iter ) + { + SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( (*iter).get() ); + if( pStyle && (pStyle->GetFamily() == mnFamily) ) + nCount++; + } + } + + return nCount; +} + +// ---------------------------------------------------------- + +Any SAL_CALL SdStyleFamily::getByIndex( sal_Int32 Index ) throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if( Index >= 0 ) + { + if( mnFamily == SD_STYLE_FAMILY_MASTERPAGE ) + { + PresStyleMap& rStyleSheets = mpImpl->getStyleSheets(); + if( !rStyleSheets.empty() ) + { + PresStyleMap::iterator iter( rStyleSheets.begin() ); + while( Index-- && (iter != rStyleSheets.end()) ) + ++iter; + + if( (Index==-1) && (iter != rStyleSheets.end()) ) + return Any( Reference< XStyle >( (*iter).second.get() ) ); + } + } + else + { + const SfxStyles& rStyles = mxPool->GetStyles(); + for( SfxStyles::const_iterator iter( rStyles.begin() ); iter != rStyles.end(); ++iter ) + { + SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( (*iter).get() ); + if( pStyle && (pStyle->GetFamily() == mnFamily) ) + { + if( Index-- == 0 ) + return Any( Reference< XStyle >( pStyle ) ); + } + } + } + } + + throw IndexOutOfBoundsException(); +} + +// ---------------------------------------------------------- +// XNameContainer +// ---------------------------------------------------------- + +void SAL_CALL SdStyleFamily::insertByName( const OUString& rName, const Any& rElement ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if(rName.getLength() == 0) + throw IllegalArgumentException(); + + SdStyleSheet* pStyle = GetValidNewSheet( rElement ); + if( !pStyle->SetName( rName ) ) + throw ElementExistException(); + + pStyle->SetApiName( rName ); + mxPool->Insert( pStyle ); +} + +// ---------------------------------------------------------- + +void SAL_CALL SdStyleFamily::removeByName( const OUString& rName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + SdStyleSheet* pStyle = GetSheetByName( rName ); + + if( !pStyle->IsUserDefined() ) + throw WrappedTargetException(); + + mxPool->Remove( pStyle ); +} + +// ---------------------------------------------------------- +// XNameReplace +// ---------------------------------------------------------- + +void SAL_CALL SdStyleFamily::replaceByName( const OUString& rName, const Any& aElement ) throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + SdStyleSheet* pOldStyle = GetSheetByName( rName ); + SdStyleSheet* pNewStyle = GetValidNewSheet( aElement ); + + mxPool->Remove( pOldStyle ); + mxPool->Insert( pNewStyle ); +} + +// ---------------------------------------------------------- +// XSingleServiceFactory +// ---------------------------------------------------------- + +Reference< XInterface > SAL_CALL SdStyleFamily::createInstance() throw(Exception, RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if( mnFamily == SD_STYLE_FAMILY_MASTERPAGE ) + { + throw IllegalAccessException(); + } + else + { + return Reference< XInterface >( static_cast< XStyle* >( SdStyleSheet::CreateEmptyUserStyle( *mxPool.get(), mnFamily ) ) ); + } +} + +// ---------------------------------------------------------- + +Reference< XInterface > SAL_CALL SdStyleFamily::createInstanceWithArguments( const Sequence< Any >& ) throw(Exception, RuntimeException) +{ + return createInstance(); +} + +// ---------------------------------------------------------- +// XComponent +// ---------------------------------------------------------- + +void SAL_CALL SdStyleFamily::dispose( ) throw (RuntimeException) +{ + if( mxPool.is() ) + mxPool.clear(); + + if( mpImpl ) + { + delete mpImpl; + mpImpl = 0; + } +} + +// ---------------------------------------------------------- + +void SAL_CALL SdStyleFamily::addEventListener( const Reference< XEventListener >& ) throw (RuntimeException) +{ +} + +// ---------------------------------------------------------- + +void SAL_CALL SdStyleFamily::removeEventListener( const Reference< XEventListener >& ) throw (RuntimeException) +{ +} + +// ---------------------------------------------------------- +// XPropertySet +// ---------------------------------------------------------- + +Reference<XPropertySetInfo> SdStyleFamily::getPropertySetInfo() throw (RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); + return Reference<XPropertySetInfo>(); +} + +// ---------------------------------------------------------- + +void SdStyleFamily::setPropertyValue( const OUString& , const Any& ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); +} + +// ---------------------------------------------------------- + +Any SdStyleFamily::getPropertyValue( const OUString& PropertyName ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DisplayName") )) + { + SolarMutexGuard aGuard; + OUString sDisplayName; + switch( mnFamily ) + { + case SD_STYLE_FAMILY_MASTERPAGE: sDisplayName = getName(); break; + case SD_STYLE_FAMILY_CELL: sDisplayName = String( SdResId(STR_CELL_STYLE_FAMILY) ); break; + default: sDisplayName = String( SdResId(STR_GRAPHICS_STYLE_FAMILY) ); break; + } + return Any( sDisplayName ); + } + else + { + throw UnknownPropertyException( OUString( RTL_CONSTASCII_USTRINGPARAM("unknown property: ") ) + PropertyName, static_cast<OWeakObject *>(this) ); + } +} + +// ---------------------------------------------------------- + +void SdStyleFamily::addPropertyChangeListener( const OUString& , const Reference<XPropertyChangeListener>& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); +} + +// ---------------------------------------------------------- + +void SdStyleFamily::removePropertyChangeListener( const OUString& , const Reference<XPropertyChangeListener>& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); +} + +// ---------------------------------------------------------- + +void SdStyleFamily::addVetoableChangeListener( const OUString& , const Reference<XVetoableChangeListener>& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); +} + +// ---------------------------------------------------------- + +void SdStyleFamily::removeVetoableChangeListener( const OUString& , const Reference<XVetoableChangeListener>& ) throw (UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/stlpool.cxx b/sd/source/core/stlpool.cxx new file mode 100644 index 000000000000..e1b6759c893d --- /dev/null +++ b/sd/source/core/stlpool.cxx @@ -0,0 +1,1411 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include <com/sun/star/lang/DisposedException.hpp> +#include <editeng/eeitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/cntritem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/fontitem.hxx> +#include <svl/poolitem.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xlineit0.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/numitem.hxx> +#include <editeng/brshitem.hxx> +#include <editeng/editeng.hxx> +#include <svl/smplhint.hxx> +#include <editeng/langitem.hxx> +#include <editeng/charreliefitem.hxx> +#include <editeng/emphitem.hxx> +#include <svx/sdr/table/tabledesign.hxx> +#include <editeng/akrnitem.hxx> + +#include <svx/svdattr.hxx> +#include "eetext.hxx" +#include <svx/xtable.hxx> // fuer RGB_Color +#include <editeng/bulitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/adjitem.hxx> +#include <svl/itempool.hxx> + +#define _SDR_POSITIVE +#define _SDR_ITEMS + +#include "stlpool.hxx" +#include "sdresid.hxx" +#include "stlsheet.hxx" +#include "glob.hrc" +#include "glob.hxx" +#include "drawdoc.hxx" +#include "sdmod.hxx" +#include "sdpage.hxx" +#include "helpids.h" +#include <svl/itemset.hxx> + +using ::rtl::OUString; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::container; + +// ---------------------------------------------------------- + +SdStyleSheetPool::SdStyleSheetPool(SfxItemPool const& _rPool, SdDrawDocument* pDocument) +: SdStyleSheetPoolBase( _rPool ) +, mpActualStyleSheet(NULL) +, mpDoc(pDocument) +{ + if( mpDoc ) + { + rtl::Reference< SfxStyleSheetPool > xPool( this ); + + // create graphics family + mxGraphicFamily = new SdStyleFamily( xPool, SD_STYLE_FAMILY_GRAPHICS ); + mxCellFamily = new SdStyleFamily( xPool, SD_STYLE_FAMILY_CELL ); + + mxTableFamily = sdr::table::CreateTableDesignFamily(); + Reference< XNamed > xNamed( mxTableFamily, UNO_QUERY ); + if( xNamed.is() ) + msTableFamilyName = xNamed->getName(); + + // create presentation families, one for each master page + const sal_uInt16 nCount = mpDoc->GetMasterSdPageCount(PK_STANDARD); + for( sal_uInt16 nPage = 0; nPage < nCount; ++nPage ) + AddStyleFamily( mpDoc->GetMasterSdPage(nPage,PK_STANDARD) ); + + } +} + +// ---------------------------------------------------------- + +SdStyleSheetPool::~SdStyleSheetPool() +{ + DBG_ASSERT( mpDoc == NULL, "sd::SdStyleSheetPool::~SdStyleSheetPool(), dispose me first!" ); +} + +// ---------------------------------------------------------- + +SfxStyleSheetBase* SdStyleSheetPool::Create(const String& rName, SfxStyleFamily eFamily, USHORT _nMask ) +{ + return new SdStyleSheet(rName, *this, eFamily, _nMask); +} + +// ---------------------------------------------------------- + +SfxStyleSheetBase* SdStyleSheetPool::Create(const SdStyleSheet& rStyle) +{ + return new SdStyleSheet( rStyle ); +} + +// ---------------------------------------------------------- + +SfxStyleSheetBase* SdStyleSheetPool::GetTitleSheet(const String& rLayoutName) +{ + String aName(rLayoutName); + aName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( SD_LT_SEPARATOR )); + aName += String(SdResId(STR_LAYOUT_TITLE)); + SfxStyleSheetBase* pResult = Find(aName, SD_STYLE_FAMILY_MASTERPAGE); + return pResult; +} + +/************************************************************************* +|* +|* eine Liste der Gliederungstextvorlagen fuer ein Praesentationlayout +|* erstellen, der Aufrufer muss die Liste wieder loeschen +|* +\************************************************************************/ + +List* SdStyleSheetPool::CreateOutlineSheetList (const String& rLayoutName) +{ + String aName(rLayoutName); + aName.AppendAscii( RTL_CONSTASCII_STRINGPARAM( SD_LT_SEPARATOR )); + aName += String(SdResId(STR_LAYOUT_OUTLINE)); + List* pList = new List; + for (USHORT nSheet = 1; nSheet < 10; nSheet++) + { + String aFullName(aName); + aFullName.Append( sal_Unicode( ' ' )); + aFullName.Append( String::CreateFromInt32( (sal_Int32)nSheet )); + SfxStyleSheetBase* pSheet = Find(aFullName, SD_STYLE_FAMILY_MASTERPAGE); + pList->Insert(pSheet, LIST_APPEND); + } + return pList; +} + +/************************************************************************* +|* +|* StyleSheets mit Defaultweren fuer das genannte Praesentationslayout erzeugen +|* +\************************************************************************/ + +void SdStyleSheetPool::CreateLayoutStyleSheets(const String& rLayoutName, sal_Bool bCheck /*= sal_False*/ ) +{ + const sal_uInt16 nUsedMask = SFXSTYLEBIT_ALL & ~SFXSTYLEBIT_USERDEF; + + (void)bCheck; + sal_Bool bCreated = sal_False; + + SfxStyleSheetBase* pSheet = NULL; + + String aPrefix(rLayoutName); + String aSep( RTL_CONSTASCII_USTRINGPARAM( SD_LT_SEPARATOR )); + aPrefix.Insert(aSep); + + Font aLatinFont, aCJKFont, aCTLFont; + + mpDoc->getDefaultFonts( aLatinFont, aCJKFont, aCTLFont ); + + // Font fuer Titel und Gliederung + SvxFontItem aSvxFontItem( aLatinFont.GetFamily(), aLatinFont.GetName(), aLatinFont.GetStyleName(), aLatinFont.GetPitch(), + aLatinFont.GetCharSet(), EE_CHAR_FONTINFO ); + + SvxFontItem aSvxFontItemCJK( aCJKFont.GetFamily(), aCJKFont.GetName(), aCJKFont.GetStyleName(), aCJKFont.GetPitch(), + aCJKFont.GetCharSet(), EE_CHAR_FONTINFO_CJK ); + + SvxFontItem aSvxFontItemCTL( aCTLFont.GetFamily(), aCTLFont.GetName(), aCTLFont.GetStyleName(), aCTLFont.GetPitch(), + aCTLFont.GetCharSet(), EE_CHAR_FONTINFO_CTL ); + + Font aBulletFont( GetBulletFont() ); + + /************************************************************************** + * Gliederungsebenen + **************************************************************************/ + String aName(SdResId(STR_LAYOUT_OUTLINE)); + String aHelpFile; + + SfxStyleSheetBase* pParent = NULL; + SvxLRSpaceItem aSvxLRSpaceItem( EE_PARA_LRSPACE ); + SvxULSpaceItem aSvxULSpaceItem( EE_PARA_ULSPACE ); + USHORT nLevel; + + for( nLevel = 1; nLevel < 10; nLevel++) + { + String aLevelName(aName); + aLevelName.Append( sal_Unicode( ' ' )); + aLevelName.Append( String::CreateFromInt32( sal_Int32( nLevel ))); + + aLevelName.Insert(aPrefix, 0); + + if (!Find(aLevelName, SD_STYLE_FAMILY_MASTERPAGE)) + { + bCreated = sal_True; + pSheet = &Make(aLevelName, SD_STYLE_FAMILY_MASTERPAGE,nUsedMask); + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_OUTLINE + nLevel ); + + pSheet->SetParent( String() ); + + // Attributierung fuer Level 1, die anderen Ebenen "erben" + if (nLevel == 1) + { + SfxItemSet& rSet = pSheet->GetItemSet(); + + rSet.Put(aSvxFontItem); + rSet.Put(aSvxFontItemCJK); + rSet.Put(aSvxFontItemCTL); + rSet.Put( SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC ) ); + rSet.Put( SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CJK ) ); + rSet.Put( SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CTL ) ); + rSet.Put( SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT ) ); + rSet.Put( SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ) ); + rSet.Put( SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ) ); + rSet.Put( SvxUnderlineItem(UNDERLINE_NONE, EE_CHAR_UNDERLINE ) ); + rSet.Put( SvxOverlineItem(UNDERLINE_NONE, EE_CHAR_OVERLINE ) ); + rSet.Put( SvxCrossedOutItem(STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) ); + rSet.Put( SvxShadowedItem(FALSE, EE_CHAR_SHADOW ) ); + rSet.Put( SvxContourItem(FALSE, EE_CHAR_OUTLINE ) ); + rSet.Put( SvxEmphasisMarkItem(EMPHASISMARK_NONE, EE_CHAR_EMPHASISMARK ) ); + rSet.Put( SvxCharReliefItem(RELIEF_NONE, EE_CHAR_RELIEF) ); + rSet.Put( SvxColorItem( Color(COL_AUTO), EE_CHAR_COLOR) ); + rSet.Put( XLineStyleItem(XLINE_NONE) ); + rSet.Put( XFillStyleItem(XFILL_NONE) ); + rSet.Put( SdrTextFitToSizeTypeItem(SDRTEXTFIT_AUTOFIT) ); + rSet.Put( SdrTextAutoGrowHeightItem(FALSE) ); + // #i16874# enable kerning by default but only for new documents + rSet.Put( SvxAutoKernItem( TRUE, EE_CHAR_PAIRKERNING ) ); + + if( nLevel == 1 ) + { + Font f( GetBulletFont() ); + PutNumBulletItem( pSheet, f ); + } + } + + ULONG nFontSize = 20; + USHORT nLower = 100; + + switch (nLevel) + { + case 1: + { + nFontSize = 32; + nLower = 500; + } + break; + + case 2: + { + nFontSize = 28; + nLower = 400; + } + break; + + case 3: + { + nFontSize = 24; + nLower = 300; + } + break; + + case 4: + { + nLower = 200; + } + break; + } + + // FontSize + nFontSize = (USHORT)((nFontSize * 2540L) / 72); // Pt --> 1/100 mm + SfxItemSet& rOutlineSet = pSheet->GetItemSet(); + rOutlineSet.Put( SvxFontHeightItem( nFontSize, 100, EE_CHAR_FONTHEIGHT ) ); + rOutlineSet.Put( SvxFontHeightItem( nFontSize, 100, EE_CHAR_FONTHEIGHT_CJK ) ); + rOutlineSet.Put( SvxFontHeightItem( SdDrawDocument::convertFontHeightToCTL( nFontSize ), 100, EE_CHAR_FONTHEIGHT_CTL ) ); + + // Line distance (downwards). Stuff around here cleaned up in i35937 + aSvxULSpaceItem.SetLower(nLower); + pSheet->GetItemSet().Put(aSvxULSpaceItem); + } + } + + // if we created outline styles, we need to chain them + if( bCreated ) + { + pParent = NULL; + for (nLevel = 1; nLevel < 10; nLevel++) + { + String aLevelName(aName); + aLevelName.Append( sal_Unicode( ' ' )); + aLevelName.Append( String::CreateFromInt32( sal_Int32( nLevel ))); + + aLevelName.Insert(aPrefix, 0); + + pSheet = Find(aLevelName, SD_STYLE_FAMILY_MASTERPAGE); + + DBG_ASSERT( pSheet, "missing layout style!"); + + if( pSheet ) + { + if (pParent) + pSheet->SetParent(pParent->GetName()); + pParent = pSheet; + } + } + } + + /************************************************************************** + * Titel + **************************************************************************/ + aName = String(SdResId(STR_LAYOUT_TITLE)); + aName.Insert(aPrefix, 0); + + if (!Find(aName, SD_STYLE_FAMILY_MASTERPAGE)) + { + bCreated = sal_True; + + pSheet = &Make(aName, SD_STYLE_FAMILY_MASTERPAGE,nUsedMask); + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_TITLE ); + pSheet->SetParent(String()); + SfxItemSet& rTitleSet = pSheet->GetItemSet(); + rTitleSet.Put(XLineStyleItem(XLINE_NONE)); + rTitleSet.Put(XFillStyleItem(XFILL_NONE)); + rTitleSet.Put(aSvxFontItem); + rTitleSet.Put(aSvxFontItemCJK); + rTitleSet.Put(aSvxFontItemCTL); + rTitleSet.Put(SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC ) ); + rTitleSet.Put(SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CJK ) ); + rTitleSet.Put(SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CTL ) ); + rTitleSet.Put(SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT ) ); + rTitleSet.Put(SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ) ); + rTitleSet.Put(SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ) ); + rTitleSet.Put(SvxFontHeightItem( 1552, 100, EE_CHAR_FONTHEIGHT ) ); // 44 pt + rTitleSet.Put(SvxFontHeightItem( 1552, 100, EE_CHAR_FONTHEIGHT_CJK ) ); // 44 pt + rTitleSet.Put(SvxFontHeightItem( SdDrawDocument::convertFontHeightToCTL( 1552 ), 100, EE_CHAR_FONTHEIGHT_CTL ) ); // 44 pt + rTitleSet.Put(SvxUnderlineItem(UNDERLINE_NONE, EE_CHAR_UNDERLINE )); + rTitleSet.Put(SvxOverlineItem(UNDERLINE_NONE, EE_CHAR_OVERLINE )); + rTitleSet.Put(SvxCrossedOutItem(STRIKEOUT_NONE, EE_CHAR_STRIKEOUT )); + rTitleSet.Put(SvxShadowedItem(FALSE, EE_CHAR_SHADOW )); + rTitleSet.Put(SvxContourItem(FALSE, EE_CHAR_OUTLINE )); + rTitleSet.Put( SvxEmphasisMarkItem(EMPHASISMARK_NONE, EE_CHAR_EMPHASISMARK ) ); + rTitleSet.Put( SvxCharReliefItem(RELIEF_NONE, EE_CHAR_RELIEF ) ); + rTitleSet.Put(SvxColorItem( Color(COL_AUTO), EE_CHAR_COLOR )); + rTitleSet.Put(SvxAdjustItem(SVX_ADJUST_CENTER, EE_PARA_JUST )); + rTitleSet.Put( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) ); + // #i16874# enable kerning by default but only for new documents + rTitleSet.Put( SvxAutoKernItem( TRUE, EE_CHAR_PAIRKERNING ) ); + + aBulletFont.SetSize(Size(0,1552)); // 44 pt + PutNumBulletItem( pSheet, aBulletFont ); + } + + /************************************************************************** + * Untertitel + **************************************************************************/ + aName = String(SdResId(STR_LAYOUT_SUBTITLE)); + aName.Insert(aPrefix, 0); + + if (!Find(aName, SD_STYLE_FAMILY_MASTERPAGE)) + { + bCreated = sal_True; + + pSheet = &Make(aName, SD_STYLE_FAMILY_MASTERPAGE,nUsedMask); + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_SUBTITLE ); + pSheet->SetParent(String()); + SfxItemSet& rSubtitleSet = pSheet->GetItemSet(); + rSubtitleSet.Put(XLineStyleItem(XLINE_NONE)); + rSubtitleSet.Put(XFillStyleItem(XFILL_NONE)); + rSubtitleSet.Put(aSvxFontItem); + rSubtitleSet.Put(aSvxFontItemCJK); + rSubtitleSet.Put(aSvxFontItemCTL); + rSubtitleSet.Put(SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC ) ); + rSubtitleSet.Put(SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CJK ) ); + rSubtitleSet.Put(SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CTL ) ); + rSubtitleSet.Put(SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT ) ); + rSubtitleSet.Put(SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ) ); + rSubtitleSet.Put(SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ) ); + rSubtitleSet.Put( SvxFontHeightItem( 1129, 100, EE_CHAR_FONTHEIGHT ) ); // 32 pt + rSubtitleSet.Put( SvxFontHeightItem( 1129, 100, EE_CHAR_FONTHEIGHT_CJK ) ); // 32 pt + rSubtitleSet.Put( SvxFontHeightItem( SdDrawDocument::convertFontHeightToCTL( 1129 ), 100, EE_CHAR_FONTHEIGHT_CTL ) ); // 32 pt + rSubtitleSet.Put(SvxUnderlineItem(UNDERLINE_NONE, EE_CHAR_UNDERLINE )); + rSubtitleSet.Put(SvxOverlineItem(UNDERLINE_NONE, EE_CHAR_OVERLINE )); + rSubtitleSet.Put(SvxCrossedOutItem(STRIKEOUT_NONE, EE_CHAR_STRIKEOUT )); + rSubtitleSet.Put(SvxShadowedItem(FALSE, EE_CHAR_SHADOW )); + rSubtitleSet.Put(SvxContourItem(FALSE, EE_CHAR_OUTLINE )); + rSubtitleSet.Put( SvxEmphasisMarkItem(EMPHASISMARK_NONE, EE_CHAR_EMPHASISMARK ) ); + rSubtitleSet.Put( SvxCharReliefItem(RELIEF_NONE, EE_CHAR_RELIEF ) ); + rSubtitleSet.Put(SvxColorItem( Color(COL_AUTO), EE_CHAR_COLOR )); + rSubtitleSet.Put(SvxAdjustItem(SVX_ADJUST_CENTER, EE_PARA_JUST )); + rSubtitleSet.Put( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) ); + // #i16874# enable kerning by default but only for new documents + rSubtitleSet.Put( SvxAutoKernItem( TRUE, EE_CHAR_PAIRKERNING ) ); + aSvxLRSpaceItem.SetTxtLeft(0); + rSubtitleSet.Put(aSvxLRSpaceItem); + + Font aTmpFont( GetBulletFont() ); + aTmpFont.SetSize(Size(0, 1129)); // 32 pt + PutNumBulletItem( pSheet, aTmpFont ); + } + + /************************************************************************** + * Notizen + **************************************************************************/ + aName = String(SdResId(STR_LAYOUT_NOTES)); + aName.Insert(aPrefix, 0); + + if (!Find(aName, SD_STYLE_FAMILY_MASTERPAGE)) + { + bCreated = sal_True; + + pSheet = &Make(aName, SD_STYLE_FAMILY_MASTERPAGE,nUsedMask); + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_NOTES ); + pSheet->SetParent(String()); + SfxItemSet& rNotesSet = pSheet->GetItemSet(); + rNotesSet.Put(XLineStyleItem(XLINE_NONE)); + rNotesSet.Put(XFillStyleItem(XFILL_NONE)); + rNotesSet.Put(aSvxFontItem); + rNotesSet.Put(aSvxFontItemCJK); + rNotesSet.Put(aSvxFontItemCTL); + rNotesSet.Put( SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC ) ); + rNotesSet.Put( SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CJK ) ); + rNotesSet.Put( SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CTL ) ); + rNotesSet.Put( SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT ) ); + rNotesSet.Put( SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ) ); + rNotesSet.Put( SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ) ); + rNotesSet.Put( SvxFontHeightItem( 705, 100, EE_CHAR_FONTHEIGHT ) ); // 20 pt + rNotesSet.Put( SvxFontHeightItem( 705, 100, EE_CHAR_FONTHEIGHT_CJK ) ); // 20 pt + rNotesSet.Put( SvxFontHeightItem( SdDrawDocument::convertFontHeightToCTL( 705 ), 100, EE_CHAR_FONTHEIGHT_CTL ) ); // 20 pt + rNotesSet.Put( SvxUnderlineItem(UNDERLINE_NONE, EE_CHAR_UNDERLINE ) ); + rNotesSet.Put( SvxOverlineItem(UNDERLINE_NONE, EE_CHAR_OVERLINE ) ); + rNotesSet.Put( SvxCrossedOutItem(STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) ); + rNotesSet.Put( SvxShadowedItem(FALSE, EE_CHAR_SHADOW ) ); + rNotesSet.Put( SvxContourItem(FALSE, EE_CHAR_OUTLINE ) ); + rNotesSet.Put( SvxEmphasisMarkItem(EMPHASISMARK_NONE, EE_CHAR_EMPHASISMARK ) ); + rNotesSet.Put( SvxCharReliefItem(RELIEF_NONE, EE_CHAR_RELIEF) ); + rNotesSet.Put( SvxColorItem( Color(COL_AUTO), EE_CHAR_COLOR ) ); + rNotesSet.Put( SvxLRSpaceItem( 0, 0, 600, -600, EE_PARA_LRSPACE ) ); + // #i16874# enable kerning by default but only for new documents + rNotesSet.Put( SvxAutoKernItem( TRUE, EE_CHAR_PAIRKERNING ) ); + +/* #i35937# */ + + } + + /************************************************************************** + * Hintergrundobjekte + **************************************************************************/ + aName = String(SdResId(STR_LAYOUT_BACKGROUNDOBJECTS)); + aName.Insert(aPrefix, 0); + + if (!Find(aName, SD_STYLE_FAMILY_MASTERPAGE)) + { + bCreated = sal_True; + + pSheet = &Make(aName, SD_STYLE_FAMILY_MASTERPAGE,nUsedMask); + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_BACKGROUNDOBJECTS ); + pSheet->SetParent(String()); + SfxItemSet& rBackgroundObjectsSet = pSheet->GetItemSet(); + rBackgroundObjectsSet.Put(SdrShadowItem(FALSE)); + rBackgroundObjectsSet.Put(SdrShadowColorItem(String(), Color(COL_GRAY))); + rBackgroundObjectsSet.Put(SdrShadowXDistItem(300)); // 3 mm Schattendistanz + rBackgroundObjectsSet.Put(SdrShadowYDistItem(300)); + // #i16874# enable kerning by default but only for new documents + rBackgroundObjectsSet.Put( SvxAutoKernItem( TRUE, EE_CHAR_PAIRKERNING ) ); + } + + /************************************************************************** + * Hintergrund + **************************************************************************/ + aName = String(SdResId(STR_LAYOUT_BACKGROUND)); + aName.Insert(aPrefix, 0); + + if (!Find(aName, SD_STYLE_FAMILY_MASTERPAGE)) + { + bCreated = sal_True; + + pSheet = &Make(aName, SD_STYLE_FAMILY_MASTERPAGE,nUsedMask); + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_BACKGROUND ); + pSheet->SetParent(String()); + SfxItemSet& rBackgroundSet = pSheet->GetItemSet(); + rBackgroundSet.Put(XLineStyleItem(XLINE_NONE)); + rBackgroundSet.Put(XFillStyleItem(XFILL_NONE)); + // #i16874# enable kerning by default but only for new documents + rBackgroundSet.Put( SvxAutoKernItem( TRUE, EE_CHAR_PAIRKERNING ) ); + } + + DBG_ASSERT( !bCheck || !bCreated, "missing layout style sheets detected!" ); +} + +/************************************************************************* +|* +|* Graphik-StyleSheets aus dem Quellpool in diesen Pool kopieren +|* +|* (rSourcePool kann nicht const sein, weil SfxStyleSheetPoolBase::Find +|* nicht const ist) +|* +\************************************************************************/ + +void SdStyleSheetPool::CopyGraphicSheets(SdStyleSheetPool& rSourcePool) +{ + CopySheets( rSourcePool, SD_STYLE_FAMILY_GRAPHICS ); +} + +void SdStyleSheetPool::CopyCellSheets(SdStyleSheetPool& rSourcePool) +{ + CopySheets( rSourcePool, SD_STYLE_FAMILY_CELL ); +} + +void SdStyleSheetPool::CopyTableStyles(SdStyleSheetPool& rSourcePool) +{ + Reference< XIndexAccess > xSource( rSourcePool.mxTableFamily, UNO_QUERY ); + Reference< XNameContainer > xTarget( mxTableFamily, UNO_QUERY ); + Reference< XSingleServiceFactory > xFactory( mxTableFamily, UNO_QUERY ); + + if( xSource.is() && xFactory.is() && mxTableFamily.is() ) + { + for( sal_Int32 nIndex = 0; nIndex < xSource->getCount(); nIndex++ ) try + { + Reference< XStyle > xSourceTableStyle( xSource->getByIndex( nIndex ), UNO_QUERY ); + if( xSourceTableStyle.is() ) + { + Reference< XStyle > xNewTableStyle( xFactory->createInstance(), UNO_QUERY ); + if( xNewTableStyle.is() ) + { + Reference< XNameAccess> xSourceNames( xSourceTableStyle, UNO_QUERY_THROW ); + + Sequence< OUString > aStyleNames( xSourceNames->getElementNames() ); + OUString* pStyleNames( aStyleNames.getArray() ); + + Reference< XNameReplace > xTargetNames( xNewTableStyle, UNO_QUERY ); + + sal_Int32 nNames = aStyleNames.getLength(); + while( nNames-- ) + { + const OUString aName( *pStyleNames++ ); + Reference< XStyle > xSourceStyle( xSourceNames->getByName( aName ), UNO_QUERY ); + Reference< XStyle > xTargetStyle; + if( xSourceStyle.is() ) try + { + mxCellFamily->getByName( xSourceStyle->getName() ) >>= xTargetStyle; + } + catch( Exception& ) + { + DBG_ERROR( "sd::SdStyleSheetPool::CopyTableStyles(), exception caught!" ); + } + + if( xTargetStyle.is() ) + xTargetNames->replaceByName( aName, Any( xTargetStyle ) ); + } + } + + OUString sName( Reference< XNamed >( xSourceTableStyle, UNO_QUERY_THROW )->getName() ); + if( xTarget->hasByName( sName ) ) + xTarget->replaceByName( sName, Any( xNewTableStyle ) ); + else + xTarget->insertByName( sName, Any( xNewTableStyle ) ); + } + } + catch( Exception& ) + { + DBG_ERROR("sd::SdStyleSheetPool::CopyTableStyles(), exception caught!"); + } + } +} + +void SdStyleSheetPool::CopySheets(SdStyleSheetPool& rSourcePool, SfxStyleFamily eFamily ) +{ + String aHelpFile; + + sal_uInt32 nCount = rSourcePool.aStyles.size(); + + std::vector< std::pair< rtl::Reference< SfxStyleSheetBase >, String > > aNewStyles; + + for (sal_uInt32 n = 0; n < nCount; n++) + { + rtl::Reference< SfxStyleSheetBase > xSheet( rSourcePool.aStyles[sal::static_int_cast<sal_uInt16>(n)] ); + + if( xSheet->GetFamily() == eFamily ) + { + String aName( xSheet->GetName() ); + if ( !Find( aName, eFamily ) ) + { + rtl::Reference< SfxStyleSheetBase > xNewSheet( &Make( aName, eFamily ) ); + + xNewSheet->SetMask( xSheet->GetMask() ); + + // #91588# Also set parent relation for copied style sheets + String aParent( xSheet->GetParent() ); + if( aParent.Len() ) + aNewStyles.push_back( std::pair< rtl::Reference< SfxStyleSheetBase >, String >( xNewSheet, aParent ) ); + + xNewSheet->SetHelpId( aHelpFile, xSheet->GetHelpId( aHelpFile ) ); + xNewSheet->GetItemSet().Put( xSheet->GetItemSet() ); + } + } + } + + // set parents on newly added stylesheets + std::vector< std::pair< rtl::Reference< SfxStyleSheetBase >, String > >::iterator aIter; + for( aIter = aNewStyles.begin(); aIter != aNewStyles.end(); ++aIter ) + { + DBG_ASSERT( rSourcePool.Find( (*aIter).second, eFamily ), "StyleSheet has invalid parent: Family mismatch" ); + (*aIter).first->SetParent( (*aIter).second ); + } +} + + +/************************************************************************* +|* +|* StyleSheets des genannten Praesentationslayouts aus dem Quellpool in diesen +|* Pool kopieren. Kopiert werden nur solche StyleSheets, die in diesem Pool +|* noch nicht vorhanden sind. +|* pCreatedSheets wird - wenn ungleich NULL - mit Zeigern auf die erzeugten +|* StyleSheets gefuellt. +|* +|* (rSourcePool kann nicht const sein, weil SfxStyleSheetPoolBase::Find +|* nicht const ist) +|* +\************************************************************************/ + +void SdStyleSheetPool::CopyLayoutSheets(const String& rLayoutName, SdStyleSheetPool& rSourcePool, SdStyleSheetVector& rCreatedSheets) +{ + SfxStyleSheetBase* pSheet = NULL; + + String aOutlineTag(SdResId(STR_LAYOUT_OUTLINE)); + + List* pNameList = CreateLayoutSheetNames(rLayoutName); + + String sEmpty; + String* pName = (String*)pNameList->First(); + while (pName) + { + pSheet = Find(*pName, SD_STYLE_FAMILY_MASTERPAGE); + if (!pSheet) + { + SfxStyleSheetBase* pSourceSheet = rSourcePool.Find(*pName, SD_STYLE_FAMILY_MASTERPAGE); + DBG_ASSERT(pSourceSheet, "CopyLayoutSheets: Quellvorlage nicht gefunden"); + if (pSourceSheet) + { + // falls einer mit Methusalem-Doks. ankommt + SfxStyleSheetBase& rNewSheet = Make(*pName, SD_STYLE_FAMILY_MASTERPAGE); + rNewSheet.SetHelpId( sEmpty, pSourceSheet->GetHelpId( sEmpty ) ); + rNewSheet.GetItemSet().Put(pSourceSheet->GetItemSet()); + rCreatedSheets.push_back( SdStyleSheetRef( static_cast< SdStyleSheet* >( &rNewSheet ) ) ); + } + } + delete pName; + pName = (String*)pNameList->Next(); + } + delete pNameList; + + // Sonderbehandlung fuer Gliederungsvorlagen: Parentbeziehungen aufbauen + List* pOutlineSheets = CreateOutlineSheetList(rLayoutName); + SfxStyleSheetBase* pParent = (SfxStyleSheetBase*)pOutlineSheets->First(); + pSheet = (SfxStyleSheetBase*)pOutlineSheets->Next(); + while (pSheet) + { + // kein Parent? + if (pSheet->GetParent().Len() == 0) + pSheet->SetParent(pParent->GetName()); + pParent = pSheet; + pSheet = (SfxStyleSheetBase*)pOutlineSheets->Next(); + } + delete pOutlineSheets; +} + +/************************************************************************* +|* +|* Liste mit den Namen der Praesentationsvorlagen eines Layouts erzeugen. +|* Die Liste und die enthaltenen Strings gehoeren dem Caller! +|* +\************************************************************************/ + +List* SdStyleSheetPool::CreateLayoutSheetNames(const String& rLayoutName) const +{ + String aPrefix(rLayoutName); + String aSep( RTL_CONSTASCII_USTRINGPARAM( SD_LT_SEPARATOR )); + aPrefix.Insert(aSep); + + List* pNameList = new List; + + String aName(SdResId(STR_LAYOUT_OUTLINE)); + String* pName = NULL; + + for (USHORT nLevel = 1; nLevel < 10; nLevel++) + { + pName = new String(aName); + pName->Append( sal_Unicode( ' ' )); + pName->Append( String::CreateFromInt32( sal_Int32( nLevel ))); + pName->Insert(aPrefix, 0); + pNameList->Insert(pName, LIST_APPEND); + } + + pName = new String(SdResId(STR_LAYOUT_TITLE)); + pName->Insert(aPrefix, 0); + pNameList->Insert(pName, LIST_APPEND); + + pName = new String(SdResId(STR_LAYOUT_SUBTITLE)); + pName->Insert(aPrefix, 0); + pNameList->Insert(pName, LIST_APPEND); + + pName = new String(SdResId(STR_LAYOUT_NOTES)); + pName->Insert(aPrefix, 0); + pNameList->Insert(pName, LIST_APPEND); + + pName = new String(SdResId(STR_LAYOUT_BACKGROUNDOBJECTS)); + pName->Insert(aPrefix, 0); + pNameList->Insert(pName, LIST_APPEND); + + pName = new String(SdResId(STR_LAYOUT_BACKGROUND)); + pName->Insert(aPrefix, 0); + pNameList->Insert(pName, LIST_APPEND); + + return pNameList; +} + +/************************************************************************* +|* +|* Liste mit Zeigern auf Praesentationsvorlagen eines Layouts erzeugen. +|* Die Liste gehoert dem Caller! +|* +\************************************************************************/ + +void SdStyleSheetPool::CreateLayoutSheetList(const String& rLayoutName, SdStyleSheetVector& rLayoutSheets ) +{ + String aLayoutNameWithSep(rLayoutName); + aLayoutNameWithSep.AppendAscii( RTL_CONSTASCII_STRINGPARAM( SD_LT_SEPARATOR )); + USHORT nLen = aLayoutNameWithSep.Len(); + + SfxStyleSheetIterator aIter(this, SD_STYLE_FAMILY_MASTERPAGE); + SfxStyleSheetBase* pSheet = aIter.First(); + + while (pSheet) + { + if (pSheet->GetName().Match(aLayoutNameWithSep) == nLen) + rLayoutSheets.push_back( SdStyleSheetRef( static_cast< SdStyleSheet* >( pSheet ) ) ); + pSheet = aIter.Next(); + } +} + +/************************************************************************* +|* +|* ggfs. PseudoStyleSheets erzeugen +|* +\************************************************************************/ + +void SdStyleSheetPool::CreatePseudosIfNecessary() +{ + String aName; + String aHelpFile; + SfxStyleSheetBase* pSheet = NULL; + SfxStyleSheetBase* pParent = NULL; + + USHORT nUsedMask = SFXSTYLEBIT_USED; + + aName = String(SdResId(STR_PSEUDOSHEET_TITLE)); + if( (pSheet = Find(aName, SD_STYLE_FAMILY_PSEUDO)) == 0 ) + { + pSheet = &Make(aName, SD_STYLE_FAMILY_PSEUDO, nUsedMask); + pSheet->SetParent( String() ); + ((SfxStyleSheet*)pSheet)->StartListening(*this); + } + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_TITLE ); + + aName = String(SdResId(STR_PSEUDOSHEET_SUBTITLE)); + if( (pSheet = Find(aName, SD_STYLE_FAMILY_PSEUDO)) == 0 ) + { + pSheet = &Make(aName, SD_STYLE_FAMILY_PSEUDO, nUsedMask); + pSheet->SetParent(String()); + ((SfxStyleSheet*)pSheet)->StartListening(*this); + } + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_SUBTITLE ); + + aName = String(SdResId(STR_PSEUDOSHEET_BACKGROUNDOBJECTS)); + if( (pSheet = Find(aName, SD_STYLE_FAMILY_PSEUDO)) == 0 ) + { + pSheet = &Make(aName, SD_STYLE_FAMILY_PSEUDO, nUsedMask); + pSheet->SetParent( String() ); + ((SfxStyleSheet*)pSheet)->StartListening(*this); + } + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_BACKGROUNDOBJECTS ); + + aName = String(SdResId(STR_PSEUDOSHEET_BACKGROUND)); + if( (pSheet = Find(aName, SD_STYLE_FAMILY_PSEUDO)) == 0 ) + { + pSheet = &Make(aName, SD_STYLE_FAMILY_PSEUDO, nUsedMask); + pSheet->SetParent( String() ); + ((SfxStyleSheet*)pSheet)->StartListening(*this); + } + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_BACKGROUND ); + + aName = String(SdResId(STR_PSEUDOSHEET_NOTES)); + if( (pSheet = Find(aName, SD_STYLE_FAMILY_PSEUDO)) == 0 ) + { + pSheet = &Make(aName, SD_STYLE_FAMILY_PSEUDO, nUsedMask); + pSheet->SetParent( String() ); + ((SfxStyleSheet*)pSheet)->StartListening(*this); + } + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_NOTES ); + + pParent = NULL; + SetSearchMask(SD_STYLE_FAMILY_PSEUDO); + aName = String(SdResId(STR_PSEUDOSHEET_OUTLINE)); + for (USHORT nLevel = 1; nLevel < 10; nLevel++) + { + String aLevelName(aName); + aLevelName.Append( sal_Unicode( ' ' )); + aLevelName.Append( String::CreateFromInt32( sal_Int32( nLevel ))); + + if( (pSheet = Find(aLevelName, SD_STYLE_FAMILY_PSEUDO)) == 0 ) + { + pSheet = &Make(aLevelName, SD_STYLE_FAMILY_PSEUDO, nUsedMask); + + if (pSheet) + { + if (pParent) + pSheet->SetParent(pParent->GetName()); + pParent = pSheet; + ((SfxStyleSheet*)pSheet)->StartListening(*this); + } + } + pSheet->SetHelpId( aHelpFile, HID_PSEUDOSHEET_OUTLINE + nLevel ); + } +} + + +/************************************************************************* +|* +|* Standard-Styles den richtigen Namen in der Programm-Sprache geben +|* +\************************************************************************/ + +void SdStyleSheetPool::UpdateStdNames() +{ + String aHelpFile; + sal_uInt32 nCount = aStyles.size(); + List* pEraseList = NULL; + + for( sal_uInt32 n=0; n < nCount; n++ ) + { + SfxStyleSheetBase* pStyle = aStyles[ n ].get(); + + if( !pStyle->IsUserDefined() ) + { + String aOldName = pStyle->GetName(); + ULONG nHelpId = pStyle->GetHelpId( aHelpFile ); + SfxStyleFamily eFam = pStyle->GetFamily(); + + BOOL bHelpKnown = TRUE; + String aNewName; + USHORT nNameId = 0; + switch( nHelpId ) + { + case HID_STANDARD_STYLESHEET_NAME: nNameId = STR_STANDARD_STYLESHEET_NAME; break; + case HID_POOLSHEET_OBJWITHARROW: nNameId = STR_POOLSHEET_OBJWITHARROW; break; + case HID_POOLSHEET_OBJWITHSHADOW: nNameId = STR_POOLSHEET_OBJWITHSHADOW; break; + case HID_POOLSHEET_OBJWITHOUTFILL: nNameId = STR_POOLSHEET_OBJWITHOUTFILL; break; + case HID_POOLSHEET_TEXT: nNameId = STR_POOLSHEET_TEXT; break; + case HID_POOLSHEET_TEXTBODY: nNameId = STR_POOLSHEET_TEXTBODY; break; + case HID_POOLSHEET_TEXTBODY_JUSTIFY:nNameId = STR_POOLSHEET_TEXTBODY_JUSTIFY;break; + case HID_POOLSHEET_TEXTBODY_INDENT: nNameId = STR_POOLSHEET_TEXTBODY_INDENT;break; + case HID_POOLSHEET_TITLE: nNameId = STR_POOLSHEET_TITLE; break; + case HID_POOLSHEET_TITLE1: nNameId = STR_POOLSHEET_TITLE1; break; + case HID_POOLSHEET_TITLE2: nNameId = STR_POOLSHEET_TITLE2; break; + case HID_POOLSHEET_HEADLINE: nNameId = STR_POOLSHEET_HEADLINE; break; + case HID_POOLSHEET_HEADLINE1: nNameId = STR_POOLSHEET_HEADLINE1; break; + case HID_POOLSHEET_HEADLINE2: nNameId = STR_POOLSHEET_HEADLINE2; break; + case HID_POOLSHEET_MEASURE: nNameId = STR_POOLSHEET_MEASURE; break; + + case HID_PSEUDOSHEET_TITLE: nNameId = STR_PSEUDOSHEET_TITLE; break; + case HID_PSEUDOSHEET_SUBTITLE: nNameId = STR_PSEUDOSHEET_SUBTITLE; break; + case HID_PSEUDOSHEET_OUTLINE1: + case HID_PSEUDOSHEET_OUTLINE2: + case HID_PSEUDOSHEET_OUTLINE3: + case HID_PSEUDOSHEET_OUTLINE4: + case HID_PSEUDOSHEET_OUTLINE5: + case HID_PSEUDOSHEET_OUTLINE6: + case HID_PSEUDOSHEET_OUTLINE7: + case HID_PSEUDOSHEET_OUTLINE8: + case HID_PSEUDOSHEET_OUTLINE9: nNameId = STR_PSEUDOSHEET_OUTLINE; break; + case HID_PSEUDOSHEET_BACKGROUNDOBJECTS: nNameId = STR_PSEUDOSHEET_BACKGROUNDOBJECTS; break; + case HID_PSEUDOSHEET_BACKGROUND: nNameId = STR_PSEUDOSHEET_BACKGROUND; break; + case HID_PSEUDOSHEET_NOTES: nNameId = STR_PSEUDOSHEET_NOTES; break; + + case HID_SD_CELL_STYLE_DEFAULT: nNameId = STR_STANDARD_STYLESHEET_NAME; break; + case HID_SD_CELL_STYLE_BANDED: nNameId = STR_POOLSHEET_BANDED_CELL; break; + case HID_SD_CELL_STYLE_HEADER: nNameId = STR_POOLSHEET_HEADER; break; + case HID_SD_CELL_STYLE_TOTAL: nNameId = STR_POOLSHEET_TOTAL; break; + case HID_SD_CELL_STYLE_FIRST_COLUMN: nNameId = STR_POOLSHEET_FIRST_COLUMN; break; + case HID_SD_CELL_STYLE_LAST_COLUMN: nNameId = STR_POOLSHEET_LAST_COLUMN; break; + + default: + // 0 oder falsche (alte) HelpId + bHelpKnown = FALSE; + } + if( bHelpKnown ) + { + if( nNameId ) + { + aNewName = String( SdResId( nNameId ) ); + if( nNameId == STR_PSEUDOSHEET_OUTLINE ) + { + aNewName.Append( sal_Unicode( ' ' )); + aNewName.Append( String::CreateFromInt32( sal_Int32( nHelpId - HID_PSEUDOSHEET_OUTLINE ))); + } + } + + if( aNewName.Len() && aNewName != aOldName ) + { + SfxStyleSheetBase* pSheetFound = Find( aNewName, eFam ); + + if ( !pSheetFound ) + { + // Sheet existiert noch nicht: Altes Sheet wird umbenannt + pStyle->SetName( aNewName ); // setzt auch Parents um + } + else + { + // Sheet existiert schon: Altes Sheet muss entfernt werden + if( !pEraseList ) + { + pEraseList = new List(); + } + + pEraseList->Insert( pStyle ); + } + } + } + } + } + + if ( pEraseList ) + { + // Styles, welche nicht umbenannt werden konnten, muessen entfernt werden + for ( ULONG i = 0; i < pEraseList->Count(); i++ ) + { + SfxStyleSheetBase* pEraseSheet = ( SfxStyleSheetBase* ) pEraseList->GetObject( i ); + Remove( pEraseSheet ); + } + + delete pEraseList; + pEraseList = NULL; + } +} +// -------------------------------------------------------------------- +// Neues SvxNumBulletItem fuer das jeweilige StyleSheet setzen +// -------------------------------------------------------------------- + +void SdStyleSheetPool::PutNumBulletItem( SfxStyleSheetBase* pSheet, + Font& rBulletFont ) +{ + String aHelpFile; + ULONG nHelpId = pSheet->GetHelpId( aHelpFile ); + SfxItemSet& rSet = pSheet->GetItemSet(); + + switch ( nHelpId ) + { + case HID_STANDARD_STYLESHEET_NAME : + { + // Standard-Vorlage + SvxNumberFormat aNumberFormat(SVX_NUM_CHAR_SPECIAL); + aNumberFormat.SetBulletFont(&rBulletFont); + aNumberFormat.SetBulletChar( 0x25CF ); // StarBats: 0xF000 + 34 + aNumberFormat.SetBulletRelSize(45); + aNumberFormat.SetBulletColor(Color(COL_AUTO)); + aNumberFormat.SetStart(1); + aNumberFormat.SetNumAdjust(SVX_ADJUST_LEFT); + + SvxNumRule aNumRule( NUM_BULLET_REL_SIZE|NUM_BULLET_COLOR|NUM_CHAR_TEXT_DISTANCE, 10 , FALSE); + aNumberFormat.SetLSpace( 0 ); + aNumberFormat.SetAbsLSpace( 0 ); + aNumberFormat.SetFirstLineOffset( 0 ); + aNumRule.SetLevel( 0, aNumberFormat ); + + for( USHORT i = 1; i < aNumRule.GetLevelCount(); i++ ) + { + const short nLSpace = (i + 1) * 600; + aNumberFormat.SetLSpace(nLSpace); + aNumberFormat.SetAbsLSpace(nLSpace); + aNumberFormat.SetFirstLineOffset(-600); + aNumRule.SetLevel( i, aNumberFormat ); + } + + rSet.Put( SvxNumBulletItem( aNumRule, EE_PARA_NUMBULLET ) ); + ((SfxStyleSheet*)pSheet)->Broadcast(SfxSimpleHint( SFX_HINT_DATACHANGED ) ); + } + break; + + case HID_PSEUDOSHEET_TITLE: + /* #84013# title gets same bullet as subtitle and not that page symbol anymore */ + case HID_PSEUDOSHEET_SUBTITLE : + { + // Untertitel-Vorlage + SvxNumRule* pDefaultRule = ((SvxNumBulletItem*) rSet.GetPool()->GetSecondaryPool()->GetPoolDefaultItem(EE_PARA_NUMBULLET))->GetNumRule(); + DBG_ASSERT( pDefaultRule, "Wo ist mein Default? [CL]" ); + + if(pDefaultRule) + { + SvxNumRule aNumRule(pDefaultRule->GetFeatureFlags(), 10, FALSE); + for(USHORT i=0; i < aNumRule.GetLevelCount(); i++) + { + SvxNumberFormat aFrmt( pDefaultRule->GetLevel(i) ); + aFrmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL); + aFrmt.SetStart(1); + aFrmt.SetBulletRelSize(45); + aFrmt.SetBulletChar( 0x25CF ); // StarBats: 0xF000 + 34 + aFrmt.SetBulletFont(&rBulletFont); + aNumRule.SetLevel(i, aFrmt); + } + + rSet.Put( SvxNumBulletItem( aNumRule, EE_PARA_NUMBULLET ) ); + ((SfxStyleSheet*)pSheet)->Broadcast(SfxSimpleHint( SFX_HINT_DATACHANGED ) ); + } + } + break; + + case HID_PSEUDOSHEET_OUTLINE + 1 : + { + // Gliederungs-Vorlage + SvxNumberFormat aNumberFormat(SVX_NUM_CHAR_SPECIAL); + aNumberFormat.SetBulletColor(Color(COL_AUTO)); + aNumberFormat.SetStart(1); + aNumberFormat.SetNumAdjust(SVX_ADJUST_LEFT); + + SvxNumRule aNumRule( NUM_BULLET_REL_SIZE|NUM_BULLET_COLOR|NUM_CHAR_TEXT_DISTANCE|NUM_SYMBOL_ALIGNMENT, + 10, FALSE ); + for( UINT16 i = 0; i < aNumRule.GetLevelCount(); i++ ) + { + aNumberFormat.SetBulletChar( 0x25CF ); // StarBats: 0xF000 + 34 + aNumberFormat.SetBulletRelSize(45); + const short nLSpace = (i + 1) * 1200; + aNumberFormat.SetLSpace(nLSpace); + aNumberFormat.SetAbsLSpace(nLSpace); + short nFirstLineOffset = -600; + + ULONG nFontSize = 20; + switch(i) + { + case 0: + case 1: + { + nFontSize = 32; + nFirstLineOffset = -900; + } + break; + + case 2: + { + nFontSize = 28; + nFirstLineOffset = -800; + aNumberFormat.SetBulletChar( 0x2013 ); // StarBats: 0xF000 + 150 + aNumberFormat.SetBulletRelSize(75); + } + break; + + case 3: + { + nFontSize = 24; + } + break; + + case 4: + { + aNumberFormat.SetBulletChar( 0x2013 ); // StarBats: 0xF000 + 150 + aNumberFormat.SetBulletRelSize(75); + } + break; + } + + aNumberFormat.SetFirstLineOffset(nFirstLineOffset); + nFontSize = (USHORT)((nFontSize * 2540L) / 72); // Pt --> 1/100 mm + rBulletFont.SetSize(Size(0,846)); // 24 pt + aNumberFormat.SetBulletFont(&rBulletFont); + aNumRule.SetLevel( i, aNumberFormat ); + } + + rSet.Put( SvxNumBulletItem( aNumRule, EE_PARA_NUMBULLET ) ); + ((SfxStyleSheet*)pSheet)->Broadcast(SfxSimpleHint( SFX_HINT_DATACHANGED ) ); + } + break; + } +} + +/************************************************************************* +|* +|* Standard Bullet-Font erzeugen (ohne Groesse) +|* +\************************************************************************/ + +Font SdStyleSheetPool::GetBulletFont() const +{ + Font aBulletFont( String( RTL_CONSTASCII_USTRINGPARAM( "StarSymbol" )), Size(0, 1000) ); + aBulletFont.SetCharSet(RTL_TEXTENCODING_UNICODE); + aBulletFont.SetWeight(WEIGHT_NORMAL); + aBulletFont.SetUnderline(UNDERLINE_NONE); + aBulletFont.SetOverline(UNDERLINE_NONE); + aBulletFont.SetStrikeout(STRIKEOUT_NONE); + aBulletFont.SetItalic(ITALIC_NONE); + aBulletFont.SetOutline(FALSE); + aBulletFont.SetShadow(FALSE); + aBulletFont.SetColor(Color(COL_AUTO)); + aBulletFont.SetTransparent(TRUE); + + return aBulletFont; +} + +// -------------------------------------------------------------------- + +void SdStyleSheetPool::AddStyleFamily( const SdPage* pPage ) +{ + rtl::Reference< SfxStyleSheetPool > xPool( this ); + maStyleFamilyMap[pPage] = new SdStyleFamily( xPool, pPage ); +} + +// -------------------------------------------------------------------- + +void SdStyleSheetPool::RemoveStyleFamily( const SdPage* pPage ) +{ + SdStyleFamilyMap::iterator iter( maStyleFamilyMap.find( pPage ) ); + if( iter != maStyleFamilyMap.end() ) + { + SdStyleFamilyRef xStyle( (*iter).second ); + maStyleFamilyMap.erase( iter ); + + if( xStyle.is() ) try + { + xStyle->dispose(); + } + catch( Exception& ) + { + } + } +} + +// -------------------------------------------------------------------- + +void SdStyleSheetPool::throwIfDisposed() throw(::com::sun::star::uno::RuntimeException) +{ + if( mpDoc == NULL ) + throw DisposedException(); +} + +// -------------------------------------------------------------------- +// XServiceInfo +// -------------------------------------------------------------------- + +OUString SAL_CALL SdStyleSheetPool::getImplementationName() throw(RuntimeException) +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM("SdStyleSheetPool") ); +} + +// -------------------------------------------------------------------- + +static const sal_Char* gpServiceName = "com.sun.star.style.StyleFamilies"; + +sal_Bool SAL_CALL SdStyleSheetPool::supportsService( const OUString& ServiceName ) throw(RuntimeException) +{ + return ServiceName.equalsAscii( gpServiceName ); +} + +// -------------------------------------------------------------------- + +Sequence< OUString > SAL_CALL SdStyleSheetPool::getSupportedServiceNames() throw(RuntimeException) +{ + OUString aStr( OUString::createFromAscii( gpServiceName ) ); + return Sequence< OUString >( &aStr, 1 ); +} + +// -------------------------------------------------------------------- +// XNameAccess +// -------------------------------------------------------------------- + +Any SAL_CALL SdStyleSheetPool::getByName( const OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + throwIfDisposed(); + + if( mxGraphicFamily->getName() == aName ) + return Any( Reference< XNameAccess >( static_cast< XNameAccess* >( mxGraphicFamily.get() ) ) ); + + if( mxCellFamily->getName() == aName ) + return Any( Reference< XNameAccess >( static_cast< XNameAccess* >( mxCellFamily.get() ) ) ); + + if( msTableFamilyName == aName ) + return Any( mxTableFamily ); + + for( SdStyleFamilyMap::iterator iter( maStyleFamilyMap.begin() ); iter != maStyleFamilyMap.end(); iter++ ) + { + if( (*iter).second->getName() == aName ) + return Any( Reference< XNameAccess >( static_cast< XNameAccess* >( (*iter).second.get() ) ) ); + } + + throw NoSuchElementException(); +} + +// -------------------------------------------------------------------- + +Sequence< OUString > SAL_CALL SdStyleSheetPool::getElementNames() throw(RuntimeException) +{ + throwIfDisposed(); + + Sequence< OUString > aNames( maStyleFamilyMap.size() + 3 ); + OUString* pNames = aNames.getArray(); + + *pNames++ = mxGraphicFamily->getName(); + *pNames++ = mxCellFamily->getName(); + *pNames++ = msTableFamilyName; + + for( SdStyleFamilyMap::iterator iter( maStyleFamilyMap.begin() ); iter != maStyleFamilyMap.end(); iter++ ) + { + *pNames++ = (*iter).second->getName(); + } + + return aNames; +} + +// -------------------------------------------------------------------- + +sal_Bool SAL_CALL SdStyleSheetPool::hasByName( const OUString& aName ) throw(RuntimeException) +{ + throwIfDisposed(); + + if( mxGraphicFamily->getName() == aName ) + return sal_True; + + if( mxCellFamily->getName() == aName ) + return sal_True; + + if( msTableFamilyName == aName ) + return sal_True; + + for( SdStyleFamilyMap::iterator iter( maStyleFamilyMap.begin() ); iter != maStyleFamilyMap.end(); iter++ ) + { + if( (*iter).second->getName() == aName ) + return sal_True; + } + + return sal_False; +} + +// -------------------------------------------------------------------- +// XElementAccess +// -------------------------------------------------------------------- + +Type SAL_CALL SdStyleSheetPool::getElementType() throw(RuntimeException) +{ + throwIfDisposed(); + + return XNameAccess::static_type(); +} + +// -------------------------------------------------------------------- + +sal_Bool SAL_CALL SdStyleSheetPool::hasElements() throw(RuntimeException) +{ + return sal_True; +} + +// -------------------------------------------------------------------- +// XIndexAccess +// -------------------------------------------------------------------- + +sal_Int32 SAL_CALL SdStyleSheetPool::getCount() throw(RuntimeException) +{ + throwIfDisposed(); + + return maStyleFamilyMap.size() + 3; +} + +// -------------------------------------------------------------------- + +Any SAL_CALL SdStyleSheetPool::getByIndex( sal_Int32 Index ) throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +{ + switch( Index ) + { + case 0: + return Any( Reference< XNameAccess >( static_cast< XNameAccess* >( mxGraphicFamily.get() ) ) ); + + case 1: + return Any( Reference< XNameAccess >( static_cast< XNameAccess* >( mxCellFamily.get() ) ) ); + + case 2: + return Any( mxTableFamily ); + + default: + { + Index -= 3; + if( (Index < 0) || (Index >= sal::static_int_cast<sal_Int32>(maStyleFamilyMap.size())) ) + throw IndexOutOfBoundsException(); + SdStyleFamilyMap::iterator iter( maStyleFamilyMap.begin() ); + while( Index-- ) + iter++; + + return Any( Reference< XNameAccess >( static_cast< XNameAccess* >( (*iter).second.get() ) ) ); + } + } +} + +// -------------------------------------------------------------------- +// XComponent +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheetPool::dispose() throw (RuntimeException) +{ + if( mpDoc ) + { + mxGraphicFamily->dispose(); + mxGraphicFamily.clear(); + mxCellFamily->dispose(); + mxCellFamily.clear(); + + Reference< XComponent > xComp( mxTableFamily, UNO_QUERY ); + if( xComp.is() ) + xComp->dispose(); + mxTableFamily = 0; + + SdStyleFamilyMap aTempMap; + aTempMap.swap( maStyleFamilyMap ); + + for( SdStyleFamilyMap::iterator iter( aTempMap.begin() ); iter != aTempMap.end(); ++iter ) try + { + (*iter).second->dispose(); + } + catch( Exception& ) + { + } + + mpDoc = 0; + + Clear(); + } +} + +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheetPool::addEventListener( const Reference< XEventListener >& /*xListener*/ ) throw (RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheetPool::removeEventListener( const Reference< XEventListener >& /*aListener*/ ) throw (RuntimeException) +{ +} + +// -------------------------------------------------------------------- + +SdStyleSheetVector SdStyleSheetPool::CreateChildList( SdStyleSheet* pSheet ) +{ + SdStyleSheetVector aResult; + + USHORT nListenerCount = pSheet->GetListenerCount(); + if (nListenerCount > 0) + { + for (USHORT n = 0; n < nListenerCount; n++) + { + SdStyleSheet* pChild = dynamic_cast< SdStyleSheet* >( pSheet->GetListener(n) ); + if(pChild && pChild->GetParent() == pSheet->GetName()) + { + aResult.push_back( SdStyleSheetRef( pChild ) ); + } + } + } + + return aResult; +} + +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheetPool::acquire (void) throw () +{ + SdStyleSheetPoolBase::acquire(); +} + +void SAL_CALL SdStyleSheetPool::release (void) throw () +{ + SdStyleSheetPoolBase::release(); +} + +// -------------------------------------------------------------------- + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/stlsheet.cxx b/sd/source/core/stlsheet.cxx new file mode 100644 index 000000000000..d61ea838db23 --- /dev/null +++ b/sd/source/core/stlsheet.cxx @@ -0,0 +1,1406 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/style/XStyle.hpp> + +#include <osl/mutex.hxx> +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include <comphelper/serviceinfohelper.hxx> +#include <boost/bind.hpp> + +#include "eetext.hxx" +#include <editeng/eeitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <svx/svdoattr.hxx> +#include <editeng/ulspitem.hxx> +#include <svl/smplhint.hxx> +#include <svl/itemset.hxx> + +#include <svx/xflbmtit.hxx> +#include <svx/xflbstit.hxx> +#include <editeng/bulitem.hxx> +#include <editeng/lrspitem.hxx> +#include <svx/unoshprp.hxx> +#include <svx/unoshape.hxx> +#include <svx/svdpool.hxx> +#include "stlsheet.hxx" +#include "sdresid.hxx" +#include "sdpage.hxx" +#include "drawdoc.hxx" +#include "stlpool.hxx" +#include "glob.hrc" +#include "app.hrc" +#include "glob.hxx" +#include "helpids.h" +#include "../ui/inc/DrawViewShell.hxx" +#include "../ui/inc/ViewShellBase.hxx" + +using ::rtl::OUString; +using ::osl::MutexGuard; +using ::osl::ClearableMutexGuard; +using ::cppu::OInterfaceContainerHelper; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::drawing; + +#define WID_STYLE_DISPNAME 7998 +#define WID_STYLE_FAMILY 7999 + +static SvxItemPropertySet& GetStylePropertySet() +{ + static const SfxItemPropertyMapEntry aFullPropertyMap_Impl[] = + { + { RTL_CONSTASCII_STRINGPARAM("Family"), WID_STYLE_FAMILY, &::getCppuType((const OUString*)0), PropertyAttribute::READONLY, 0}, + { RTL_CONSTASCII_STRINGPARAM("UserDefinedAttributes"), SDRATTR_XMLATTRIBUTES, &XNameContainer::static_type(), 0, 0}, + { RTL_CONSTASCII_STRINGPARAM("DisplayName"), WID_STYLE_DISPNAME, &::getCppuType((const OUString*)0), PropertyAttribute::READONLY, 0}, + + SVX_UNOEDIT_NUMBERING_PROPERTIE, + SHADOW_PROPERTIES + LINE_PROPERTIES + LINE_PROPERTIES_START_END + FILL_PROPERTIES + EDGERADIUS_PROPERTIES + TEXT_PROPERTIES_DEFAULTS + CONNECTOR_PROPERTIES + SPECIAL_DIMENSIONING_PROPERTIES_DEFAULTS + {0,0,0,0,0,0} + }; + + static SvxItemPropertySet aPropSet( aFullPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() ); + return aPropSet; +} + +class ModifyListenerForewarder : public SfxListener +{ +public: + ModifyListenerForewarder( SdStyleSheet* pStyleSheet ); + + virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint); + +private: + SdStyleSheet* mpStyleSheet; +}; + +ModifyListenerForewarder::ModifyListenerForewarder( SdStyleSheet* pStyleSheet ) +: mpStyleSheet( pStyleSheet ) +{ + if( pStyleSheet ) + { + SfxBroadcaster& rBC = static_cast< SfxBroadcaster& >( *pStyleSheet ); + StartListening( rBC ); + } +} + +void ModifyListenerForewarder::Notify(SfxBroadcaster& /*rBC*/, const SfxHint& /*rHint*/) +{ + if( mpStyleSheet ) + mpStyleSheet->notifyModifyListener(); +} + +SdStyleSheet::SdStyleSheet(const OUString& rDisplayName, SfxStyleSheetBasePool& _rPool, SfxStyleFamily eFamily, USHORT _nMask) +: SdStyleSheetBase( UniString( rDisplayName ), _rPool, eFamily, _nMask) +, ::cppu::BaseMutex() +, msApiName( rDisplayName ) +, mxPool( const_cast< SfxStyleSheetBasePool* >(&_rPool) ) +, mrBHelper( m_aMutex ) +{ +} + +SdStyleSheet::SdStyleSheet( const SdStyleSheet & r ) +: SdStyleSheetBase( r ) +, ::cppu::BaseMutex() +, msApiName( r.msApiName ) +, mxPool( r.mxPool ) +, mrBHelper( m_aMutex ) +{ +} + +SdStyleSheet::~SdStyleSheet() +{ + delete pSet; + pSet = NULL; // damit nachfolgende Destruktoren eine Chance haben +} + +void SdStyleSheet::SetApiName( const OUString& rApiName ) +{ + msApiName = rApiName; +} + +rtl::OUString SdStyleSheet::GetApiName() const +{ + if( msApiName.getLength() ) + return msApiName; + else + return GetName(); +} + + +void SdStyleSheet::Load (SvStream& rIn, USHORT nVersion) +{ + SfxStyleSheetBase::Load(rIn, nVersion); + + // Die Default-Maske war frueher 0xAFFE. + // Aus dieser Default-Maske wurden die benoetigten Flags ausmaskiert. + // Nun wurde das Flag SFXSTYLEBIT_READONLY eingefuehrt, was dazu + // das alle StyleSheets read-only waren. + // Da im Draw kein StyleSheet read-only sein soll, wird an dieser Stelle + // das Flag zurueckgesetzt. + nMask &= ~SFXSTYLEBIT_READONLY; +} + +/************************************************************************* +|* +|* Store +|* +\************************************************************************/ + +void SdStyleSheet::Store(SvStream& rOut) +{ + SfxStyleSheetBase::Store(rOut); +} + +/************************************************************************* +|* +|* Parent setzen +|* +\************************************************************************/ + +BOOL SdStyleSheet::SetParent(const String& rParentName) +{ + BOOL bResult = FALSE; + + if (SfxStyleSheet::SetParent(rParentName)) + { + // PseudoStyleSheets haben keine eigenen ItemSets + if (nFamily != SD_STYLE_FAMILY_PSEUDO) + { + if( rParentName.Len() ) + { + SfxStyleSheetBase* pStyle = rPool.Find(rParentName, nFamily); + if (pStyle) + { + bResult = TRUE; + SfxItemSet& rParentSet = pStyle->GetItemSet(); + GetItemSet().SetParent(&rParentSet); + Broadcast( SfxSimpleHint( SFX_HINT_DATACHANGED ) ); + } + } + else + { + bResult = TRUE; + GetItemSet().SetParent(NULL); + Broadcast( SfxSimpleHint( SFX_HINT_DATACHANGED ) ); + } + } + else + { + bResult = TRUE; + } + } + return bResult; +} + +/************************************************************************* +|* +|* ItemSet ggfs. erzeugen und herausreichen +|* +\************************************************************************/ + +SfxItemSet& SdStyleSheet::GetItemSet() +{ + if (nFamily == SD_STYLE_FAMILY_GRAPHICS || nFamily == SD_STYLE_FAMILY_MASTERPAGE) + { + // ggfs. das ItemSet 'on demand' anlegen + if (!pSet) + { + USHORT nWhichPairTable[] = { XATTR_LINE_FIRST, XATTR_LINE_LAST, + XATTR_FILL_FIRST, XATTR_FILL_LAST, + + SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST, + SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_CONTOURFRAME, + + SDRATTR_TEXT_WORDWRAP, SDRATTR_TEXT_AUTOGROWSIZE, + + SDRATTR_EDGE_FIRST, SDRATTR_EDGE_LAST, + SDRATTR_MEASURE_FIRST, SDRATTR_MEASURE_LAST, + + EE_PARA_START, EE_CHAR_END, + + SDRATTR_XMLATTRIBUTES, SDRATTR_TEXT_USEFIXEDCELLHEIGHT, + + SDRATTR_3D_FIRST, SDRATTR_3D_LAST, + 0, 0 }; + + pSet = new SfxItemSet(GetPool().GetPool(), nWhichPairTable); + } + + return *pSet; + } + + else if( nFamily == SD_STYLE_FAMILY_CELL ) + { + if (!pSet) + { + USHORT nWhichPairTable[] = { XATTR_LINE_FIRST, XATTR_LINE_LAST, + XATTR_FILL_FIRST, XATTR_FILL_LAST, + + SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST, + SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_CONTOURFRAME, + + SDRATTR_TEXT_WORDWRAP, SDRATTR_TEXT_AUTOGROWSIZE, + + EE_PARA_START, EE_CHAR_END, + + SDRATTR_TABLE_FIRST, SDRATTR_TABLE_LAST, + SDRATTR_XMLATTRIBUTES, SDRATTR_XMLATTRIBUTES, + + 0, 0 }; + + pSet = new SfxItemSet(GetPool().GetPool(), nWhichPairTable); + } + + return *pSet; + } + + // dies ist eine Stellvertretervorlage fuer die interne Vorlage des + // aktuellen Praesentationslayouts: dessen ItemSet returnieren + else + { + + SdStyleSheet* pSdSheet = GetRealStyleSheet(); + + if (pSdSheet) + { + return(pSdSheet->GetItemSet()); + } + else + { + if (!pSet) + { + USHORT nWhichPairTable[] = { XATTR_LINE_FIRST, XATTR_LINE_LAST, + XATTR_FILL_FIRST, XATTR_FILL_LAST, + + SDRATTR_SHADOW_FIRST, SDRATTR_SHADOW_LAST, + SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_CONTOURFRAME, + + SDRATTR_TEXT_WORDWRAP, SDRATTR_TEXT_AUTOGROWSIZE, + + SDRATTR_EDGE_FIRST, SDRATTR_EDGE_LAST, + SDRATTR_MEASURE_FIRST, SDRATTR_MEASURE_LAST, + + EE_PARA_START, EE_CHAR_END, + + SDRATTR_XMLATTRIBUTES, SDRATTR_TEXT_USEFIXEDCELLHEIGHT, + + SDRATTR_3D_FIRST, SDRATTR_3D_LAST, + 0, 0 }; + + pSet = new SfxItemSet(GetPool().GetPool(), nWhichPairTable); + } + + return(*pSet); + } + } +} + +/************************************************************************* +|* +|* IsUsed(), eine Vorlage gilt als benutzt, wenn sie von eingefuegten Objekten +|* oder von benutzten Vorlagen referenziert wird +|* +\************************************************************************/ + +BOOL SdStyleSheet::IsUsed() const +{ + BOOL bResult = FALSE; + + USHORT nListenerCount = GetListenerCount(); + if (nListenerCount > 0) + { + for (USHORT n = 0; n < nListenerCount; n++) + { + SfxListener* pListener = GetListener(n); + if( pListener == this ) + continue; + + // NULL-Pointer ist im Listener-Array erlaubt + if (pListener && pListener->ISA(SdrAttrObj)) + { + bResult = ((SdrAttrObj*)pListener)->IsInserted(); + } + else if (pListener && pListener->ISA(SfxStyleSheet)) + { + bResult = ((SfxStyleSheet*)pListener)->IsUsed(); + } + if (bResult) + break; + } + } + + if( !bResult ) + { + MutexGuard aGuard( mrBHelper.rMutex ); + + OInterfaceContainerHelper * pContainer = mrBHelper.getContainer( XModifyListener::static_type() ); + if( pContainer ) + { + Sequence< Reference< XInterface > > aModifyListeners( pContainer->getElements() ); + Reference< XInterface > *p = aModifyListeners.getArray(); + sal_Int32 nCount = aModifyListeners.getLength(); + while( nCount-- && !bResult ) + { + Reference< XStyle > xStyle( *p++, UNO_QUERY ); + if( xStyle.is() ) + bResult = xStyle->isInUse(); + } + } + } + return bResult; +} + +/************************************************************************* +|* +|* das StyleSheet ermitteln, fuer das dieses StyleSheet steht +|* +\************************************************************************/ + +SdStyleSheet* SdStyleSheet::GetRealStyleSheet() const +{ + String aRealStyle; + String aSep( RTL_CONSTASCII_USTRINGPARAM( SD_LT_SEPARATOR )); + SdStyleSheet* pRealStyle = NULL; + SdDrawDocument* pDoc = ((SdStyleSheetPool&) rPool).GetDoc(); + + ::sd::DrawViewShell* pDrawViewShell = 0; + + ::sd::ViewShellBase* pBase = dynamic_cast< ::sd::ViewShellBase* >( SfxViewShell::Current() ); + if( pBase ) + pDrawViewShell = dynamic_cast< ::sd::DrawViewShell* >( pBase->GetMainViewShell().get() ); + + if (pDrawViewShell && pDrawViewShell->GetDoc() == pDoc) + { + SdPage* pPage = pDrawViewShell->getCurrentPage(); + if( pPage ) + { + aRealStyle = pPage->GetLayoutName(); + // cut after seperator string + aRealStyle.Erase(aRealStyle.Search(aSep) + aSep.Len()); + } + } + + if (aRealStyle.Len() == 0) + { + SdPage* pPage = pDoc->GetSdPage(0, PK_STANDARD); + + if (pPage) + { + aRealStyle = pDoc->GetSdPage(0, PK_STANDARD)->GetLayoutName(); + } + else + { + // Noch keine Seite vorhanden + // Dieses kann beim Aktualisieren vonDokumentvorlagen vorkommen + SfxStyleSheetIterator aIter(&rPool, SD_STYLE_FAMILY_MASTERPAGE); + SfxStyleSheetBase* pSheet = aIter.First(); + if( pSheet ) + aRealStyle = pSheet->GetName(); + } + + aRealStyle.Erase(aRealStyle.Search(aSep) + aSep.Len()); + } + + // jetzt vom Namen (landessprachlich angepasst) auf den internen + // Namen (unabhaengig von der Landessprache) mappen + String aInternalName; + + if (aName == String(SdResId(STR_PSEUDOSHEET_TITLE))) + { + aInternalName = String(SdResId(STR_LAYOUT_TITLE)); + } + else if (aName == String(SdResId(STR_PSEUDOSHEET_SUBTITLE))) + { + aInternalName = String(SdResId(STR_LAYOUT_SUBTITLE)); + } + else if (aName == String(SdResId(STR_PSEUDOSHEET_BACKGROUND))) + { + aInternalName = String(SdResId(STR_LAYOUT_BACKGROUND)); + } + else if (aName == String(SdResId(STR_PSEUDOSHEET_BACKGROUNDOBJECTS))) + { + aInternalName = String(SdResId(STR_LAYOUT_BACKGROUNDOBJECTS)); + } + else if (aName == String(SdResId(STR_PSEUDOSHEET_NOTES))) + { + aInternalName = String(SdResId(STR_LAYOUT_NOTES)); + } + else + { + String aOutlineStr(SdResId(STR_PSEUDOSHEET_OUTLINE)); + USHORT nPos = aName.Search(aOutlineStr); + if (nPos != STRING_NOTFOUND) + { + String aNumStr(aName.Copy(aOutlineStr.Len())); + aInternalName = String(SdResId(STR_LAYOUT_OUTLINE)); + aInternalName += aNumStr; + } + } + + aRealStyle += aInternalName; + pRealStyle = static_cast< SdStyleSheet* >( rPool.Find(aRealStyle, SD_STYLE_FAMILY_MASTERPAGE) ); + +#ifdef DBG_UTIL + if( !pRealStyle ) + { + SfxStyleSheetIterator aIter(&rPool, SD_STYLE_FAMILY_MASTERPAGE); + if( aIter.Count() > 0 ) + // StyleSheet not found, but pool already loaded + DBG_ASSERT(pRealStyle, "Internal StyleSheet not found"); + } +#endif + + return pRealStyle; +} + +/************************************************************************* +|* +|* das PseudoStyleSheet ermitteln, durch das dieses StyleSheet vertreten wird +|* +\************************************************************************/ + +SdStyleSheet* SdStyleSheet::GetPseudoStyleSheet() const +{ + SdStyleSheet* pPseudoStyle = NULL; + String aSep( RTL_CONSTASCII_USTRINGPARAM( SD_LT_SEPARATOR )); + String aStyleName(aName); + // ohne Layoutnamen und Separator + aStyleName.Erase(0, aStyleName.Search(aSep) + aSep.Len()); + + if (aStyleName == String(SdResId(STR_LAYOUT_TITLE))) + { + aStyleName = String(SdResId(STR_PSEUDOSHEET_TITLE)); + } + else if (aStyleName == String(SdResId(STR_LAYOUT_SUBTITLE))) + { + aStyleName = String(SdResId(STR_PSEUDOSHEET_SUBTITLE)); + } + else if (aStyleName == String(SdResId(STR_LAYOUT_BACKGROUND))) + { + aStyleName = String(SdResId(STR_PSEUDOSHEET_BACKGROUND)); + } + else if (aStyleName == String(SdResId(STR_LAYOUT_BACKGROUNDOBJECTS))) + { + aStyleName = String(SdResId(STR_PSEUDOSHEET_BACKGROUNDOBJECTS)); + } + else if (aStyleName == String(SdResId(STR_LAYOUT_NOTES))) + { + aStyleName = String(SdResId(STR_PSEUDOSHEET_NOTES)); + } + else + { + String aOutlineStr((SdResId(STR_LAYOUT_OUTLINE))); + USHORT nPos = aStyleName.Search(aOutlineStr); + if (nPos != STRING_NOTFOUND) + { + String aNumStr(aStyleName.Copy(aOutlineStr.Len())); + aStyleName = String(SdResId(STR_PSEUDOSHEET_OUTLINE)); + aStyleName += aNumStr; + } + } + + pPseudoStyle = static_cast<SdStyleSheet*>(rPool.Find(aStyleName, SD_STYLE_FAMILY_PSEUDO)); + DBG_ASSERT(pPseudoStyle, "PseudoStyleSheet nicht gefunden"); + + return pPseudoStyle; +} + + +/************************************************************************* +|* +|* Notify +|* +\************************************************************************/ + +void SdStyleSheet::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) +{ + // erstmal die Basisklassenfunktionalitaet + SfxStyleSheet::Notify(rBC, rHint); + + // wenn der Stellvertreter ein Notify bezueglich geaenderter Attribute + // bekommt, sorgt er dafuer, dass das eigentlich gemeinte StyleSheet + // broadcastet + SfxSimpleHint* pSimple = PTR_CAST(SfxSimpleHint, &rHint); + ULONG nId = pSimple == NULL ? 0 : pSimple->GetId(); + if (nId == SFX_HINT_DATACHANGED && nFamily == SD_STYLE_FAMILY_PSEUDO) + { + SdStyleSheet* pRealStyle = GetRealStyleSheet(); + if (pRealStyle) + pRealStyle->Broadcast(rHint); + } +} + +/************************************************************************* +|* AdjustToFontHeight passt die Bulletbreite und den linken Texteinzug +|* des uebergebenen ItemSets dessen Fonthoehe an. Die neuen Werte werden so +|* berechnet, dass das Verhaeltnis zur Fonthoehe so ist wie im StyleSheet. +|* +|* bOnlyMissingItems legt fest, ob lediglich nicht gesetzte Items ergaenzt +|* (TRUE) oder explizit gesetzte Items ueberschreiben werden sollen (FALSE) +|* +\************************************************************************/ + +void SdStyleSheet::AdjustToFontHeight(SfxItemSet& rSet, BOOL bOnlyMissingItems) +{ + // Bulletbreite und Texteinzug an neue Fonthoehe + // anpassen, wenn sie nicht explizit gesetzt wurden + SfxStyleFamily eFamily = nFamily; + String aStyleName(aName); + if (eFamily == SD_STYLE_FAMILY_PSEUDO) + { + SfxStyleSheet* pRealStyle = GetRealStyleSheet(); + eFamily = pRealStyle->GetFamily(); + aStyleName = pRealStyle->GetName(); + } + + if (eFamily == SD_STYLE_FAMILY_MASTERPAGE && + aStyleName.Search(String(SdResId(STR_LAYOUT_OUTLINE))) != STRING_NOTFOUND && + rSet.GetItemState(EE_CHAR_FONTHEIGHT) == SFX_ITEM_SET) + { + const SfxItemSet* pCurSet = &GetItemSet(); + UINT32 nNewHeight = ((SvxFontHeightItem&)rSet.Get(EE_CHAR_FONTHEIGHT)).GetHeight(); + UINT32 nOldHeight = ((SvxFontHeightItem&)pCurSet->Get(EE_CHAR_FONTHEIGHT)).GetHeight(); + + if (rSet.GetItemState(EE_PARA_BULLET) != SFX_ITEM_SET || !bOnlyMissingItems) + { + const SvxBulletItem& rBItem = (const SvxBulletItem&)pCurSet->Get(EE_PARA_BULLET); + double fBulletFraction = double(rBItem.GetWidth()) / nOldHeight; + SvxBulletItem aNewBItem(rBItem); + aNewBItem.SetWidth((UINT32)(fBulletFraction * nNewHeight)); + rSet.Put(aNewBItem); + } + + if (rSet.GetItemState(EE_PARA_LRSPACE) != SFX_ITEM_SET || !bOnlyMissingItems) + { + const SvxLRSpaceItem& rLRItem = (const SvxLRSpaceItem&)pCurSet->Get(EE_PARA_LRSPACE); + double fIndentFraction = double(rLRItem.GetTxtLeft()) / nOldHeight; + SvxLRSpaceItem aNewLRItem(rLRItem); + aNewLRItem.SetTxtLeft((USHORT)(fIndentFraction * nNewHeight)); + double fFirstIndentFraction = double(rLRItem.GetTxtFirstLineOfst()) / nOldHeight; + aNewLRItem.SetTxtFirstLineOfst((short)(fFirstIndentFraction * nNewHeight)); + rSet.Put(aNewLRItem); + } + + if (rSet.GetItemState(EE_PARA_ULSPACE) != SFX_ITEM_SET || !bOnlyMissingItems) + { + const SvxULSpaceItem& rULItem = (const SvxULSpaceItem&)pCurSet->Get(EE_PARA_ULSPACE); + SvxULSpaceItem aNewULItem(rULItem); + double fLowerFraction = double(rULItem.GetLower()) / nOldHeight; + aNewULItem.SetLower((USHORT)(fLowerFraction * nNewHeight)); + double fUpperFraction = double(rULItem.GetUpper()) / nOldHeight; + aNewULItem.SetUpper((USHORT)(fUpperFraction * nNewHeight)); + rSet.Put(aNewULItem); + } + } +} + +// -------------------------------------------------------------------- + +BOOL SdStyleSheet::HasFollowSupport() const +{ + return FALSE; +} + +// -------------------------------------------------------------------- + +BOOL SdStyleSheet::HasParentSupport() const +{ + return TRUE; +} + +// -------------------------------------------------------------------- + +BOOL SdStyleSheet::HasClearParentSupport() const +{ + return TRUE; +} + +// -------------------------------------------------------------------- + +BOOL SdStyleSheet::SetName( const UniString& rName ) +{ + return SfxStyleSheet::SetName( rName ); +} + +// -------------------------------------------------------------------- + +void SdStyleSheet::SetHelpId( const String& r, ULONG nId ) +{ + SfxStyleSheet::SetHelpId( r, nId ); + + if( (nId >= HID_PSEUDOSHEET_OUTLINE1) && ( nId <= HID_PSEUDOSHEET_OUTLINE9 ) ) + { + msApiName = OUString( RTL_CONSTASCII_USTRINGPARAM("outline") ); + msApiName += OUString( (sal_Unicode)( '1' + (nId - HID_PSEUDOSHEET_OUTLINE1) ) ); + } + else + { + static struct ApiNameMap + { + const sal_Char* mpApiName; + sal_uInt32 mnApiNameLength; + sal_uInt32 mnHelpId; + } + pApiNameMap[] = + { + { RTL_CONSTASCII_STRINGPARAM( "title" ), HID_PSEUDOSHEET_TITLE }, + { RTL_CONSTASCII_STRINGPARAM( "subtitle" ), HID_PSEUDOSHEET_SUBTITLE }, + { RTL_CONSTASCII_STRINGPARAM( "background" ), HID_PSEUDOSHEET_BACKGROUND }, + { RTL_CONSTASCII_STRINGPARAM( "backgroundobjects" ),HID_PSEUDOSHEET_BACKGROUNDOBJECTS }, + { RTL_CONSTASCII_STRINGPARAM( "notes" ), HID_PSEUDOSHEET_NOTES }, + { RTL_CONSTASCII_STRINGPARAM( "standard" ), HID_STANDARD_STYLESHEET_NAME }, + { RTL_CONSTASCII_STRINGPARAM( "objectwitharrow" ), HID_POOLSHEET_OBJWITHARROW }, + { RTL_CONSTASCII_STRINGPARAM( "objectwithshadow" ), HID_POOLSHEET_OBJWITHSHADOW }, + { RTL_CONSTASCII_STRINGPARAM( "objectwithoutfill" ),HID_POOLSHEET_OBJWITHOUTFILL }, + { RTL_CONSTASCII_STRINGPARAM( "text" ), HID_POOLSHEET_TEXT }, + { RTL_CONSTASCII_STRINGPARAM( "textbody" ), HID_POOLSHEET_TEXTBODY }, + { RTL_CONSTASCII_STRINGPARAM( "textbodyjustfied" ), HID_POOLSHEET_TEXTBODY_JUSTIFY }, + { RTL_CONSTASCII_STRINGPARAM( "textbodyindent" ), HID_POOLSHEET_TEXTBODY_INDENT }, + { RTL_CONSTASCII_STRINGPARAM( "title" ), HID_POOLSHEET_TITLE }, + { RTL_CONSTASCII_STRINGPARAM( "title1" ), HID_POOLSHEET_TITLE1 }, + { RTL_CONSTASCII_STRINGPARAM( "title2" ), HID_POOLSHEET_TITLE2 }, + { RTL_CONSTASCII_STRINGPARAM( "headline" ), HID_POOLSHEET_HEADLINE }, + { RTL_CONSTASCII_STRINGPARAM( "headline1" ), HID_POOLSHEET_HEADLINE1 }, + { RTL_CONSTASCII_STRINGPARAM( "headline2" ), HID_POOLSHEET_HEADLINE2 }, + { RTL_CONSTASCII_STRINGPARAM( "measure" ), HID_POOLSHEET_MEASURE }, + { 0, 0, 0 } + }; + + ApiNameMap* p = pApiNameMap; + while( p->mpApiName ) + { + if( nId == p->mnHelpId ) + { + msApiName = OUString( p->mpApiName, p->mnApiNameLength, RTL_TEXTENCODING_ASCII_US ); + break; + } + p++; + } + } +} + +// -------------------------------------------------------------------- + +OUString SdStyleSheet::GetFamilyString( SfxStyleFamily eFamily ) +{ + switch( eFamily ) + { + case SD_STYLE_FAMILY_CELL: + return OUString( RTL_CONSTASCII_USTRINGPARAM( "cell" ) ); + default: + DBG_ERROR( "SdStyleSheet::GetFamilyString(), illegal family!" ); + case SD_STYLE_FAMILY_GRAPHICS: + return OUString( RTL_CONSTASCII_USTRINGPARAM( "graphics" ) ); + } +} + +// -------------------------------------------------------------------- + +void SdStyleSheet::throwIfDisposed() throw (RuntimeException) +{ + if( !mxPool.is() ) + throw DisposedException(); +} + +// -------------------------------------------------------------------- + +SdStyleSheet* SdStyleSheet::CreateEmptyUserStyle( SfxStyleSheetBasePool& rPool, SfxStyleFamily eFamily ) +{ + OUString aPrefix( RTL_CONSTASCII_USTRINGPARAM("user") ); + OUString aName; + sal_Int32 nIndex = 1; + do + { + aName = aPrefix + OUString::valueOf( nIndex++ ); + } + while( rPool.Find( aName, eFamily ) != 0 ); + + return new SdStyleSheet(aName, rPool, eFamily, SFXSTYLEBIT_USERDEF); +} + +// -------------------------------------------------------------------- +// XInterface +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheet::release( ) throw () +{ + if (osl_decrementInterlockedCount( &m_refCount ) == 0) + { + // restore reference count: + osl_incrementInterlockedCount( &m_refCount ); + if (! mrBHelper.bDisposed) try + { + dispose(); + } + catch (RuntimeException const& exc) + { // don't break throw () + OSL_ENSURE( + false, OUStringToOString( + exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); + static_cast<void>(exc); + } + OSL_ASSERT( mrBHelper.bDisposed ); + SdStyleSheetBase::release(); + } +} + +// -------------------------------------------------------------------- +// XComponent +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheet::dispose( ) throw (RuntimeException) +{ + ClearableMutexGuard aGuard( mrBHelper.rMutex ); + if (!mrBHelper.bDisposed && !mrBHelper.bInDispose) + { + mrBHelper.bInDispose = sal_True; + aGuard.clear(); + try + { + // side effect: keeping a reference to this + EventObject aEvt( static_cast< OWeakObject * >( this ) ); + try + { + mrBHelper.aLC.disposeAndClear( aEvt ); + disposing(); + } + catch (...) + { + MutexGuard aGuard2( mrBHelper.rMutex ); + // bDisposed and bInDispose must be set in this order: + mrBHelper.bDisposed = sal_True; + mrBHelper.bInDispose = sal_False; + throw; + } + MutexGuard aGuard2( mrBHelper.rMutex ); + // bDisposed and bInDispose must be set in this order: + mrBHelper.bDisposed = sal_True; + mrBHelper.bInDispose = sal_False; + } + catch (RuntimeException &) + { + throw; + } + catch (Exception & exc) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "unexpected UNO exception caught: ") ) + + exc.Message, Reference< XInterface >() ); + } + } +} + +// -------------------------------------------------------------------- + +void SdStyleSheet::disposing() +{ + mxPool.clear(); +} + +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheet::addEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException) +{ + ClearableMutexGuard aGuard( mrBHelper.rMutex ); + if (mrBHelper.bDisposed || mrBHelper.bInDispose) + { + aGuard.clear(); + EventObject aEvt( static_cast< OWeakObject * >( this ) ); + xListener->disposing( aEvt ); + } + else + { + mrBHelper.addListener( ::getCppuType( &xListener ), xListener ); + } +} + +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheet::removeEventListener( const Reference< XEventListener >& xListener ) throw (RuntimeException) +{ + mrBHelper.removeListener( ::getCppuType( &xListener ), xListener ); +} + +//------------------------------------------------------------------------ +// XModifyBroadcaster +//------------------------------------------------------------------------ + +void SAL_CALL SdStyleSheet::addModifyListener( const Reference< XModifyListener >& xListener ) throw (RuntimeException) +{ + ClearableMutexGuard aGuard( mrBHelper.rMutex ); + if (mrBHelper.bDisposed || mrBHelper.bInDispose) + { + aGuard.clear(); + EventObject aEvt( static_cast< OWeakObject * >( this ) ); + xListener->disposing( aEvt ); + } + else + { + if( !mpModifyListenerForewarder.get() ) + mpModifyListenerForewarder.reset( new ModifyListenerForewarder( this ) ); + mrBHelper.addListener( XModifyListener::static_type(), xListener ); + } +} + +//------------------------------------------------------------------------ + +void SAL_CALL SdStyleSheet::removeModifyListener( const Reference< XModifyListener >& xListener ) throw (RuntimeException) +{ + mrBHelper.removeListener( XModifyListener::static_type(), xListener ); +} + +//------------------------------------------------------------------------ + +void SdStyleSheet::notifyModifyListener() +{ + MutexGuard aGuard( mrBHelper.rMutex ); + + OInterfaceContainerHelper * pContainer = mrBHelper.getContainer( XModifyListener::static_type() ); + if( pContainer ) + { + EventObject aEvt( static_cast< OWeakObject * >( this ) ); + pContainer->forEach<XModifyListener>( boost::bind( &XModifyListener::modified, _1, boost::cref( aEvt ) ) ); + } +} + + +// -------------------------------------------------------------------- +// XServiceInfo +// -------------------------------------------------------------------- + +OUString SAL_CALL SdStyleSheet::getImplementationName() throw(RuntimeException) +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "SdStyleSheet" ) ); +} + +// -------------------------------------------------------------------- + +sal_Bool SAL_CALL SdStyleSheet::supportsService( const OUString& ServiceName ) throw(RuntimeException) +{ + return comphelper::ServiceInfoHelper::supportsService( ServiceName, getSupportedServiceNames() ); +} + +// -------------------------------------------------------------------- + +Sequence< OUString > SAL_CALL SdStyleSheet::getSupportedServiceNames() throw(RuntimeException) +{ + Sequence< OUString > aNameSequence( 10 ); + OUString* pStrings = aNameSequence.getArray(); + + *pStrings++ = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.style.Style" ) ); + *pStrings++ = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.FillProperties" ) ); + *pStrings++ = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.LineProperties" ) ); + *pStrings++ = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.ShadowProperties" ) ); + *pStrings++ = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.ConnectorProperties" ) ); + *pStrings++ = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.MeasureProperties" ) ); + *pStrings++ = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.style.ParagraphProperties" ) ); + *pStrings++ = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.style.CharacterProperties" ) ); + *pStrings++ = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.TextProperties" ) ); + *pStrings++ = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.Text" ) ); + + return aNameSequence; +} + +// -------------------------------------------------------------------- +// XNamed +// -------------------------------------------------------------------- + +OUString SAL_CALL SdStyleSheet::getName() throw(RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + return GetApiName(); +} + +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheet::setName( const OUString& rName ) throw(RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + if( IsUserDefined() ) + { + if( SetName( rName ) ) + { + msApiName = rName; + Broadcast(SfxSimpleHint(SFX_HINT_DATACHANGED)); + } + } +} + +// -------------------------------------------------------------------- +// XStyle +// -------------------------------------------------------------------- + +sal_Bool SAL_CALL SdStyleSheet::isUserDefined() throw(RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + return IsUserDefined() ? sal_True : sal_False; +} + +// -------------------------------------------------------------------- + +sal_Bool SAL_CALL SdStyleSheet::isInUse() throw(RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + return IsUsed() ? sal_True : sal_False; +} + +// -------------------------------------------------------------------- + +OUString SAL_CALL SdStyleSheet::getParentStyle() throw(RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if( GetParent().Len() ) + { + SdStyleSheet* pParentStyle = static_cast< SdStyleSheet* >( mxPool->Find( GetParent(), nFamily ) ); + if( pParentStyle ) + return pParentStyle->msApiName; + } + return OUString(); +} + +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheet::setParentStyle( const OUString& rParentName ) throw(NoSuchElementException, RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + if( IsUserDefined() ) + { + if( rParentName.getLength() ) + { + const SfxStyles& rStyles = mxPool->GetStyles(); + + for( SfxStyles::const_iterator iter( rStyles.begin() ); iter != rStyles.end(); ++iter ) + { + SdStyleSheet* pStyle = static_cast< SdStyleSheet* >( (*iter).get() ); + if( pStyle && (pStyle->nFamily == nFamily) && (pStyle->msApiName == rParentName) ) + { + if( pStyle != this ) + SetParent( pStyle->GetName() ); + return; + } + } + throw NoSuchElementException(); + } + else + { + SetParent( rParentName ); + } + } +} + +// -------------------------------------------------------------------- +// XPropertySet +// -------------------------------------------------------------------- + +Reference< XPropertySetInfo > SdStyleSheet::getPropertySetInfo() throw(RuntimeException) +{ + throwIfDisposed(); + static Reference< XPropertySetInfo > xInfo; + if( !xInfo.is() ) + xInfo = GetStylePropertySet().getPropertySetInfo(); + return xInfo; +} + +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheet::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + SolarMutexGuard aGuard; + throwIfDisposed(); + + const SfxItemPropertySimpleEntry* pEntry = getPropertyMapEntry( aPropertyName ); + if( pEntry == NULL ) + { + throw UnknownPropertyException(); + } + else + { + if( pEntry->nWID == SDRATTR_TEXTDIRECTION ) + return; // not yet implemented for styles + + if( pEntry->nWID == WID_STYLE_FAMILY ) + throw PropertyVetoException(); + + if( (pEntry->nWID == EE_PARA_NUMBULLET) && (GetFamily() == SD_STYLE_FAMILY_MASTERPAGE) ) + { + String aStr; + const sal_uInt32 nTempHelpId = GetHelpId( aStr ); + + if( (nTempHelpId >= HID_PSEUDOSHEET_OUTLINE2) && (nTempHelpId <= HID_PSEUDOSHEET_OUTLINE9) ) + return; + } + + SfxItemSet &rStyleSet = GetItemSet(); + + if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE ) + { + BitmapMode eMode; + if( aValue >>= eMode ) + { + rStyleSet.Put( XFillBmpStretchItem( eMode == BitmapMode_STRETCH ) ); + rStyleSet.Put( XFillBmpTileItem( eMode == BitmapMode_REPEAT ) ); + return; + } + throw IllegalArgumentException(); + } + + SfxItemSet aSet( GetPool().GetPool(), pEntry->nWID, pEntry->nWID); + aSet.Put( rStyleSet ); + + if( !aSet.Count() ) + { + if( EE_PARA_NUMBULLET == pEntry->nWID ) + { + Font aBulletFont; + SdStyleSheetPool::PutNumBulletItem( this, aBulletFont ); + aSet.Put( rStyleSet ); + } + else + { + aSet.Put( GetPool().GetPool().GetDefaultItem( pEntry->nWID ) ); + } + } + + if( pEntry->nMemberId == MID_NAME && + ( pEntry->nWID == XATTR_FILLBITMAP || pEntry->nWID == XATTR_FILLGRADIENT || + pEntry->nWID == XATTR_FILLHATCH || pEntry->nWID == XATTR_FILLFLOATTRANSPARENCE || + pEntry->nWID == XATTR_LINESTART || pEntry->nWID == XATTR_LINEEND || pEntry->nWID == XATTR_LINEDASH) ) + { + OUString aTempName; + if(!(aValue >>= aTempName )) + throw IllegalArgumentException(); + + SvxShape::SetFillAttribute( pEntry->nWID, aTempName, aSet ); + } + else if(!SvxUnoTextRangeBase::SetPropertyValueHelper( aSet, pEntry, aValue, aSet )) + { + SvxItemPropertySet_setPropertyValue( GetStylePropertySet(), pEntry, aValue, aSet ); + } + + rStyleSet.Put( aSet ); + Broadcast(SfxSimpleHint(SFX_HINT_DATACHANGED)); + } +} + +// -------------------------------------------------------------------- + +Any SAL_CALL SdStyleSheet::getPropertyValue( const OUString& PropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + SolarMutexGuard aGuard; + + throwIfDisposed(); + + const SfxItemPropertySimpleEntry* pEntry = getPropertyMapEntry( PropertyName ); + if( pEntry == NULL ) + { + throw UnknownPropertyException(); + } + else + { + Any aAny; + + if( pEntry->nWID == WID_STYLE_FAMILY ) + { + if( nFamily == SD_STYLE_FAMILY_MASTERPAGE ) + { + const OUString aLayoutName( GetName() ); + aAny <<= aLayoutName.copy( 0, aLayoutName.indexOf(OUString( RTL_CONSTASCII_USTRINGPARAM(SD_LT_SEPARATOR) ) ) ); + } + else + { + aAny <<= GetFamilyString(nFamily); + } + } + else if( pEntry->nWID == WID_STYLE_DISPNAME ) + { + aAny <<= maDisplayName; + } + else if( pEntry->nWID == SDRATTR_TEXTDIRECTION ) + { + aAny <<= sal_False; + } + else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE ) + { + SfxItemSet &rStyleSet = GetItemSet(); + + XFillBmpStretchItem* pStretchItem = (XFillBmpStretchItem*)rStyleSet.GetItem(XATTR_FILLBMP_STRETCH); + XFillBmpTileItem* pTileItem = (XFillBmpTileItem*)rStyleSet.GetItem(XATTR_FILLBMP_TILE); + + if( pStretchItem && pTileItem ) + { + if( pTileItem->GetValue() ) + aAny <<= BitmapMode_REPEAT; + else if( pStretchItem->GetValue() ) + aAny <<= BitmapMode_STRETCH; + else + aAny <<= BitmapMode_NO_REPEAT; + } + } + else + { + SfxItemSet aSet( GetPool().GetPool(), pEntry->nWID, pEntry->nWID); + + const SfxPoolItem* pItem; + SfxItemSet& rStyleSet = GetItemSet(); + + if( rStyleSet.GetItemState( pEntry->nWID, sal_True, &pItem ) == SFX_ITEM_SET ) + aSet.Put( *pItem ); + + if( !aSet.Count() ) + aSet.Put( GetPool().GetPool().GetDefaultItem( pEntry->nWID ) ); + + if(SvxUnoTextRangeBase::GetPropertyValueHelper( aSet, pEntry, aAny )) + return aAny; + + // Hole Wert aus ItemSet + aAny = SvxItemPropertySet_getPropertyValue( GetStylePropertySet(),pEntry, aSet ); + } + + if( *pEntry->pType != aAny.getValueType() ) + { + // since the sfx uint16 item now exports a sal_Int32, we may have to fix this here + if( ( *pEntry->pType == ::getCppuType((const sal_Int16*)0)) && aAny.getValueType() == ::getCppuType((const sal_Int32*)0) ) + { + sal_Int32 nValue = 0; + aAny >>= nValue; + aAny <<= (sal_Int16)nValue; + } + else + { + DBG_ERROR("SvxShape::GetAnyForItem() Returnvalue has wrong Type!" ); + } + } + + return aAny; + } +} + +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheet::addPropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) {} +void SAL_CALL SdStyleSheet::removePropertyChangeListener( const OUString& , const Reference< XPropertyChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) {} +void SAL_CALL SdStyleSheet::addVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) {} +void SAL_CALL SdStyleSheet::removeVetoableChangeListener( const OUString& , const Reference< XVetoableChangeListener >& ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) {} + +// -------------------------------------------------------------------- +// XPropertyState +// -------------------------------------------------------------------- + +PropertyState SAL_CALL SdStyleSheet::getPropertyState( const OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException) +{ + SolarMutexGuard aGuard; + + throwIfDisposed(); + + const SfxItemPropertySimpleEntry* pEntry = getPropertyMapEntry( PropertyName ); + + if( pEntry == NULL ) + throw UnknownPropertyException(); + + if( pEntry->nWID == WID_STYLE_FAMILY ) + { + return PropertyState_DIRECT_VALUE; + } + else if( pEntry->nWID == SDRATTR_TEXTDIRECTION ) + { + return PropertyState_DEFAULT_VALUE; + } + else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE ) + { + const SfxItemSet& rSet = GetItemSet(); + + if( rSet.GetItemState( XATTR_FILLBMP_STRETCH, false ) == SFX_ITEM_SET || + rSet.GetItemState( XATTR_FILLBMP_TILE, false ) == SFX_ITEM_SET ) + { + return PropertyState_DIRECT_VALUE; + } + else + { + return PropertyState_AMBIGUOUS_VALUE; + } + } + else + { + SfxItemSet &rStyleSet = GetItemSet(); + + PropertyState eState; + + switch( rStyleSet.GetItemState( pEntry->nWID, sal_False ) ) + { + case SFX_ITEM_READONLY: + case SFX_ITEM_SET: + eState = PropertyState_DIRECT_VALUE; + break; + case SFX_ITEM_DEFAULT: + eState = PropertyState_DEFAULT_VALUE; + break; + default: + eState = PropertyState_AMBIGUOUS_VALUE; + break; + } + + // if a item is set, this doesn't mean we want it :) + if( ( PropertyState_DIRECT_VALUE == eState ) ) + { + switch( pEntry->nWID ) + { + case XATTR_FILLBITMAP: + case XATTR_FILLGRADIENT: + case XATTR_FILLHATCH: + case XATTR_FILLFLOATTRANSPARENCE: + case XATTR_LINEEND: + case XATTR_LINESTART: + case XATTR_LINEDASH: + { + NameOrIndex* pItem = (NameOrIndex*)rStyleSet.GetItem((USHORT)pEntry->nWID); + if( ( pItem == NULL ) || ( pItem->GetName().Len() == 0) ) + eState = PropertyState_DEFAULT_VALUE; + } + } + } + + return eState; + } +} + +// -------------------------------------------------------------------- + +Sequence< PropertyState > SAL_CALL SdStyleSheet::getPropertyStates( const Sequence< OUString >& aPropertyName ) throw(UnknownPropertyException, RuntimeException) +{ + SolarMutexGuard aGuard; + + throwIfDisposed(); + + sal_Int32 nCount = aPropertyName.getLength(); + const OUString* pNames = aPropertyName.getConstArray(); + + Sequence< PropertyState > aPropertyStateSequence( nCount ); + PropertyState* pState = aPropertyStateSequence.getArray(); + + while( nCount-- ) + *pState++ = getPropertyState( *pNames++ ); + + return aPropertyStateSequence; +} + +// -------------------------------------------------------------------- + +void SAL_CALL SdStyleSheet::setPropertyToDefault( const OUString& PropertyName ) throw(UnknownPropertyException, RuntimeException) +{ + SolarMutexGuard aGuard; + + throwIfDisposed(); + + const SfxItemPropertySimpleEntry* pEntry = getPropertyMapEntry( PropertyName ); + if( pEntry == NULL ) + throw UnknownPropertyException(); + + SfxItemSet &rStyleSet = GetItemSet(); + + if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE ) + { + rStyleSet.ClearItem( XATTR_FILLBMP_STRETCH ); + rStyleSet.ClearItem( XATTR_FILLBMP_TILE ); + } + else + { + rStyleSet.ClearItem( pEntry->nWID ); + } + Broadcast(SfxSimpleHint(SFX_HINT_DATACHANGED)); +} + +// -------------------------------------------------------------------- + +Any SAL_CALL SdStyleSheet::getPropertyDefault( const OUString& aPropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + SolarMutexGuard aGuard; + + throwIfDisposed(); + + const SfxItemPropertySimpleEntry* pEntry = getPropertyMapEntry( aPropertyName ); + if( pEntry == NULL ) + throw UnknownPropertyException(); + Any aRet; + if( pEntry->nWID == WID_STYLE_FAMILY ) + { + aRet <<= GetFamilyString(nFamily); + } + else if( pEntry->nWID == SDRATTR_TEXTDIRECTION ) + { + aRet <<= sal_False; + } + else if( pEntry->nWID == OWN_ATTR_FILLBMP_MODE ) + { + aRet <<= BitmapMode_REPEAT; + } + else + { + SfxItemPool& rMyPool = GetPool().GetPool(); + SfxItemSet aSet( rMyPool, pEntry->nWID, pEntry->nWID); + aSet.Put( rMyPool.GetDefaultItem( pEntry->nWID ) ); + aRet = SvxItemPropertySet_getPropertyValue( GetStylePropertySet(), pEntry, aSet ); + } + return aRet; +} + +// -------------------------------------------------------------------- + +/** this is used because our property map is not sorted yet */ +const SfxItemPropertySimpleEntry* SdStyleSheet::getPropertyMapEntry( const OUString& rPropertyName ) const throw() +{ + return GetStylePropertySet().getPropertyMapEntry(rPropertyName); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/text/makefile.mk b/sd/source/core/text/makefile.mk new file mode 100644 index 000000000000..73b3e8a4ae44 --- /dev/null +++ b/sd/source/core/text/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PROJECTPCH=sd +PROJECTPCHSOURCE=$(PRJ)$/util$/sd +PRJNAME=sd +TARGET=text +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = $(SLO)$/textapi.obj + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sd/source/core/text/textapi.cxx b/sd/source/core/text/textapi.cxx new file mode 100644 index 000000000000..6e146f60d836 --- /dev/null +++ b/sd/source/core/text/textapi.cxx @@ -0,0 +1,298 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include <com/sun/star/text/XTextField.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include <textapi.hxx> +#include <drawdoc.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/outlobj.hxx> +#include "Outliner.hxx" +#include <svx/svdpool.hxx> + +using ::rtl::OUString; + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; + +namespace sd { + +class UndoTextAPIChanged : public SdrUndoAction +{ +public: + UndoTextAPIChanged( SdrModel& rModel, TextApiObject* pTextObj ); + ~UndoTextAPIChanged(); + + virtual void Undo(); + virtual void Redo(); + +protected: + OutlinerParaObject* mpOldText; + OutlinerParaObject* mpNewText; + rtl::Reference< TextApiObject > mxTextObj; +}; + +UndoTextAPIChanged::UndoTextAPIChanged(SdrModel& rModel, TextApiObject* pTextObj ) +: SdrUndoAction( rModel ) +, mpOldText( pTextObj->CreateText() ) +, mpNewText( 0 ) +, mxTextObj( pTextObj ) +{ +} + +UndoTextAPIChanged::~UndoTextAPIChanged() +{ + delete mpOldText; + delete mpNewText; +} + +void UndoTextAPIChanged::Undo() +{ + if( !mpNewText ) + mpNewText = mxTextObj->CreateText(); + + mxTextObj->SetText( *mpOldText ); +} + +void UndoTextAPIChanged::Redo() +{ + if( mpNewText ) + { + mxTextObj->SetText( *mpNewText ); + } +} + +struct TextAPIEditSource_Impl +{ + // needed for "internal" refcounting + SdDrawDocument* mpDoc; + Outliner* mpOutliner; + SvxOutlinerForwarder* mpTextForwarder; + sal_Int32 mnRef; +}; + +class TextAPIEditSource : public SvxEditSource +{ + TextAPIEditSource_Impl* pImpl; + + virtual SvxEditSource* Clone() const; + virtual SvxTextForwarder* GetTextForwarder(); + virtual void UpdateData(); + explicit TextAPIEditSource( const TextAPIEditSource& rSource ); + +public: + TextAPIEditSource(SdDrawDocument* pDoc); + virtual ~TextAPIEditSource(); + + void Dispose(); + void SetText( OutlinerParaObject& rText ); + OutlinerParaObject* CreateText(); + String GetText(); + SdDrawDocument* GetDoc() { return pImpl->mpDoc; } +}; + +const SvxItemPropertySet* ImplGetSdTextPortionPropertyMap() +{ + static const SfxItemPropertyMapEntry aSdTextPortionPropertyEntries[] = + { + SVX_UNOEDIT_CHAR_PROPERTIES, + SVX_UNOEDIT_FONT_PROPERTIES, + SVX_UNOEDIT_OUTLINER_PROPERTIES, + SVX_UNOEDIT_PARA_PROPERTIES, + {MAP_CHAR_LEN("TextField"), EE_FEATURE_FIELD, &::getCppuType((const Reference< XTextField >*)0), PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN("TextPortionType"), WID_PORTIONTYPE, &::getCppuType((const OUString*)0), PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN("TextUserDefinedAttributes"), EE_CHAR_XMLATTRIBS, &::getCppuType((const Reference< XNameContainer >*)0) , 0, 0}, + {MAP_CHAR_LEN("ParaUserDefinedAttributes"), EE_PARA_XMLATTRIBS, &::getCppuType((const Reference< XNameContainer >*)0) , 0, 0}, + {0,0,0,0,0,0} + }; + static SvxItemPropertySet aSdTextPortionPropertyMap( aSdTextPortionPropertyEntries, SdrObject::GetGlobalDrawObjectItemPool() ); + + return &aSdTextPortionPropertyMap; +} + +TextApiObject::TextApiObject( TextAPIEditSource* pEditSource ) +: SvxUnoText( pEditSource, ImplGetSdTextPortionPropertyMap(), Reference < XText >() ) +, mpSource(pEditSource) +{ +} + +TextApiObject::~TextApiObject() throw() +{ + dispose(); +} + +rtl::Reference< TextApiObject > TextApiObject::create( SdDrawDocument* pDoc ) +{ + rtl::Reference< TextApiObject > xRet( new TextApiObject( new TextAPIEditSource( pDoc ) ) ); + return xRet; +} + +void SAL_CALL TextApiObject::dispose() throw(RuntimeException) +{ + if( mpSource ) + { + mpSource->Dispose(); + delete mpSource; + mpSource = 0; + } + +} + +OutlinerParaObject* TextApiObject::CreateText() +{ + return mpSource->CreateText(); +} + +void TextApiObject::SetText( OutlinerParaObject& rText ) +{ + SdrModel* pModel = mpSource->GetDoc(); + if( pModel && pModel->IsUndoEnabled() ) + pModel->AddUndo( new UndoTextAPIChanged( *pModel, this ) ); + + mpSource->SetText( rText ); + maSelection.nStartPara = 0xffff; +} + +String TextApiObject::GetText() +{ + return mpSource->GetText(); +} + +TextApiObject* TextApiObject::getImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::text::XText >& xText ) +{ + TextApiObject* pImpl = dynamic_cast< TextApiObject* >( xText.get() ); + + if( !pImpl ) + pImpl = dynamic_cast< TextApiObject* >( SvxUnoTextBase::getImplementation( xText ) ); + + return pImpl; +} + +TextAPIEditSource::TextAPIEditSource( const TextAPIEditSource& rSource ) +: SvxEditSource( *this ) +{ + // shallow copy; uses internal refcounting + pImpl = rSource.pImpl; + pImpl->mnRef++; +} + +SvxEditSource* TextAPIEditSource::Clone() const +{ + return new TextAPIEditSource( *this ); +} + +void TextAPIEditSource::UpdateData() +{ + // data is kept in outliner all the time +} + +TextAPIEditSource::TextAPIEditSource(SdDrawDocument* pDoc) +: pImpl(new TextAPIEditSource_Impl) +{ + pImpl->mpDoc = pDoc; + pImpl->mpOutliner = 0; + pImpl->mpTextForwarder = 0; + pImpl->mnRef = 1; +} + +TextAPIEditSource::~TextAPIEditSource() +{ + if (!--pImpl->mnRef) + delete pImpl; +} + +void TextAPIEditSource::Dispose() +{ + pImpl->mpDoc=0; + delete pImpl->mpTextForwarder; + pImpl->mpTextForwarder = 0; + + delete pImpl->mpOutliner; + pImpl->mpOutliner = 0; +} + +SvxTextForwarder* TextAPIEditSource::GetTextForwarder() +{ + if( !pImpl->mpDoc ) + return 0; // mpDoc == 0 can be used to flag this as disposed + + if( !pImpl->mpOutliner ) + { + //init draw model first + pImpl->mpOutliner = new Outliner( pImpl->mpDoc, OUTLINERMODE_TEXTOBJECT ); + pImpl->mpDoc->SetCalcFieldValueHdl( pImpl->mpOutliner ); + } + + if( !pImpl->mpTextForwarder ) + pImpl->mpTextForwarder = new SvxOutlinerForwarder( *pImpl->mpOutliner, 0 ); + + return pImpl->mpTextForwarder; +} + +void TextAPIEditSource::SetText( OutlinerParaObject& rText ) +{ + if ( pImpl->mpDoc ) + { + if( !pImpl->mpOutliner ) + { + //init draw model first + pImpl->mpOutliner = new Outliner( pImpl->mpDoc, OUTLINERMODE_TEXTOBJECT ); + pImpl->mpDoc->SetCalcFieldValueHdl( pImpl->mpOutliner ); + } + + pImpl->mpOutliner->SetText( rText ); + } +} + +OutlinerParaObject* TextAPIEditSource::CreateText() +{ + if ( pImpl->mpDoc && pImpl->mpOutliner ) + return pImpl->mpOutliner->CreateParaObject(); + else + return 0; +} + +String TextAPIEditSource::GetText() +{ + if ( pImpl->mpDoc && pImpl->mpOutliner ) + return pImpl->mpOutliner->GetEditEngine().GetText(); + else + return String(); +} + +} // namespace sd + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/typemap.cxx b/sd/source/core/typemap.cxx new file mode 100644 index 000000000000..8518eac0d273 --- /dev/null +++ b/sd/source/core/typemap.cxx @@ -0,0 +1,136 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include "eetext.hxx" +#include <editeng/eeitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/cntritem.hxx> +#include <editeng/shdditem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/fontitem.hxx> +#include <svl/poolitem.hxx> +#include <editeng/tstpitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/protitem.hxx> +#include <svx/chrtitem.hxx> +#include <sfx2/msg.hxx> +#include <svl/globalnameitem.hxx> +#include <svx/hlnkitem.hxx> +#include <svx/postattr.hxx> +#include <editeng/editdata.hxx> +#include <svx/srchdlg.hxx> +#include <svx/rulritem.hxx> +#include <svx/clipfmtitem.hxx> +#include <svl/srchitem.hxx> +#include <editeng/sizeitem.hxx> +#include <editeng/svxenum.hxx> +#include <svx/algitem.hxx> +#include <svx/zoomitem.hxx> +#include <svx/pageitem.hxx> +#include <svx/svdattr.hxx> +#include <svx/grafctrl.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/bolnitem.hxx> +#include "sdattr.hxx" +#include <svx/zoomslideritem.hxx> +#include <editeng/memberids.hrc> +#include <svx/xftstit.hxx> +#include <svx/xlnwtit.hxx> +#include <svx/xlineit0.hxx> +#include <svx/xlnclit.hxx> +#include <svx/xlndsit.hxx> +#include <svx/xflclit.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xlnedit.hxx> +#include <svx/xlnstit.hxx> +#include <svx/xgrad.hxx> +#include <svx/xflgrit.hxx> +#include <svx/xflhtit.hxx> +#include <svx/xbtmpit.hxx> +#include <svx/xtextit0.hxx> +#include <svx/xftadit.hxx> +#include <svx/xftdiit.hxx> +#include <svx/xftmrit.hxx> +#include <svx/xftouit.hxx> +#include <svx/xftshit.hxx> +#include <svx/xftshcit.hxx> +#include <svx/xftshxy.hxx> +#include <svx/xftsfit.hxx> +#include <svx/xtextit0.hxx> +#include <avmedia/mediaitem.hxx> +#include <svx/drawitem.hxx> + +// #UndoRedo# +#include <svl/slstitm.hxx> + +#include <svl/lckbitem.hxx> + + +#define CharSetItem SfxUInt16Item +#define FontFamilyItem SfxUInt16Item +#define FontPitchItem SfxUInt16Item +#define FontAlignItem SfxUInt16Item +#define FontWeightItem SfxUInt16Item +#define FontUnderlineItem SfxUInt16Item +#define FontStrikeoutItem SfxUInt16Item +#define FontItalicItem SfxUInt16Item +#define SvxDbTypeItem SfxUInt16Item +#define SvxLineSpaceItem SfxUInt16Item +#define SvxInterLineSpaceItem SfxUInt16Item +#define SvxBreakItem SfxUInt16Item +#define BrushStyleItem SfxUInt16Item +#define SvxNumTypeItem SfxUInt16Item +#define SvxShadowLocationItem SfxUInt16Item +#define SvxDbTypeItem SfxUInt16Item +#define SvxDrawToolEnumItem SfxUInt16Item +#define SvxChooseControlItem SfxEnumItem +#define SvxDrawToolItem SfxUInt16Item +#define SvxCellHorJustifyEnumItem SfxUInt16Item +#define SvxCellVerJustifyEnumItem SfxUInt16Item +#define SvxCellOrientationEnumItem SfxUInt16Item +#define SvxLanguage SfxUInt16Item +#define OfaStringListItem SfxStringListItem +#define avmedia_MediaItem ::avmedia::MediaItem +#include <sfx2/tplpitem.hxx> +#include <svl/ptitem.hxx> +#include <svl/rectitem.hxx> + +#include <sfx2/frame.hxx> + +#define SFX_TYPEMAP +#include "sdslots.hxx" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/undo/makefile.mk b/sd/source/core/undo/makefile.mk new file mode 100644 index 000000000000..e9b3753b0b24 --- /dev/null +++ b/sd/source/core/undo/makefile.mk @@ -0,0 +1,50 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PROJECTPCH=sd +PROJECTPCHSOURCE=$(PRJ)$/util$/sd +PRJNAME=sd +TARGET=undo +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = $(SLO)$/undomanager.obj \ + $(SLO)$/undofactory.obj \ + $(SLO)$/undoobjects.obj + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sd/source/core/undo/undofactory.cxx b/sd/source/core/undo/undofactory.cxx new file mode 100644 index 000000000000..72ad5414e4d0 --- /dev/null +++ b/sd/source/core/undo/undofactory.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <tools/debug.hxx> + +#include "undo/undofactory.hxx" +#include "undo/undoobjects.hxx" + +using namespace sd; + +SdrUndoAction* UndoFactory::CreateUndoRemoveObject( SdrObject& rObject, bool bOrdNumDirect ) +{ + return new UndoRemoveObject( rObject, bOrdNumDirect ); +} + +SdrUndoAction* UndoFactory::CreateUndoDeleteObject( SdrObject& rObject, bool bOrdNumDirect ) +{ + return new UndoDeleteObject( rObject, bOrdNumDirect ); +} + +SdrUndoAction* UndoFactory::CreateUndoObjectSetText( SdrObject& rNewObj, sal_Int32 nText ) +{ + return new UndoObjectSetText( rNewObj, nText ); +} + +SdrUndoAction* UndoFactory::CreateUndoReplaceObject( SdrObject& rOldObject, SdrObject& rNewObject, bool bOrdNumDirect ) +{ + return new UndoReplaceObject( rOldObject, rNewObject, bOrdNumDirect ); +} + +SdrUndoAction* UndoFactory::CreateUndoGeoObject( SdrObject& rObject ) +{ + return new UndoGeoObject( rObject ); +} + +SdrUndoAction* UndoFactory::CreateUndoAttrObject( SdrObject& rObject, bool bStyleSheet1, bool bSaveText ) +{ + return new UndoAttrObject( rObject, bStyleSheet1, bSaveText ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/undo/undomanager.cxx b/sd/source/core/undo/undomanager.cxx new file mode 100644 index 000000000000..05892631c07f --- /dev/null +++ b/sd/source/core/undo/undomanager.cxx @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <tools/debug.hxx> +#include "undo/undomanager.hxx" + +using namespace sd; + +UndoManager::UndoManager( USHORT nMaxUndoActionCount /* = 20 */ ) +: SfxUndoManager( nMaxUndoActionCount ) +, mnListLevel( 0 ) +, mpLinkedUndoManager(NULL) +{ +} + +void UndoManager::EnterListAction(const UniString &rComment, const UniString& rRepeatComment, USHORT nId /* =0 */) +{ + if( !isInUndo() ) + { + ClearLinkedRedoActions(); + mnListLevel++; + SfxUndoManager::EnterListAction( rComment, rRepeatComment, nId ); + } +} + +void UndoManager::LeaveListAction() +{ + if( !isInUndo() ) + { + SfxUndoManager::LeaveListAction(); + if( mnListLevel ) + { + mnListLevel--; + } + else + { + DBG_ERROR("sd::UndoManager::LeaveListAction(), no open list action!" ); + } + } +} + +void UndoManager::AddUndoAction( SfxUndoAction *pAction, BOOL bTryMerg /* = FALSE */ ) +{ + if( !isInUndo() ) + { + ClearLinkedRedoActions(); + SfxUndoManager::AddUndoAction( pAction, bTryMerg ); + } + else + { + delete pAction; + } +} + + +BOOL UndoManager::Undo( USHORT nCount ) +{ + ScopeLockGuard aGuard( maIsInUndoLock ); + return SfxUndoManager::Undo( nCount ); +} + +BOOL UndoManager::Redo( USHORT nCount ) +{ + ScopeLockGuard aGuard( maIsInUndoLock ); + return SfxUndoManager::Redo( nCount ); +} + + + + +void UndoManager::SetLinkedUndoManager (SfxUndoManager* pLinkedUndoManager) +{ + mpLinkedUndoManager = pLinkedUndoManager; +} + + + + +void UndoManager::ClearLinkedRedoActions (void) +{ + if (mpLinkedUndoManager != NULL) + mpLinkedUndoManager->ClearRedo(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/undo/undoobjects.cxx b/sd/source/core/undo/undoobjects.cxx new file mode 100644 index 000000000000..8687de4d3c9f --- /dev/null +++ b/sd/source/core/undo/undoobjects.cxx @@ -0,0 +1,450 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" + +#include "undo/undoobjects.hxx" +#include "sdpage.hxx" +#include "CustomAnimationEffect.hxx" +#include "drawdoc.hxx" +#include "undoanim.hxx" + +using namespace sd; + +/////////////////////////////////////////////////////////////////////// + +UndoRemovePresObjectImpl::UndoRemovePresObjectImpl( SdrObject& rObject ) +: mpUndoUsercall(0) +, mpUndoAnimation(0) +, mpUndoPresObj(0) +{ + SdPage* pPage = dynamic_cast< SdPage* >( rObject.GetPage() ); + if( pPage ) + { + if( pPage->IsPresObj(&rObject) ) + mpUndoPresObj = new UndoObjectPresentationKind( rObject ); + if( rObject.GetUserCall() ) + mpUndoUsercall = new UndoObjectUserCall(rObject); + + if( pPage->hasAnimationNode() ) + { + com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape( rObject.getUnoShape(), com::sun::star::uno::UNO_QUERY ); + if( pPage->getMainSequence()->hasEffect( xShape ) ) + { + mpUndoAnimation = new UndoAnimation( static_cast< SdDrawDocument* >( pPage->GetModel() ), pPage ); + } + } + } +} + +//--------------------------------------------------------------------- + +UndoRemovePresObjectImpl::~UndoRemovePresObjectImpl() +{ + delete mpUndoAnimation; + delete mpUndoPresObj; + delete mpUndoUsercall; +} + +//--------------------------------------------------------------------- + +void UndoRemovePresObjectImpl::Undo() +{ + if( mpUndoUsercall ) + mpUndoUsercall->Undo(); + if( mpUndoPresObj ) + mpUndoPresObj->Undo(); + if( mpUndoAnimation ) + mpUndoAnimation->Undo(); +} + +//--------------------------------------------------------------------- + +void UndoRemovePresObjectImpl::Redo() +{ + if( mpUndoAnimation ) + mpUndoAnimation->Redo(); + if( mpUndoPresObj ) + mpUndoPresObj->Redo(); + if( mpUndoUsercall ) + mpUndoUsercall->Redo(); +} + +/////////////////////////////////////////////////////////////////////// + + +UndoRemoveObject::UndoRemoveObject( SdrObject& rObject, bool bOrdNumDirect ) +: SdrUndoRemoveObj( rObject, bOrdNumDirect ), UndoRemovePresObjectImpl( rObject ) +, mxSdrObject(&rObject) +{ +} + +//--------------------------------------------------------------------- + +void UndoRemoveObject::Undo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoRemoveObject::Undo(), object already dead!" ); + if( mxSdrObject.is() ) + { + SdrUndoRemoveObj::Undo(); + UndoRemovePresObjectImpl::Undo(); + } +} + +//--------------------------------------------------------------------- + +void UndoRemoveObject::Redo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoRemoveObject::Redo(), object already dead!" ); + if( mxSdrObject.is() ) + { + UndoRemovePresObjectImpl::Redo(); + SdrUndoRemoveObj::Redo(); + } +} + +/////////////////////////////////////////////////////////////////////// + +UndoDeleteObject::UndoDeleteObject( SdrObject& rObject, bool bOrdNumDirect ) +: SdrUndoDelObj( rObject, bOrdNumDirect ) +, UndoRemovePresObjectImpl( rObject ) +, mxSdrObject(&rObject) +{ +} + +//--------------------------------------------------------------------- + +void UndoDeleteObject::Undo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoDeleteObject::Undo(), object already dead!" ); + if( mxSdrObject.is() ) + { + SdrUndoDelObj::Undo(); + UndoRemovePresObjectImpl::Undo(); + } +} + +//--------------------------------------------------------------------- + +void UndoDeleteObject::Redo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoDeleteObject::Redo(), object already dead!" ); + if( mxSdrObject.is() ) + { + UndoRemovePresObjectImpl::Redo(); + SdrUndoDelObj::Redo(); + } +} + +/////////////////////////////////////////////////////////////////////// + +UndoReplaceObject::UndoReplaceObject( SdrObject& rOldObject, SdrObject& rNewObject, bool bOrdNumDirect ) +: SdrUndoReplaceObj( rOldObject, rNewObject, bOrdNumDirect ) +, UndoRemovePresObjectImpl( rOldObject ) +, mxSdrObject( &rOldObject ) +{ +} + +//--------------------------------------------------------------------- + +void UndoReplaceObject::Undo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoReplaceObject::Undo(), object already dead!" ); + if( mxSdrObject.is() ) + { + SdrUndoReplaceObj::Undo(); + UndoRemovePresObjectImpl::Undo(); + } +} + +//--------------------------------------------------------------------- + +void UndoReplaceObject::Redo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoReplaceObject::Redo(), object already dead!" ); + if( mxSdrObject.is() ) + { + UndoRemovePresObjectImpl::Redo(); + SdrUndoReplaceObj::Redo(); + } +} + +/////////////////////////////////////////////////////////////////////// + +UndoObjectSetText::UndoObjectSetText( SdrObject& rObject, sal_Int32 nText ) +: SdrUndoObjSetText( rObject, nText ) +, mpUndoAnimation(0) +, mbNewEmptyPresObj(false) +, mxSdrObject( &rObject ) +{ + SdPage* pPage = dynamic_cast< SdPage* >( rObject.GetPage() ); + if( pPage && pPage->hasAnimationNode() ) + { + com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape( rObject.getUnoShape(), com::sun::star::uno::UNO_QUERY ); + if( pPage->getMainSequence()->hasEffect( xShape ) ) + { + mpUndoAnimation = new UndoAnimation( static_cast< SdDrawDocument* >( pPage->GetModel() ), pPage ); + } + } +} + +//--------------------------------------------------------------------- + +UndoObjectSetText::~UndoObjectSetText() +{ + delete mpUndoAnimation; +} + +//--------------------------------------------------------------------- + +void UndoObjectSetText::Undo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoObjectSetText::Undo(), object already dead!" ); + if( mxSdrObject.is() ) + { + mbNewEmptyPresObj = mxSdrObject->IsEmptyPresObj() ? true : false; + SdrUndoObjSetText::Undo(); + if( mpUndoAnimation ) + mpUndoAnimation->Undo(); + } +} + +//--------------------------------------------------------------------- + +void UndoObjectSetText::Redo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoObjectSetText::Redo(), object already dead!" ); + if( mxSdrObject.is() ) + { + if( mpUndoAnimation ) + mpUndoAnimation->Redo(); + SdrUndoObjSetText::Redo(); + mxSdrObject->SetEmptyPresObj(mbNewEmptyPresObj ? TRUE : FALSE ); + } +} + +////////////////////////////////////////////////////////////////////////////// +// Undo for SdrObject::SetUserCall() + +UndoObjectUserCall::UndoObjectUserCall(SdrObject& rObject) +: SdrUndoObj(rObject) +, mpOldUserCall((SdPage*)rObject.GetUserCall()) +, mpNewUserCall(0) +, mxSdrObject( &rObject ) +{ +} + +//--------------------------------------------------------------------- + +void UndoObjectUserCall::Undo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoObjectUserCall::Undo(), object already dead!" ); + if( mxSdrObject.is() ) + { + mpNewUserCall = mxSdrObject->GetUserCall(); + mxSdrObject->SetUserCall(mpOldUserCall); + } +} + +//--------------------------------------------------------------------- + +void UndoObjectUserCall::Redo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoObjectUserCall::Redo(), object already dead!" ); + if( mxSdrObject.is() ) + { + mxSdrObject->SetUserCall(mpNewUserCall); + } +} + +////////////////////////////////////////////////////////////////////////////// +// Undo for SdPage::InsertPresObj() and SdPage::RemovePresObj() + +UndoObjectPresentationKind::UndoObjectPresentationKind(SdrObject& rObject) +: SdrUndoObj(rObject) +, meOldKind(PRESOBJ_NONE) +, meNewKind(PRESOBJ_NONE) +, mxPage( rObject.GetPage() ) +, mxSdrObject( &rObject ) +{ + DBG_ASSERT( mxPage.is(), "sd::UndoObjectPresentationKind::UndoObjectPresentationKind(), does not work for shapes without a slide!" ); + + if( mxPage.is() ) + meOldKind = static_cast< SdPage* >( mxPage.get() )->GetPresObjKind( &rObject ); +} + +//--------------------------------------------------------------------- + +void UndoObjectPresentationKind::Undo() +{ + if( mxPage.is() && mxSdrObject.is() ) + { + SdPage* pPage = static_cast< SdPage* >( mxPage.get() ); + meNewKind = pPage->GetPresObjKind( mxSdrObject.get() ); + if( meNewKind != PRESOBJ_NONE ) + pPage->RemovePresObj( mxSdrObject.get() ); + if( meOldKind != PRESOBJ_NONE ) + pPage->InsertPresObj( mxSdrObject.get(), meOldKind ); + } +} + +//--------------------------------------------------------------------- + +void UndoObjectPresentationKind::Redo() +{ + if( mxPage.is() && mxSdrObject.is() ) + { + SdPage* pPage = static_cast< SdPage* >( mxPage.get() ); + if( meOldKind != PRESOBJ_NONE ) + pPage->RemovePresObj( mxSdrObject.get() ); + if( meNewKind != PRESOBJ_NONE ) + pPage->InsertPresObj( mxSdrObject.get(), meNewKind ); + } +} + +////////////////////////////////////////////////////////////////////////////// + +UndoAutoLayoutPosAndSize::UndoAutoLayoutPosAndSize( SdPage& rPage ) +: mxPage( &rPage ) +{ +} + +//--------------------------------------------------------------------- + +void UndoAutoLayoutPosAndSize::Undo() +{ + // do nothing +} + +//--------------------------------------------------------------------- + +void UndoAutoLayoutPosAndSize::Redo() +{ + SdPage* pPage = static_cast< SdPage* >( mxPage.get() ); + if( pPage ) + pPage->SetAutoLayout( pPage->GetAutoLayout(), FALSE, FALSE ); +} + +////////////////////////////////////////////////////////////////////////////// + +UndoGeoObject::UndoGeoObject( SdrObject& rNewObj ) +: SdrUndoGeoObj( rNewObj ) +, mxPage( rNewObj.GetPage() ) +, mxSdrObject( &rNewObj ) +{ +} + +//--------------------------------------------------------------------- + +void UndoGeoObject::Undo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoGeoObject::Undo(), object already dead!" ); + if( mxSdrObject.is() ) + { + if( mxPage.is() ) + { + ScopeLockGuard aGuard( static_cast< SdPage* >( mxPage.get() )->maLockAutoLayoutArrangement ); + SdrUndoGeoObj::Undo(); + } + else + { + SdrUndoGeoObj::Undo(); + } + } +} + +//--------------------------------------------------------------------- + +void UndoGeoObject::Redo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoGeoObject::Redo(), object already dead!" ); + if( mxSdrObject.is() ) + { + if( mxPage.is() ) + { + ScopeLockGuard aGuard( static_cast< SdPage* >(mxPage.get())->maLockAutoLayoutArrangement ); + SdrUndoGeoObj::Redo(); + } + else + { + SdrUndoGeoObj::Redo(); + } + } +} + +//--------------------------------------------------------------------- + +////////////////////////////////////////////////////////////////////////////// + +UndoAttrObject::UndoAttrObject( SdrObject& rObject, bool bStyleSheet1, bool bSaveText ) +: SdrUndoAttrObj( rObject, bStyleSheet1 ? TRUE : FALSE, bSaveText ? TRUE : FALSE ) +, mxPage( rObject.GetPage() ) +, mxSdrObject( &rObject ) +{ +} + +//--------------------------------------------------------------------- + +void UndoAttrObject::Undo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoAttrObject::Undo(), object already dead!" ); + if( mxSdrObject.is() ) + { + if( mxPage.is() ) + { + ScopeLockGuard aGuard( static_cast< SdPage* >( mxPage.get() )->maLockAutoLayoutArrangement ); + SdrUndoAttrObj::Undo(); + } + else + { + SdrUndoAttrObj::Undo(); + } + } +} + +//--------------------------------------------------------------------- + +void UndoAttrObject::Redo() +{ + DBG_ASSERT( mxSdrObject.is(), "sd::UndoAttrObject::Redo(), object already dead!" ); + if( mxSdrObject.is() ) + { + if( mxPage.is() ) + { + ScopeLockGuard aGuard( static_cast< SdPage* >( mxPage.get() )->maLockAutoLayoutArrangement ); + SdrUndoAttrObj::Redo(); + } + else + { + SdrUndoAttrObj::Redo(); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/core/undoanim.cxx b/sd/source/core/undoanim.cxx new file mode 100644 index 000000000000..307094a5b367 --- /dev/null +++ b/sd/source/core/undoanim.cxx @@ -0,0 +1,299 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sd.hxx" +#include <com/sun/star/util/XCloneable.hpp> +#include <com/sun/star/animations/XAnimationNode.hpp> +#include "CustomAnimationCloner.hxx" + +#include "undoanim.hxx" +#include "glob.hrc" +#include "sdpage.hxx" +#include "sdresid.hxx" +#include "CustomAnimationEffect.hxx" +#include "drawdoc.hxx" + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::util::XCloneable; +using namespace ::com::sun::star::animations; + + +namespace sd +{ + +struct UndoAnimationImpl +{ + SdPage* mpPage; + Reference< XAnimationNode > mxOldNode; + Reference< XAnimationNode > mxNewNode; + bool mbNewNodeSet; +}; + +UndoAnimation::UndoAnimation( SdDrawDocument* pDoc, SdPage* pThePage ) +: SdrUndoAction( *pDoc ), mpImpl( new UndoAnimationImpl ) +{ + mpImpl->mpPage = pThePage; + mpImpl->mbNewNodeSet = false; + + try + { + if( pThePage->mxAnimationNode.is() ) + mpImpl->mxOldNode = ::sd::Clone( pThePage->getAnimationNode() ); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::UndoAnimation::UndoAnimation(), exception caught!"); + } +} + +UndoAnimation::~UndoAnimation() +{ + delete mpImpl; +} + +void UndoAnimation::Undo() +{ + try + { + if( !mpImpl->mbNewNodeSet ) + { + if( mpImpl->mpPage->mxAnimationNode.is() ) + mpImpl->mxNewNode.set( ::sd::Clone( mpImpl->mpPage->mxAnimationNode ) ); + mpImpl->mbNewNodeSet = true; + } + + Reference< XAnimationNode > xOldNode; + if( mpImpl->mxOldNode.is() ) + xOldNode = ::sd::Clone( mpImpl->mxOldNode ); + + mpImpl->mpPage->setAnimationNode( xOldNode ); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::UndoAnimation::Undo(), exception caught!"); + } +} + +void UndoAnimation::Redo() +{ + try + { + Reference< XAnimationNode > xNewNode; + if( mpImpl->mxNewNode.is() ) + xNewNode = ::sd::Clone( mpImpl->mxNewNode ); + mpImpl->mpPage->setAnimationNode( xNewNode ); + } + catch( Exception& e ) + { + (void)e; + DBG_ERROR("sd::UndoAnimation::Redo(), exception caught!"); + } +} + +String UndoAnimation::GetComment() const +{ + return String(SdResId(STR_UNDO_ANIMATION)); +} + +struct UndoAnimationPathImpl +{ + SdPage* mpPage; + sal_Int32 mnEffectOffset; + ::rtl::OUString msUndoPath; + ::rtl::OUString msRedoPath; + + UndoAnimationPathImpl( SdPage* pThePage, const com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) + : mpPage( pThePage ) + , mnEffectOffset( -1 ) + { + if( mpPage && xNode.is() ) + { + boost::shared_ptr< sd::MainSequence > pMainSequence( mpPage->getMainSequence() ); + if( pMainSequence.get() ) + { + CustomAnimationEffectPtr pEffect( pMainSequence->findEffect( xNode ) ); + if( pEffect.get() ) + { + mnEffectOffset = pMainSequence->getOffsetFromEffect( pEffect ); + msUndoPath = pEffect->getPath(); + } + } + } + } + + CustomAnimationEffectPtr getEffect() const + { + CustomAnimationEffectPtr pEffect; + if( mpPage && (mnEffectOffset >= 0) ) + { + boost::shared_ptr< sd::MainSequence > pMainSequence( mpPage->getMainSequence() ); + if( pMainSequence.get() ) + pEffect = pMainSequence->getEffectFromOffset( mnEffectOffset ); + } + return pEffect; + } + + private: + UndoAnimationPathImpl( const UndoAnimationPathImpl& ); //not implemented + const UndoAnimationPathImpl& operator=( const UndoAnimationPathImpl& ); // not implemented + +}; + +UndoAnimationPath::UndoAnimationPath( SdDrawDocument* pDoc, SdPage* pThePage, const com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode ) +: SdrUndoAction( *pDoc ) +, mpImpl( new UndoAnimationPathImpl( pThePage, xNode ) ) +{ +} + +UndoAnimationPath::~UndoAnimationPath() +{ +} + +void UndoAnimationPath::Undo() +{ + CustomAnimationEffectPtr pEffect = mpImpl->getEffect(); + if( pEffect.get() ) + { + mpImpl->msRedoPath = pEffect->getPath(); + pEffect->setPath( mpImpl->msUndoPath ); + } +} + +void UndoAnimationPath::Redo() +{ + CustomAnimationEffectPtr pEffect = mpImpl->getEffect(); + if( pEffect.get() ) + { + pEffect->setPath( mpImpl->msRedoPath ); + } +} + +String UndoAnimationPath::GetComment() const +{ + return String(SdResId(STR_UNDO_ANIMATION)); +} + +struct UndoTransitionImpl +{ + SdPage* mpPage; + + sal_Int16 mnNewTransitionType; + sal_Int16 mnNewTransitionSubtype; + sal_Bool mbNewTransitionDirection; + sal_Int32 mnNewTransitionFadeColor; + double mfNewTransitionDuration; + String maNewSoundFile; + bool mbNewSoundOn; + bool mbNewLoopSound; + bool mbNewStopSound; + + sal_Int16 mnOldTransitionType; + sal_Int16 mnOldTransitionSubtype; + sal_Bool mbOldTransitionDirection; + sal_Int32 mnOldTransitionFadeColor; + double mfOldTransitionDuration; + String maOldSoundFile; + bool mbOldSoundOn; + bool mbOldLoopSound; + bool mbOldStopSound; +}; + +UndoTransition::UndoTransition( SdDrawDocument* _pDoc, SdPage* pThePage ) +: SdUndoAction( _pDoc ), mpImpl( new UndoTransitionImpl ) +{ + mpImpl->mpPage = pThePage; + + mpImpl->mnNewTransitionType = -1; + mpImpl->mnOldTransitionType = pThePage->mnTransitionType; + mpImpl->mnOldTransitionSubtype = pThePage->mnTransitionSubtype; + mpImpl->mbOldTransitionDirection = pThePage->mbTransitionDirection; + mpImpl->mnOldTransitionFadeColor = pThePage->mnTransitionFadeColor; + mpImpl->mfOldTransitionDuration = pThePage->mfTransitionDuration; + mpImpl->maOldSoundFile = pThePage->maSoundFile; + mpImpl->mbOldSoundOn = pThePage->mbSoundOn; + mpImpl->mbOldLoopSound = pThePage->mbLoopSound; + mpImpl->mbOldStopSound = pThePage->mbStopSound; +} + +UndoTransition::~UndoTransition() +{ + delete mpImpl; +} + +void UndoTransition::Undo() +{ + if( mpImpl->mnNewTransitionType == -1 ) + { + mpImpl->mnNewTransitionType = mpImpl->mpPage->mnTransitionType; + mpImpl->mnNewTransitionSubtype = mpImpl->mpPage->mnTransitionSubtype; + mpImpl->mbNewTransitionDirection = mpImpl->mpPage->mbTransitionDirection; + mpImpl->mnNewTransitionFadeColor = mpImpl->mpPage->mnTransitionFadeColor; + mpImpl->mfNewTransitionDuration = mpImpl->mpPage->mfTransitionDuration; + mpImpl->maNewSoundFile = mpImpl->mpPage->maSoundFile; + mpImpl->mbNewSoundOn = mpImpl->mpPage->mbSoundOn; + mpImpl->mbNewLoopSound = mpImpl->mpPage->mbLoopSound; + mpImpl->mbNewStopSound = mpImpl->mpPage->mbStopSound; + } + + mpImpl->mpPage->mnTransitionType = mpImpl->mnOldTransitionType; + mpImpl->mpPage->mnTransitionSubtype = mpImpl->mnOldTransitionSubtype; + mpImpl->mpPage->mbTransitionDirection = mpImpl->mbOldTransitionDirection; + mpImpl->mpPage->mnTransitionFadeColor = mpImpl->mnOldTransitionFadeColor; + mpImpl->mpPage->mfTransitionDuration = mpImpl->mfOldTransitionDuration; + mpImpl->mpPage->maSoundFile = mpImpl->maOldSoundFile; + mpImpl->mpPage->mbSoundOn = mpImpl->mbOldSoundOn; + mpImpl->mpPage->mbLoopSound = mpImpl->mbOldLoopSound; + mpImpl->mpPage->mbStopSound = mpImpl->mbOldStopSound; +} + +void UndoTransition::Redo() +{ + mpImpl->mpPage->mnTransitionType = mpImpl->mnNewTransitionType; + mpImpl->mpPage->mnTransitionSubtype = mpImpl->mnNewTransitionSubtype; + mpImpl->mpPage->mbTransitionDirection = mpImpl->mbNewTransitionDirection; + mpImpl->mpPage->mnTransitionFadeColor = mpImpl->mnNewTransitionFadeColor; + mpImpl->mpPage->mfTransitionDuration = mpImpl->mfNewTransitionDuration; + mpImpl->mpPage->maSoundFile = mpImpl->maNewSoundFile; + mpImpl->mpPage->mbSoundOn = mpImpl->mbNewSoundOn; + mpImpl->mpPage->mbLoopSound = mpImpl->mbNewLoopSound; + mpImpl->mpPage->mbStopSound = mpImpl->mbNewStopSound; +} + +String UndoTransition::GetComment() const +{ + return String(SdResId(STR_UNDO_SLIDE_PARAMS)); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |