summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Fraser <andthebrain@softfrog.ca>2019-04-15 09:49:53 -0700
committerJim Raykowski <raykowj@gmail.com>2019-04-30 03:01:02 +0200
commitc0ff8a24365456383900ed7958c8fb9ea68043e9 (patch)
treec1c5d38db7d9a0dd7b2ae0316979cb095eaccad3
parentdb39336550ff547bcb7ca15793b12291c913ab42 (diff)
Impress: Delete an empty paragraph's animation over a non-empty one's
- Backspacing into empty paragraph deletes empty paragraph's animation, not the next paragraph's animation. - Pressing delete while in empty paragraph deletes its animation, not next paragraph's animation. - Changing indent level of an animated paragraph no longer collapses any expanded animations in the animation list side panel. Change-Id: I65ff5813893b1ffe91687cc106f276447de4b225 Reviewed-on: https://gerrit.libreoffice.org/70792 Tested-by: Jenkins Reviewed-by: Jim Raykowski <raykowj@gmail.com>
-rw-r--r--sd/source/core/CustomAnimationEffect.cxx107
1 files changed, 79 insertions, 28 deletions
diff --git a/sd/source/core/CustomAnimationEffect.cxx b/sd/source/core/CustomAnimationEffect.cxx
index 04f4fed1e035..ac1e8bbabc1a 100644
--- a/sd/source/core/CustomAnimationEffect.cxx
+++ b/sd/source/core/CustomAnimationEffect.cxx
@@ -2176,6 +2176,39 @@ void EffectSequenceHelper::insertTextRange( const css::uno::Any& aTarget )
rebuild();
}
+static bool isParagraphTargetTextEmpty( ParagraphTarget aParaTarget )
+{
+ // get paragraph
+ Reference< XText > xText ( aParaTarget.Shape, UNO_QUERY );
+ if( xText.is() )
+ {
+ Reference< XEnumerationAccess > xEA( xText, UNO_QUERY );
+ if( xEA.is() )
+ {
+ Reference< XEnumeration > xEnumeration( xEA->createEnumeration(), UNO_QUERY );
+ if( xEnumeration.is() )
+ {
+ // advance to the Nth paragraph
+ sal_Int32 nPara = aParaTarget.Paragraph;
+ while( xEnumeration->hasMoreElements() && nPara-- )
+ xEnumeration->nextElement();
+
+ // get Nth paragraph's text and check if it's empty
+ if( xEnumeration->hasMoreElements() )
+ {
+ Reference< XTextRange > xRange( xEnumeration->nextElement(), UNO_QUERY );
+ if( xRange.is() )
+ {
+ OUString text = xRange->getString();
+ return text.isEmpty();
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
void EffectSequenceHelper::disposeTextRange( const css::uno::Any& aTarget )
{
ParagraphTarget aParaTarget;
@@ -2183,49 +2216,67 @@ void EffectSequenceHelper::disposeTextRange( const css::uno::Any& aTarget )
return;
bool bChanges = false;
- bool bErased = false;
- EffectSequence::iterator aIter( maEffects.begin() );
- while( aIter != maEffects.end() )
+ // building list of effects for target shape; process effects not on target shape
+ EffectSequence aTargetParagraphEffects;
+ for( const auto &pEffect : maEffects )
{
- Any aIterTarget( (*aIter)->getTarget() );
+ Any aIterTarget( pEffect->getTarget() );
if( aIterTarget.getValueType() == ::cppu::UnoType<ParagraphTarget>::get() )
{
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( nullptr );
- 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 ) );
- }
- }
+ aTargetParagraphEffects.push_back(pEffect);
}
}
- else if( (*aIter)->getTargetShape() == aParaTarget.Shape )
+ else if( pEffect->getTargetShape() == aParaTarget.Shape )
{
- bChanges |= (*aIter)->checkForText();
+ bChanges |= pEffect->checkForText();
}
+ }
- if( bErased )
- bErased = false;
- else
- ++aIter;
+ // select effect to delete:
+ // if paragraph before target is blank, then delete its animation effect (if any) instead
+ ParagraphTarget aPreviousParagraph = aParaTarget;
+ --aPreviousParagraph.Paragraph;
+ bool bIsPreviousParagraphEmpty = isParagraphTargetTextEmpty( aPreviousParagraph );
+ sal_Int16 anParaNumToDelete = bIsPreviousParagraphEmpty ? aPreviousParagraph.Paragraph : aParaTarget.Paragraph;
+
+ // update effects
+ for( const auto &pEffect : aTargetParagraphEffects )
+ {
+ Any aIterTarget( pEffect->getTarget() );
+
+ ParagraphTarget aIterParaTarget;
+ aIterTarget >>= aIterParaTarget;
+
+ // delete effect for target paragraph (may have effects in more than one text group)
+ if( aIterParaTarget.Paragraph == anParaNumToDelete )
+ {
+ auto aItr = find( pEffect );
+ DBG_ASSERT( aItr != maEffects.end(), "sd::EffectSequenceHelper::disposeTextRange(), Expected effect missing.");
+ if( aItr != maEffects.end() )
+ {
+ (*aItr)->setEffectSequence( nullptr );
+ maEffects.erase(aItr);
+ bChanges = true;
+ }
+ }
+
+ // shift all paragraphs after disposed paragraph
+ if( aIterParaTarget.Paragraph > anParaNumToDelete )
+ {
+ --aIterParaTarget.Paragraph;
+ pEffect->setTarget( makeAny( aIterParaTarget ) );
+ bChanges = true;
+ }
}
if( bChanges )
+ {
rebuild();
+ }
}
CustomAnimationTextGroup::CustomAnimationTextGroup( const Reference< XShape >& rTarget, sal_Int32 nGroupId )
@@ -3246,7 +3297,7 @@ void EffectSequenceHelper::onTextChanged( const Reference< XShape >& xShape )
});
if( bChanges )
- EffectSequenceHelper::implRebuild();
+ rebuild();
}
void MainSequence::rebuild()