Kaydet (Commit) c0ff8a24 authored tarafından Brian Fraser's avatar Brian Fraser Kaydeden (comit) Jim Raykowski

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: 's avatarJim Raykowski <raykowj@gmail.com>
üst db393365
...@@ -2176,6 +2176,39 @@ void EffectSequenceHelper::insertTextRange( const css::uno::Any& aTarget ) ...@@ -2176,6 +2176,39 @@ void EffectSequenceHelper::insertTextRange( const css::uno::Any& aTarget )
rebuild(); 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 ) void EffectSequenceHelper::disposeTextRange( const css::uno::Any& aTarget )
{ {
ParagraphTarget aParaTarget; ParagraphTarget aParaTarget;
...@@ -2183,49 +2216,67 @@ void EffectSequenceHelper::disposeTextRange( const css::uno::Any& aTarget ) ...@@ -2183,49 +2216,67 @@ void EffectSequenceHelper::disposeTextRange( const css::uno::Any& aTarget )
return; return;
bool bChanges = false; bool bChanges = false;
bool bErased = false;
EffectSequence::iterator aIter( maEffects.begin() ); // building list of effects for target shape; process effects not on target shape
while( aIter != maEffects.end() ) EffectSequence aTargetParagraphEffects;
for( const auto &pEffect : maEffects )
{ {
Any aIterTarget( (*aIter)->getTarget() ); Any aIterTarget( pEffect->getTarget() );
if( aIterTarget.getValueType() == ::cppu::UnoType<ParagraphTarget>::get() ) if( aIterTarget.getValueType() == ::cppu::UnoType<ParagraphTarget>::get() )
{ {
ParagraphTarget aIterParaTarget; ParagraphTarget aIterParaTarget;
if( (aIterTarget >>= aIterParaTarget) && (aIterParaTarget.Shape == aParaTarget.Shape) ) if( (aIterTarget >>= aIterParaTarget) && (aIterParaTarget.Shape == aParaTarget.Shape) )
{ {
if( aIterParaTarget.Paragraph == aParaTarget.Paragraph ) aTargetParagraphEffects.push_back(pEffect);
{
// 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 ) );
}
}
} }
} }
else if( (*aIter)->getTargetShape() == aParaTarget.Shape ) else if( pEffect->getTargetShape() == aParaTarget.Shape )
{ {
bChanges |= (*aIter)->checkForText(); bChanges |= pEffect->checkForText();
} }
}
if( bErased ) // select effect to delete:
bErased = false; // if paragraph before target is blank, then delete its animation effect (if any) instead
else ParagraphTarget aPreviousParagraph = aParaTarget;
++aIter; --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 ) if( bChanges )
{
rebuild(); rebuild();
}
} }
CustomAnimationTextGroup::CustomAnimationTextGroup( const Reference< XShape >& rTarget, sal_Int32 nGroupId ) CustomAnimationTextGroup::CustomAnimationTextGroup( const Reference< XShape >& rTarget, sal_Int32 nGroupId )
...@@ -3246,7 +3297,7 @@ void EffectSequenceHelper::onTextChanged( const Reference< XShape >& xShape ) ...@@ -3246,7 +3297,7 @@ void EffectSequenceHelper::onTextChanged( const Reference< XShape >& xShape )
}); });
if( bChanges ) if( bChanges )
EffectSequenceHelper::implRebuild(); rebuild();
} }
void MainSequence::rebuild() void MainSequence::rebuild()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment