bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / animations / CustomAnimationPane.cxx
blobca19853a4c0ab996d87eb257e5f5587291a0347e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/presentation/EffectPresetClass.hpp>
21 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
22 #include <com/sun/star/animations/ParallelTimeContainer.hpp>
23 #include <com/sun/star/view/XSelectionSupplier.hpp>
24 #include <com/sun/star/drawing/XDrawView.hpp>
25 #include <com/sun/star/drawing/XShape.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/presentation/EffectNodeType.hpp>
28 #include <com/sun/star/presentation/EffectCommands.hpp>
29 #include <com/sun/star/animations/AnimationTransformType.hpp>
30 #include <com/sun/star/text/XTextRangeCompare.hpp>
31 #include <com/sun/star/container/XEnumerationAccess.hpp>
32 #include <com/sun/star/container/XIndexAccess.hpp>
33 #include <com/sun/star/presentation/ParagraphTarget.hpp>
34 #include <com/sun/star/text/XText.hpp>
35 #include <com/sun/star/awt/XWindow.hpp>
36 #include <com/sun/star/drawing/LineStyle.hpp>
37 #include <com/sun/star/drawing/FillStyle.hpp>
38 #include <comphelper/processfactory.hxx>
39 #include <sfx2/dispatch.hxx>
40 #include "STLPropertySet.hxx"
41 #include "CustomAnimationPane.hxx"
42 #include "CustomAnimationDialog.hxx"
43 #include "CustomAnimationCreateDialog.hxx"
44 #include "CustomAnimation.hrc"
45 #include "CustomAnimationList.hxx"
46 #include "createcustomanimationpanel.hxx"
47 #include <vcl/lstbox.hxx>
48 #include <vcl/fixed.hxx>
50 #include <vcl/button.hxx>
51 #include <vcl/combobox.hxx>
52 #include <vcl/scrbar.hxx>
54 #include <comphelper/sequence.hxx>
55 #include <sfx2/frame.hxx>
56 #include <sfx2/sidebar/Theme.hxx>
58 #include <svx/unoapi.hxx>
59 #include <svx/svxids.hrc>
60 #include <DrawDocShell.hxx>
61 #include <ViewShellBase.hxx>
62 #include "DrawViewShell.hxx"
63 #include "DrawController.hxx"
64 #include "sdresid.hxx"
65 #include "drawview.hxx"
66 #include "slideshow.hxx"
67 #include "undoanim.hxx"
68 #include "optsitem.hxx"
69 #include "sddll.hxx"
70 #include "framework/FrameworkHelper.hxx"
72 #include "EventMultiplexer.hxx"
74 #include "glob.hrc"
75 #include "sdpage.hxx"
76 #include "drawdoc.hxx"
77 #include "app.hrc"
79 #include <algorithm>
81 #include <basegfx/polygon/b2dpolypolygontools.hxx>
82 #include <basegfx/matrix/b2dhommatrix.hxx>
83 #include <basegfx/range/b2drange.hxx>
84 #include <boost/scoped_ptr.hpp>
86 using namespace ::com::sun::star;
87 using namespace ::com::sun::star::animations;
88 using namespace ::com::sun::star::presentation;
89 using namespace ::com::sun::star::text;
91 using namespace ::com::sun::star::uno;
92 using namespace ::com::sun::star::drawing;
93 using ::com::sun::star::view::XSelectionSupplier;
94 using ::com::sun::star::view::XSelectionChangeListener;
95 using ::com::sun::star::frame::XController;
96 using ::com::sun::star::frame::XModel;
97 using ::com::sun::star::beans::XPropertySet;
98 using ::com::sun::star::beans::XPropertyChangeListener;
99 using ::com::sun::star::container::XIndexAccess;
100 using ::com::sun::star::container::XEnumerationAccess;
101 using ::com::sun::star::container::XEnumeration;
102 using ::com::sun::star::text::XText;
103 using ::sd::framework::FrameworkHelper;
105 namespace sd {
107 void fillDurationComboBox( ListBox* pBox )
109 static const double gdVerySlow = 5.0;
110 static const double gdSlow = 3.0;
111 static const double gdNormal = 2.0;
112 static const double gdFast = 1.0;
113 static const double gdVeryFast = 0.5;
115 OUString aVerySlow( SD_RESSTR( STR_CUSTOMANIMATION_DURATION_VERY_SLOW ) );
116 pBox->SetEntryData( pBox->InsertEntry( aVerySlow ), (void*)&gdVerySlow );
118 OUString aSlow( SD_RESSTR( STR_CUSTOMANIMATION_DURATION_SLOW ) );
119 pBox->SetEntryData( pBox->InsertEntry( aSlow ), (void*)&gdSlow );
121 OUString aNormal( SD_RESSTR( STR_CUSTOMANIMATION_DURATION_NORMAL ) );
122 pBox->SetEntryData( pBox->InsertEntry( aNormal ), (void*)&gdNormal );
124 OUString aFast( SD_RESSTR( STR_CUSTOMANIMATION_DURATION_FAST ) );
125 pBox->SetEntryData( pBox->InsertEntry( aFast ), (void*)&gdFast );
127 OUString aVeryFast( SD_RESSTR( STR_CUSTOMANIMATION_DURATION_VERY_FAST ) );
128 pBox->SetEntryData( pBox->InsertEntry( aVeryFast ), (void*)&gdVeryFast );
131 void fillRepeatComboBox( ListBox* pBox )
133 OUString aNone( SD_RESSTR( STR_CUSTOMANIMATION_REPEAT_NONE ) );
134 pBox->InsertEntry(aNone);
135 pBox->InsertEntry(OUString::number(2));
136 pBox->InsertEntry(OUString::number(3));
137 pBox->InsertEntry(OUString::number(4));
138 pBox->InsertEntry(OUString::number(5));
139 pBox->InsertEntry(OUString::number(10));
141 OUString aUntilClick( SD_RESSTR( STR_CUSTOMANIMATION_REPEAT_UNTIL_NEXT_CLICK ) );
142 pBox->InsertEntry(aUntilClick);
144 OUString aEndOfSlide( SD_RESSTR( STR_CUSTOMANIMATION_REPEAT_UNTIL_END_OF_SLIDE ) );
145 pBox->InsertEntry(aEndOfSlide);
148 CustomAnimationPane::CustomAnimationPane( Window* pParent, ViewShellBase& rBase,
149 const css::uno::Reference<css::frame::XFrame>& rxFrame,
150 const Size& rMinSize )
151 : PanelLayout( pParent, "CustomAnimationsPanel", "modules/simpress/ui/customanimationspanel.ui", rxFrame ),
152 mrBase( rBase ),
153 mpCustomAnimationPresets(NULL),
154 mnPropertyType( nPropertyTypeNone ),
155 maMinSize( rMinSize ),
156 mxModel( rBase.GetDocShell()->GetDoc()->getUnoModel(), UNO_QUERY ),
157 maLateInitTimer()
159 // load resources
160 get(mpPBAddEffect, "add_effect");
161 get(mpPBChangeEffect, "change_effect");
162 get(mpPBRemoveEffect, "remove_effect");
164 get(mpFTEffect, "effect_label");
166 get(mpFTStart, "start_effect");
167 get(mpLBStart, "start_effect_list");
168 get(mpFTProperty, "effect_property");
169 get(mpPlaceholderBox, "placeholder");
170 get(mpLBProperty, "effect_property_list");
171 get(mpPBPropertyMore, "more_properties");
173 get(mpFTSpeed, "effect_speed");
174 get(mpCBSpeed, "effect_speed_list");
176 get(mpCustomAnimationList, "custom_animation_list");
177 mpCustomAnimationList->setController( dynamic_cast<ICustomAnimationListController*> ( this ) );
178 mpCustomAnimationList->set_width_request(mpCustomAnimationList->approximate_char_width() * 16);
179 mpCustomAnimationList->set_height_request(mpCustomAnimationList->GetTextHeight() * 16);
181 get(mpPBMoveUp, "move_up");
182 get(mpPBMoveDown, "move_down");
183 get(mpPBPlay, "play");
184 get(mpCBAutoPreview,"auto_preview");
186 maStrProperty = mpFTProperty->GetText();
188 fillDurationComboBox( mpCBSpeed );
190 mpPBAddEffect->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
191 mpPBChangeEffect->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
192 mpPBRemoveEffect->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
193 mpLBStart->SetSelectHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
194 mpCBSpeed->SetSelectHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
195 mpPBPropertyMore->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
196 mpPBMoveUp->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
197 mpPBMoveDown->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
198 mpPBPlay->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
199 mpCBAutoPreview->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
201 maStrModify = mpFTEffect->GetText();
203 // get current controller and initialize listeners
206 mxView = Reference< XDrawView >::query(mrBase.GetController());
207 addListener();
209 catch( Exception& )
211 OSL_FAIL( "sd::CustomAnimationPane::CustomAnimationPane(), Exception caught!" );
214 // get current page and update custom animation list
215 onChangeCurrentPage();
217 // Wait a short time before the presets list is created. This gives the
218 // system time to paint the control.
219 maLateInitTimer.SetTimeout(100);
220 maLateInitTimer.SetTimeoutHdl(LINK(this, CustomAnimationPane, lateInitCallback));
221 maLateInitTimer.Start();
223 UpdateLook();
226 CustomAnimationPane::~CustomAnimationPane()
228 disposeOnce();
231 void CustomAnimationPane::dispose()
233 maLateInitTimer.Stop();
235 removeListener();
237 MotionPathTagVector aTags;
238 aTags.swap( maMotionPathTags );
239 MotionPathTagVector::iterator aIter;
240 for( aIter = aTags.begin(); aIter != aTags.end(); ++aIter )
241 (*aIter)->Dispose();
243 mpPBAddEffect.clear();
244 mpPBChangeEffect.clear();
245 mpPBRemoveEffect.clear();
246 mpFTEffect.clear();
247 mpFTStart.clear();
248 mpLBStart.clear();
249 mpFTProperty.clear();
250 mpPlaceholderBox.clear();
251 mpLBProperty.clear();
252 mpPBPropertyMore.clear();
253 mpFTSpeed.clear();
254 mpCBSpeed.clear();
255 mpCustomAnimationList.clear();
256 mpPBMoveUp.clear();
257 mpPBMoveDown.clear();
258 mpPBPlay.clear();
259 mpCBAutoPreview.clear();
260 PanelLayout::dispose();
263 void CustomAnimationPane::addUndo()
265 ::svl::IUndoManager* pManager = mrBase.GetDocShell()->GetUndoManager();
266 if( pManager )
268 SdPage* pPage = SdPage::getImplementation( mxCurrentPage );
269 if( pPage )
270 pManager->AddUndoAction( new UndoAnimation( mrBase.GetDocShell()->GetDoc(), pPage ) );
274 void CustomAnimationPane::StateChanged( StateChangedType nStateChange )
276 Control::StateChanged( nStateChange );
278 if( nStateChange == StateChangedType::Visible )
279 updateMotionPathTags();
282 void CustomAnimationPane::KeyInput( const KeyEvent& rKEvt )
284 if( mpCustomAnimationList )
285 mpCustomAnimationList->KeyInput( rKEvt );
288 void CustomAnimationPane::addListener()
290 Link<> aLink( LINK(this,CustomAnimationPane,EventMultiplexerListener) );
291 mrBase.GetEventMultiplexer()->AddEventListener (
292 aLink,
293 tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION
294 | tools::EventMultiplexerEvent::EID_CURRENT_PAGE
295 | tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
296 | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
297 | tools::EventMultiplexerEvent::EID_DISPOSING
298 | tools::EventMultiplexerEvent::EID_END_TEXT_EDIT);
301 void CustomAnimationPane::removeListener()
303 Link<> aLink( LINK(this,CustomAnimationPane,EventMultiplexerListener) );
304 mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
307 IMPL_LINK(CustomAnimationPane,EventMultiplexerListener,
308 tools::EventMultiplexerEvent*,pEvent)
310 switch (pEvent->meEventId)
312 case tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION:
313 onSelectionChanged();
314 break;
316 case tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
317 onChangeCurrentPage();
318 break;
320 case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
321 // At this moment the controller may not yet been set at model
322 // or ViewShellBase. Take it from the view shell passed with
323 // the event.
324 if (mrBase.GetMainViewShell() != 0)
326 if( mrBase.GetMainViewShell()->GetShellType() == ViewShell::ST_IMPRESS )
328 mxView = Reference<XDrawView>::query(mrBase.GetDrawController());
329 onSelectionChanged();
330 onChangeCurrentPage();
331 break;
334 // fall through intended
335 case tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
336 mxView = 0;
337 mxCurrentPage = 0;
338 updateControls();
339 break;
341 case tools::EventMultiplexerEvent::EID_DISPOSING:
342 mxView.clear();
343 onSelectionChanged();
344 onChangeCurrentPage();
345 break;
346 case tools::EventMultiplexerEvent::EID_END_TEXT_EDIT:
347 if( mpMainSequence.get() && pEvent->mpUserData )
348 mpCustomAnimationList->update( mpMainSequence );
349 break;
351 return 0;
354 static sal_Int32 getPropertyType( const OUString& rProperty )
356 if ( rProperty == "Direction" )
357 return nPropertyTypeDirection;
359 if ( rProperty == "Spokes" )
360 return nPropertyTypeSpokes;
362 if ( rProperty == "Zoom" )
363 return nPropertyTypeZoom;
365 if ( rProperty == "Accelerate" )
366 return nPropertyTypeAccelerate;
368 if ( rProperty == "Decelerate" )
369 return nPropertyTypeDecelerate;
371 if ( rProperty == "Color1" )
372 return nPropertyTypeFirstColor;
374 if ( rProperty == "Color2" )
375 return nPropertyTypeSecondColor;
377 if ( rProperty == "FillColor" )
378 return nPropertyTypeFillColor;
380 if ( rProperty == "ColorStyle" )
381 return nPropertyTypeColorStyle;
383 if ( rProperty == "AutoReverse" )
384 return nPropertyTypeAutoReverse;
386 if ( rProperty == "FontStyle" )
387 return nPropertyTypeFont;
389 if ( rProperty == "CharColor" )
390 return nPropertyTypeCharColor;
392 if ( rProperty == "CharHeight" )
393 return nPropertyTypeCharHeight;
395 if ( rProperty == "CharDecoration" )
396 return nPropertyTypeCharDecoration;
398 if ( rProperty == "LineColor" )
399 return nPropertyTypeLineColor;
401 if ( rProperty == "Rotate" )
402 return nPropertyTypeRotate;
404 if ( rProperty == "Transparency" )
405 return nPropertyTypeTransparency;
407 if ( rProperty == "Color" )
408 return nPropertyTypeColor;
410 if ( rProperty == "Scale" )
411 return nPropertyTypeScale;
413 return nPropertyTypeNone;
416 OUString getPropertyName( sal_Int32 nPropertyType )
418 switch( nPropertyType )
420 case nPropertyTypeDirection:
421 return SD_RESSTR(STR_CUSTOMANIMATION_DIRECTION_PROPERTY);
423 case nPropertyTypeSpokes:
424 return SD_RESSTR(STR_CUSTOMANIMATION_SPOKES_PROPERTY);
426 case nPropertyTypeFirstColor:
427 return SD_RESSTR(STR_CUSTOMANIMATION_FIRST_COLOR_PROPERTY);
429 case nPropertyTypeSecondColor:
430 return SD_RESSTR(STR_CUSTOMANIMATION_SECOND_COLOR_PROPERTY);
432 case nPropertyTypeZoom:
433 return SD_RESSTR(STR_CUSTOMANIMATION_ZOOM_PROPERTY);
435 case nPropertyTypeFillColor:
436 return SD_RESSTR(STR_CUSTOMANIMATION_FILL_COLOR_PROPERTY);
438 case nPropertyTypeColorStyle:
439 return SD_RESSTR(STR_CUSTOMANIMATION_STYLE_PROPERTY);
441 case nPropertyTypeFont:
442 return SD_RESSTR(STR_CUSTOMANIMATION_FONT_PROPERTY);
444 case nPropertyTypeCharHeight:
445 return SD_RESSTR(STR_CUSTOMANIMATION_SIZE_PROPERTY);
447 case nPropertyTypeCharColor:
448 return SD_RESSTR(STR_CUSTOMANIMATION_FONT_COLOR_PROPERTY);
450 case nPropertyTypeCharHeightStyle:
451 return SD_RESSTR(STR_CUSTOMANIMATION_FONT_SIZE_STYLE_PROPERTY);
453 case nPropertyTypeCharDecoration:
454 return SD_RESSTR(STR_CUSTOMANIMATION_FONT_STYLE_PROPERTY);
456 case nPropertyTypeLineColor:
457 return SD_RESSTR(STR_CUSTOMANIMATION_LINE_COLOR_PROPERTY);
459 case nPropertyTypeRotate:
460 return SD_RESSTR(STR_CUSTOMANIMATION_AMOUNT_PROPERTY);
462 case nPropertyTypeColor:
463 return SD_RESSTR(STR_CUSTOMANIMATION_COLOR_PROPERTY);
465 case nPropertyTypeTransparency:
466 return SD_RESSTR(STR_CUSTOMANIMATION_AMOUNT_PROPERTY);
468 case nPropertyTypeScale:
469 return SD_RESSTR(STR_CUSTOMANIMATION_SCALE_PROPERTY);
472 return OUString();
475 void CustomAnimationPane::updateControls()
477 mpFTSpeed->Enable( mxView.is() );
478 mpCBSpeed->Enable( mxView.is() );
479 mpCustomAnimationList->Enable( mxView.is() );
480 mpPBMoveUp->Enable( mxView.is() );
481 mpPBMoveDown->Enable( mxView.is() );
482 mpPBPlay->Enable( mxView.is() );
483 mpCBAutoPreview->Enable( mxView.is() );
485 if( !mxView.is() )
487 mpPBAddEffect->Enable( false );
488 mpPBChangeEffect->Enable( false );
489 mpPBRemoveEffect->Enable( false );
490 mpFTStart->Enable( false );
491 mpLBStart->Enable( false );
492 mpPBPropertyMore->Enable( false );
493 mpLBProperty->Enable( false );
494 mpFTProperty->Enable( false );
495 mpCustomAnimationList->clear();
496 return;
499 const int nSelectionCount = maListSelection.size();
501 mpPBAddEffect->Enable( maViewSelection.hasValue() );
502 mpPBChangeEffect->Enable( nSelectionCount);
503 mpPBRemoveEffect->Enable(nSelectionCount);
505 mpFTStart->Enable(nSelectionCount > 0);
506 mpLBStart->Enable(nSelectionCount > 0);
507 mpPBPropertyMore->Enable(nSelectionCount > 0);
509 mpFTProperty->SetText( maStrProperty );
511 mnPropertyType = nPropertyTypeNone;
513 if( nSelectionCount == 1 )
515 CustomAnimationEffectPtr pEffect = maListSelection.front();
517 OUString aUIName( getPresets().getUINameForPresetId( pEffect->getPresetId() ) );
519 OUString aTemp( maStrModify );
521 if( !aUIName.isEmpty() )
523 aTemp += OUString( (sal_Unicode)' ' );
524 aTemp += aUIName;
525 mpFTEffect->SetText( aTemp );
528 CustomAnimationPresetPtr pDescriptor = getPresets().getEffectDescriptor( pEffect->getPresetId() );
529 if( pDescriptor.get() )
531 PropertySubControl* pSubControl = NULL;
533 Any aValue;
535 UStringList aProperties( pDescriptor->getProperties() );
536 if( aProperties.size() >= 1 )
538 mnPropertyType = getPropertyType( aProperties.front() );
540 mpFTProperty->SetText( getPropertyName( mnPropertyType ) );
542 aValue = getProperty1Value( mnPropertyType, pEffect );
545 if( aValue.hasValue() )
547 pSubControl = mpLBProperty->getSubControl();
548 if( !pSubControl || (pSubControl->getControlType() != mnPropertyType) )
550 pSubControl = PropertySubControl::create( mnPropertyType, mpPlaceholderBox, aValue, pEffect->getPresetId(), LINK( this, CustomAnimationPane, implPropertyHdl ) );
551 mpLBProperty->setSubControl( pSubControl );
553 else
555 pSubControl->setValue( aValue, pEffect->getPresetId() );
558 else
560 mpLBProperty->setSubControl( 0 );
563 bool bEnable = (pSubControl != 0) && (pSubControl->getControl()->IsEnabled());
564 mpLBProperty->Enable( bEnable );
565 mpFTProperty->Enable( bEnable );
567 else
569 mpLBProperty->setSubControl( 0 );
570 mpFTProperty->Enable( false );
571 mpLBProperty->Enable( false );
572 mpPBPropertyMore->Enable( false );
575 sal_uInt16 nPos = 0xffff;
577 sal_Int16 nNodeType = pEffect->getNodeType();
578 switch( nNodeType )
580 case EffectNodeType::ON_CLICK: nPos = 0; break;
581 case EffectNodeType::WITH_PREVIOUS: nPos = 1; break;
582 case EffectNodeType::AFTER_PREVIOUS: nPos = 2; break;
585 mpLBStart->SelectEntryPos( nPos );
587 double fDuration = pEffect->getDuration();
588 const bool bHasSpeed = fDuration > 0.001;
590 mpFTSpeed->Enable(bHasSpeed);
591 mpCBSpeed->Enable(bHasSpeed);
593 if( bHasSpeed )
595 if( fDuration == 5.0 )
596 nPos = 0;
597 else if( fDuration == 3.0 )
598 nPos = 1;
599 else if( fDuration == 2.0 )
600 nPos = 2;
601 else if( fDuration == 1.0 )
602 nPos = 3;
603 else if( fDuration == 0.5 )
604 nPos = 4;
605 else
606 nPos = 0xffff;
608 mpCBSpeed->SelectEntryPos( nPos );
611 mpPBPropertyMore->Enable( true );
613 else
615 mpLBProperty->setSubControl( 0 );
616 mpFTProperty->Enable( false );
617 mpLBProperty->Enable( false );
618 mpPBPropertyMore->Enable( false );
619 mpFTSpeed->Enable(false);
620 mpCBSpeed->Enable(false);
621 mpLBStart->SetNoSelection();
622 mpCBSpeed->SetNoSelection();
623 mpFTEffect->SetText( maStrModify );
626 bool bEnableUp = true;
627 bool bEnableDown = true;
628 if( nSelectionCount == 0 )
630 bEnableUp = false;
631 bEnableDown = false;
633 else
635 if( mpMainSequence->find( maListSelection.front() ) == mpMainSequence->getBegin() )
636 bEnableUp = false;
638 EffectSequence::iterator aIter( mpMainSequence->find( maListSelection.back() ) );
639 if( aIter == mpMainSequence->getEnd() )
641 bEnableDown = false;
643 else
647 ++aIter;
649 while( (aIter != mpMainSequence->getEnd()) && !(mpCustomAnimationList->isExpanded((*aIter)) ) );
651 if( aIter == mpMainSequence->getEnd() )
652 bEnableDown = false;
655 if( bEnableUp || bEnableDown )
657 MainSequenceRebuildGuard aGuard( mpMainSequence );
659 EffectSequenceHelper* pSequence = 0;
660 EffectSequence::iterator aRebuildIter( maListSelection.begin() );
661 const EffectSequence::iterator aRebuildEnd( maListSelection.end() );
662 while( aRebuildIter != aRebuildEnd )
664 CustomAnimationEffectPtr pEffect = (*aRebuildIter++);
666 if( pEffect.get() )
668 if( pSequence == 0 )
670 pSequence = pEffect->getEffectSequence();
672 else
674 if( pSequence != pEffect->getEffectSequence() )
676 bEnableUp = false;
677 bEnableDown = false;
678 break;
686 mpPBMoveUp->Enable(bEnableUp);
687 mpPBMoveDown->Enable(bEnableDown);
689 SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
690 mpCBAutoPreview->Check( pOptions->IsPreviewChangedEffects() );
692 updateMotionPathTags();
695 static bool updateMotionPathImpl( CustomAnimationPane& rPane, ::sd::View& rView, EffectSequence::iterator aIter, EffectSequence::iterator aEnd, MotionPathTagVector& rOldTags, MotionPathTagVector& rNewTags )
697 bool bChanges = false;
698 while( aIter != aEnd )
700 CustomAnimationEffectPtr pEffect( (*aIter++) );
701 if( pEffect.get() && pEffect->getPresetClass() == ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH )
703 rtl::Reference< MotionPathTag > xMotionPathTag;
704 // first try to find if there is already a tag for this
705 MotionPathTagVector::iterator aMIter( rOldTags.begin() );
706 for( ; aMIter != rOldTags.end(); ++aMIter )
708 rtl::Reference< MotionPathTag > xTag( (*aMIter) );
709 if( xTag->getEffect() == pEffect )
711 if( !xTag->isDisposed() )
713 xMotionPathTag = xTag;
714 rOldTags.erase( aMIter );
716 break;
720 // if not found, create new one
721 if( !xMotionPathTag.is() )
723 xMotionPathTag.set( new MotionPathTag( rPane, rView, pEffect ) );
724 bChanges = true;
727 if( xMotionPathTag.is() )
728 rNewTags.push_back( xMotionPathTag );
732 return bChanges;
735 void CustomAnimationPane::updateMotionPathTags()
737 bool bChanges = false;
739 MotionPathTagVector aTags;
740 aTags.swap( maMotionPathTags );
742 ::sd::View* pView = 0;
744 if( mxView.is() )
746 ::boost::shared_ptr<ViewShell> xViewShell( mrBase.GetMainViewShell() );
747 if( xViewShell.get() )
748 pView = xViewShell->GetView();
751 if( IsVisible() && mpMainSequence.get() && pView )
753 bChanges = updateMotionPathImpl( *this, *pView, mpMainSequence->getBegin(), mpMainSequence->getEnd(), aTags, maMotionPathTags );
755 const InteractiveSequenceList& rISL = mpMainSequence->getInteractiveSequenceList();
756 InteractiveSequenceList::const_iterator aISI( rISL.begin() );
757 while( aISI != rISL.end() )
759 InteractiveSequencePtr pIS( (*aISI++) );
760 bChanges |= updateMotionPathImpl( *this, *pView, pIS->getBegin(), pIS->getEnd(), aTags, maMotionPathTags );
764 if( !aTags.empty() )
766 bChanges = true;
767 MotionPathTagVector::iterator aIter( aTags.begin() );
768 while( aIter != aTags.end() )
770 rtl::Reference< MotionPathTag > xTag( (*aIter++) );
771 xTag->Dispose();
775 if( bChanges && pView )
776 pView->updateHandles();
779 void CustomAnimationPane::onSelectionChanged()
781 if( !maSelectionLock.isLocked() )
783 ScopeLockGuard aGuard( maSelectionLock );
785 if( mxView.is() ) try
787 Reference< XSelectionSupplier > xSel( mxView, UNO_QUERY_THROW );
788 if (xSel.is())
790 maViewSelection = xSel->getSelection();
791 mpCustomAnimationList->onSelectionChanged( maViewSelection );
792 updateControls();
795 catch( Exception& )
797 OSL_FAIL( "sd::CustomAnimationPane::onSelectionChanged(), Exception caught!" );
802 void CustomAnimationPane::onDoubleClick()
804 showOptions();
807 void CustomAnimationPane::onContextMenu( sal_uInt16 nSelectedPopupEntry )
809 switch( nSelectedPopupEntry )
811 case CM_WITH_CLICK: onChangeStart( EffectNodeType::ON_CLICK ); break;
812 case CM_WITH_PREVIOUS: onChangeStart( EffectNodeType::WITH_PREVIOUS ); break;
813 case CM_AFTER_PREVIOUS: onChangeStart( EffectNodeType::AFTER_PREVIOUS ); break;
814 case CM_OPTIONS: showOptions(); break;
815 case CM_DURATION: showOptions("timing"); break;
816 case CM_REMOVE: onRemove(); break;
817 case CM_CREATE: if( maViewSelection.hasValue() ) onChange( true ); break;
820 updateControls();
823 void CustomAnimationPane::DataChanged (const DataChangedEvent& rEvent)
825 (void)rEvent;
826 UpdateLook();
829 void CustomAnimationPane::UpdateLook()
831 const Wallpaper aBackground (
832 ::sfx2::sidebar::Theme::GetWallpaper(
833 ::sfx2::sidebar::Theme::Paint_PanelBackground));
834 SetBackground(aBackground);
835 if (mpFTStart != nullptr)
836 mpFTStart->SetBackground(aBackground);
837 if (mpFTProperty != nullptr)
838 mpFTProperty->SetBackground(aBackground);
839 if (mpFTSpeed != nullptr)
840 mpFTSpeed->SetBackground(aBackground);
843 void addValue( STLPropertySet* pSet, sal_Int32 nHandle, const Any& rValue )
845 switch( pSet->getPropertyState( nHandle ) )
847 case STLPropertyState_AMBIGUOUS:
848 // value is already ambiguous, do nothing
849 break;
850 case STLPropertyState_DIRECT:
851 // set to ambiguous if existing value is different
852 if( rValue != pSet->getPropertyValue( nHandle ) )
853 pSet->setPropertyState( nHandle, STLPropertyState_AMBIGUOUS );
854 break;
855 case STLPropertyState_DEFAULT:
856 // just set new value
857 pSet->setPropertyValue( nHandle, rValue );
858 break;
862 static sal_Int32 calcMaxParaDepth( Reference< XShape > xTargetShape )
864 sal_Int32 nMaxParaDepth = -1;
866 if( xTargetShape.is() )
868 Reference< XEnumerationAccess > xText( xTargetShape, UNO_QUERY );
869 if( xText.is() )
871 Reference< XPropertySet > xParaSet;
872 const OUString strNumberingLevel( "NumberingLevel" );
874 Reference< XEnumeration > xEnumeration( xText->createEnumeration(), UNO_QUERY_THROW );
875 while( xEnumeration->hasMoreElements() )
877 xEnumeration->nextElement() >>= xParaSet;
878 if( xParaSet.is() )
880 sal_Int32 nParaDepth = 0;
881 xParaSet->getPropertyValue( strNumberingLevel ) >>= nParaDepth;
883 if( nParaDepth > nMaxParaDepth )
884 nMaxParaDepth = nParaDepth;
890 return nMaxParaDepth + 1;
893 Any CustomAnimationPane::getProperty1Value( sal_Int32 nType, CustomAnimationEffectPtr pEffect )
895 switch( nType )
897 case nPropertyTypeDirection:
898 case nPropertyTypeSpokes:
899 case nPropertyTypeZoom:
900 return makeAny( pEffect->getPresetSubType() );
902 case nPropertyTypeColor:
903 case nPropertyTypeFillColor:
904 case nPropertyTypeFirstColor:
905 case nPropertyTypeSecondColor:
906 case nPropertyTypeCharColor:
907 case nPropertyTypeLineColor:
909 const sal_Int32 nIndex = (nPropertyTypeFirstColor == nType) ? 0 : 1;
910 return pEffect->getColor( nIndex );
913 case nPropertyTypeFont:
914 return pEffect->getProperty( AnimationNodeType::SET, "CharFontName" , VALUE_TO );
916 case nPropertyTypeCharHeight:
918 const OUString aAttributeName( "CharHeight" );
919 Any aValue( pEffect->getProperty( AnimationNodeType::SET, aAttributeName, VALUE_TO ) );
920 if( !aValue.hasValue() )
921 aValue = pEffect->getProperty( AnimationNodeType::ANIMATE, aAttributeName, VALUE_TO );
922 return aValue;
925 case nPropertyTypeRotate:
926 return pEffect->getTransformationProperty( AnimationTransformType::ROTATE, VALUE_BY);
928 case nPropertyTypeTransparency:
929 return pEffect->getProperty( AnimationNodeType::SET, "Opacity" , VALUE_TO );
931 case nPropertyTypeScale:
932 return pEffect->getTransformationProperty( AnimationTransformType::SCALE, VALUE_BY );
934 case nPropertyTypeCharDecoration:
936 Sequence< Any > aValues(3);
937 aValues[0] = pEffect->getProperty( AnimationNodeType::SET, "CharWeight" , VALUE_TO );
938 aValues[1] = pEffect->getProperty( AnimationNodeType::SET, "CharPosture" , VALUE_TO );
939 aValues[2] = pEffect->getProperty( AnimationNodeType::SET, "CharUnderline" , VALUE_TO );
940 return makeAny( aValues );
944 Any aAny;
945 return aAny;
948 bool CustomAnimationPane::setProperty1Value( sal_Int32 nType, CustomAnimationEffectPtr pEffect, const Any& rValue )
950 bool bEffectChanged = false;
951 switch( nType )
953 case nPropertyTypeDirection:
954 case nPropertyTypeSpokes:
955 case nPropertyTypeZoom:
957 OUString aPresetSubType;
958 rValue >>= aPresetSubType;
959 if( aPresetSubType != pEffect->getPresetSubType() )
961 getPresets().changePresetSubType( pEffect, aPresetSubType );
962 bEffectChanged = true;
965 break;
967 case nPropertyTypeFillColor:
968 case nPropertyTypeColor:
969 case nPropertyTypeFirstColor:
970 case nPropertyTypeSecondColor:
971 case nPropertyTypeCharColor:
972 case nPropertyTypeLineColor:
974 const sal_Int32 nIndex = (nPropertyTypeFirstColor == nType) ? 0 : 1;
975 Any aOldColor( pEffect->getColor( nIndex ) );
976 if( aOldColor != rValue )
978 pEffect->setColor( nIndex, rValue );
979 bEffectChanged = true;
982 break;
984 case nPropertyTypeFont:
985 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, "CharFontName" , VALUE_TO, rValue );
986 break;
988 case nPropertyTypeCharHeight:
990 const OUString aAttributeName( "CharHeight" );
991 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, aAttributeName, VALUE_TO, rValue );
992 if( !bEffectChanged )
993 bEffectChanged = pEffect->setProperty( AnimationNodeType::ANIMATE, aAttributeName, VALUE_TO, rValue );
995 break;
996 case nPropertyTypeRotate:
997 bEffectChanged = pEffect->setTransformationProperty( AnimationTransformType::ROTATE, VALUE_BY , rValue );
998 break;
1000 case nPropertyTypeTransparency:
1001 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, "Opacity" , VALUE_TO, rValue );
1002 break;
1004 case nPropertyTypeScale:
1005 bEffectChanged = pEffect->setTransformationProperty( AnimationTransformType::SCALE, VALUE_BY, rValue );
1006 break;
1008 case nPropertyTypeCharDecoration:
1010 Sequence< Any > aValues(3);
1011 rValue >>= aValues;
1012 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, "CharWeight" , VALUE_TO, aValues[0] );
1013 bEffectChanged |= pEffect->setProperty( AnimationNodeType::SET, "CharPosture" , VALUE_TO, aValues[1] );
1014 bEffectChanged |= pEffect->setProperty( AnimationNodeType::SET, "CharUnderline" , VALUE_TO, aValues[2] );
1016 break;
1020 return bEffectChanged;
1023 static bool hasVisibleShape( const Reference< XShape >& xShape )
1027 const OUString sShapeType( xShape->getShapeType() );
1029 if( sShapeType == "com.sun.star.presentation.TitleTextShape" || sShapeType == "com.sun.star.presentation.OutlinerShape" ||
1030 sShapeType == "com.sun.star.presentation.SubtitleShape" || sShapeType == "com.sun.star.drawing.TextShape" )
1032 const OUString sFillStyle( "FillStyle" );
1033 const OUString sLineStyle( "LineStyle" );
1034 Reference< XPropertySet > xSet( xShape, UNO_QUERY_THROW );
1036 FillStyle eFillStyle;
1037 xSet->getPropertyValue( sFillStyle ) >>= eFillStyle;
1039 ::com::sun::star::drawing::LineStyle eLineStyle;
1040 xSet->getPropertyValue( sLineStyle ) >>= eLineStyle;
1042 return eFillStyle != FillStyle_NONE || eLineStyle != ::com::sun::star::drawing::LineStyle_NONE;
1045 catch( Exception& )
1048 return true;
1051 STLPropertySet* CustomAnimationPane::createSelectionSet()
1053 STLPropertySet* pSet = CustomAnimationDialog::createDefaultSet();
1055 pSet->setPropertyValue( nHandleCurrentPage, makeAny( mxCurrentPage ) );
1057 sal_Int32 nMaxParaDepth = 0;
1059 // get options from selected effects
1060 EffectSequence::iterator aIter( maListSelection.begin() );
1061 const EffectSequence::iterator aEnd( maListSelection.end() );
1062 const CustomAnimationPresets& rPresets (getPresets());
1063 while( aIter != aEnd )
1065 CustomAnimationEffectPtr pEffect = (*aIter++);
1067 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
1068 if( !pEffectSequence )
1069 pEffectSequence = mpMainSequence.get();
1071 if( pEffect->hasText() )
1073 sal_Int32 n = calcMaxParaDepth(pEffect->getTargetShape());
1074 if( n > nMaxParaDepth )
1075 nMaxParaDepth = n;
1078 addValue( pSet, nHandleHasAfterEffect, makeAny( pEffect->hasAfterEffect() ) );
1079 addValue( pSet, nHandleAfterEffectOnNextEffect, makeAny( pEffect->IsAfterEffectOnNext() ? sal_True : sal_False ) );
1080 addValue( pSet, nHandleDimColor, pEffect->getDimColor() );
1081 addValue( pSet, nHandleIterateType, makeAny( pEffect->getIterateType() ) );
1083 // convert absolute time to percentage value
1084 // This calculation is done in float to avoid some rounding artifacts.
1085 float fIterateInterval = (float)pEffect->getIterateInterval();
1086 if( pEffect->getDuration() )
1087 fIterateInterval = (float)(fIterateInterval / pEffect->getDuration() );
1088 fIterateInterval *= 100.0;
1089 addValue( pSet, nHandleIterateInterval, makeAny( (double)fIterateInterval ) );
1091 addValue( pSet, nHandleBegin, makeAny( pEffect->getBegin() ) );
1092 addValue( pSet, nHandleDuration, makeAny( pEffect->getDuration() ) );
1093 addValue( pSet, nHandleStart, makeAny( pEffect->getNodeType() ) );
1094 addValue( pSet, nHandleRepeat, pEffect->getRepeatCount() );
1095 addValue( pSet, nHandleEnd, pEffect->getEnd() );
1096 addValue( pSet, nHandleRewind, makeAny( pEffect->getFill() ) );
1098 addValue( pSet, nHandlePresetId, makeAny( pEffect->getPresetId() ) );
1100 addValue( pSet, nHandleHasText, makeAny( pEffect->hasText() ) );
1102 addValue( pSet, nHandleHasVisibleShape, Any( hasVisibleShape( pEffect->getTargetShape() ) ) );
1104 Any aSoundSource;
1105 if( pEffect->getAudio().is() )
1107 aSoundSource = pEffect->getAudio()->getSource();
1108 addValue( pSet, nHandleSoundVolumne, makeAny( pEffect->getAudio()->getVolume() ) );
1109 // todo addValue( pSet, nHandleSoundEndAfterSlide, makeAny( pEffect->getAudio()->getEndAfterSlide() ) );
1110 // this is now stored at the XCommand parameter sequence
1112 else if( pEffect->getCommand() == EffectCommands::STOPAUDIO )
1114 aSoundSource = makeAny( true );
1116 addValue( pSet, nHandleSoundURL, aSoundSource );
1118 sal_Int32 nGroupId = pEffect->getGroupId();
1119 CustomAnimationTextGroupPtr pTextGroup;
1120 if( nGroupId != -1 )
1121 pTextGroup = pEffectSequence->findGroup( nGroupId );
1123 addValue( pSet, nHandleTextGrouping, makeAny( pTextGroup.get() ? pTextGroup->getTextGrouping() : (sal_Int32)-1 ) );
1124 addValue( pSet, nHandleAnimateForm, makeAny( pTextGroup.get() == nullptr || pTextGroup->getAnimateForm() ) );
1125 addValue( pSet, nHandleTextGroupingAuto, makeAny( pTextGroup.get() ? pTextGroup->getTextGroupingAuto() : (double)-1.0 ) );
1126 addValue( pSet, nHandleTextReverse, makeAny( pTextGroup.get() && pTextGroup->getTextReverse() ) );
1128 if( pEffectSequence->getSequenceType() == EffectNodeType::INTERACTIVE_SEQUENCE )
1130 InteractiveSequence* pIS = static_cast< InteractiveSequence* >( pEffectSequence );
1131 addValue( pSet, nHandleTrigger, makeAny( pIS->getTriggerShape() ) );
1134 CustomAnimationPresetPtr pDescriptor = rPresets.getEffectDescriptor( pEffect->getPresetId() );
1135 if( pDescriptor.get() )
1137 sal_Int32 nType = nPropertyTypeNone;
1139 UStringList aProperties( pDescriptor->getProperties() );
1140 if( aProperties.size() >= 1 )
1141 nType = getPropertyType( aProperties.front() );
1143 if( nType != nPropertyTypeNone )
1145 addValue( pSet, nHandleProperty1Type, makeAny( nType ) );
1146 addValue( pSet, nHandleProperty1Value, getProperty1Value( nType, pEffect ) );
1149 if( pDescriptor->hasProperty( "Accelerate" ) )
1151 addValue( pSet, nHandleAccelerate, makeAny( pEffect->getAcceleration() ) );
1154 if( pDescriptor->hasProperty( "Decelerate" ) )
1156 addValue( pSet, nHandleDecelerate, makeAny( pEffect->getDecelerate() ) );
1159 if( pDescriptor->hasProperty( "AutoReverse" ) )
1161 addValue( pSet, nHandleAutoReverse, makeAny( pEffect->getAutoReverse() ) );
1166 addValue( pSet, nHandleMaxParaDepth, makeAny( nMaxParaDepth ) );
1168 return pSet;
1171 void CustomAnimationPane::changeSelection( STLPropertySet* pResultSet, STLPropertySet* pOldSet )
1173 // change selected effect
1174 bool bChanged = false;
1176 MainSequenceRebuildGuard aGuard( mpMainSequence );
1178 EffectSequence::iterator aIter( maListSelection.begin() );
1179 const EffectSequence::iterator aEnd( maListSelection.end() );
1180 while( aIter != aEnd )
1182 CustomAnimationEffectPtr pEffect = (*aIter++);
1184 DBG_ASSERT( pEffect->getEffectSequence(), "sd::CustomAnimationPane::changeSelection(), dead effect in selection!" );
1185 if( !pEffect->getEffectSequence() )
1186 continue;
1188 double fDuration = 0.0; // we might need this for iterate-interval
1189 if( pResultSet->getPropertyState( nHandleDuration ) == STLPropertyState_DIRECT )
1191 pResultSet->getPropertyValue( nHandleDuration ) >>= fDuration;
1193 else
1195 fDuration = pEffect->getDuration();
1198 if( pResultSet->getPropertyState( nHandleIterateType ) == STLPropertyState_DIRECT )
1200 sal_Int16 nIterateType = 0;
1201 pResultSet->getPropertyValue( nHandleIterateType ) >>= nIterateType;
1202 if( pEffect->getIterateType() != nIterateType )
1204 pEffect->setIterateType( nIterateType );
1205 bChanged = true;
1209 if( pEffect->getIterateType() )
1211 if( pResultSet->getPropertyState( nHandleIterateInterval ) == STLPropertyState_DIRECT )
1213 double fIterateInterval = 0.0;
1214 pResultSet->getPropertyValue( nHandleIterateInterval ) >>= fIterateInterval;
1215 if( pEffect->getIterateInterval() != fIterateInterval )
1217 const double f = fIterateInterval * pEffect->getDuration() / 100;
1218 pEffect->setIterateInterval( f );
1219 bChanged = true;
1224 if( pResultSet->getPropertyState( nHandleBegin ) == STLPropertyState_DIRECT )
1226 double fBegin = 0.0;
1227 pResultSet->getPropertyValue( nHandleBegin ) >>= fBegin;
1228 if( pEffect->getBegin() != fBegin )
1230 pEffect->setBegin( fBegin );
1231 bChanged = true;
1235 if( pResultSet->getPropertyState( nHandleDuration ) == STLPropertyState_DIRECT )
1237 if( pEffect->getDuration() != fDuration )
1239 pEffect->setDuration( fDuration );
1240 bChanged = true;
1244 if( pResultSet->getPropertyState( nHandleStart ) == STLPropertyState_DIRECT )
1246 sal_Int16 nNodeType = 0;
1247 pResultSet->getPropertyValue( nHandleStart ) >>= nNodeType;
1248 if( pEffect->getNodeType() != nNodeType )
1250 pEffect->setNodeType( nNodeType );
1251 bChanged = true;
1255 if( pResultSet->getPropertyState( nHandleRepeat ) == STLPropertyState_DIRECT )
1257 Any aRepeatCount( pResultSet->getPropertyValue( nHandleRepeat ) );
1258 if( aRepeatCount != pEffect->getRepeatCount() )
1260 pEffect->setRepeatCount( aRepeatCount );
1261 bChanged = true;
1265 if( pResultSet->getPropertyState( nHandleEnd ) == STLPropertyState_DIRECT )
1267 Any aEndValue( pResultSet->getPropertyValue( nHandleEnd ) );
1268 if( pEffect->getEnd() != aEndValue )
1270 pEffect->setEnd( aEndValue );
1271 bChanged = true;
1275 if( pResultSet->getPropertyState( nHandleRewind ) == STLPropertyState_DIRECT )
1277 sal_Int16 nFill = 0;
1278 pResultSet->getPropertyValue( nHandleRewind ) >>= nFill;
1279 if( pEffect->getFill() != nFill )
1281 pEffect->setFill( nFill );
1282 bChanged = true;
1286 if( pResultSet->getPropertyState( nHandleHasAfterEffect ) == STLPropertyState_DIRECT )
1288 bool bHasAfterEffect = false;
1289 if( pResultSet->getPropertyValue( nHandleHasAfterEffect ) >>= bHasAfterEffect )
1291 if( pEffect->hasAfterEffect() != bHasAfterEffect )
1293 pEffect->setHasAfterEffect( bHasAfterEffect );
1294 bChanged = true;
1299 if( pResultSet->getPropertyState( nHandleAfterEffectOnNextEffect ) == STLPropertyState_DIRECT )
1301 bool bAfterEffectOnNextEffect = false;
1302 if( (pResultSet->getPropertyValue( nHandleAfterEffectOnNextEffect ) >>= bAfterEffectOnNextEffect)
1303 && (pEffect->IsAfterEffectOnNext() != bAfterEffectOnNextEffect) )
1305 pEffect->setAfterEffectOnNext( bAfterEffectOnNextEffect );
1306 bChanged = true;
1310 if( pResultSet->getPropertyState( nHandleDimColor ) == STLPropertyState_DIRECT )
1312 Any aDimColor( pResultSet->getPropertyValue( nHandleDimColor ) );
1313 if( pEffect->getDimColor() != aDimColor )
1315 pEffect->setDimColor( aDimColor );
1316 bChanged = true;
1320 if( pResultSet->getPropertyState( nHandleAccelerate ) == STLPropertyState_DIRECT )
1322 double fAccelerate = 0.0;
1323 pResultSet->getPropertyValue( nHandleAccelerate ) >>= fAccelerate;
1324 if( pEffect->getAcceleration() != fAccelerate )
1326 pEffect->setAcceleration( fAccelerate );
1327 bChanged = true;
1331 if( pResultSet->getPropertyState( nHandleDecelerate ) == STLPropertyState_DIRECT )
1333 double fDecelerate = 0.0;
1334 pResultSet->getPropertyValue( nHandleDecelerate ) >>= fDecelerate;
1335 if( pEffect->getDecelerate() != fDecelerate )
1337 pEffect->setDecelerate( fDecelerate );
1338 bChanged = true;
1342 if( pResultSet->getPropertyState( nHandleAutoReverse ) == STLPropertyState_DIRECT )
1344 bool bAutoReverse = false;
1345 pResultSet->getPropertyValue( nHandleAutoReverse ) >>= bAutoReverse;
1346 if( pEffect->getAutoReverse() != bAutoReverse )
1348 pEffect->setAutoReverse( bAutoReverse );
1349 bChanged = true;
1353 if( pResultSet->getPropertyState( nHandleProperty1Value ) == STLPropertyState_DIRECT )
1355 sal_Int32 nType = 0;
1356 pOldSet->getPropertyValue( nHandleProperty1Type ) >>= nType;
1358 bChanged |= setProperty1Value( nType, pEffect, pResultSet->getPropertyValue( nHandleProperty1Value ) );
1361 if( pResultSet->getPropertyState( nHandleSoundURL ) == STLPropertyState_DIRECT )
1363 const Any aSoundSource( pResultSet->getPropertyValue( nHandleSoundURL ) );
1365 if( aSoundSource.getValueType() == ::cppu::UnoType<sal_Bool>::get() )
1367 pEffect->setStopAudio();
1368 bChanged = true;
1370 else
1372 OUString aSoundURL;
1373 aSoundSource >>= aSoundURL;
1375 if( !aSoundURL.isEmpty() )
1377 if( !pEffect->getAudio().is() )
1379 pEffect->createAudio( aSoundSource );
1380 bChanged = true;
1382 else
1384 if( pEffect->getAudio()->getSource() != aSoundSource )
1386 pEffect->getAudio()->setSource( aSoundSource );
1387 bChanged = true;
1391 else
1393 if( pEffect->getAudio().is() || pEffect->getStopAudio() )
1395 pEffect->removeAudio();
1396 bChanged = true;
1402 if( pResultSet->getPropertyState( nHandleTrigger ) == STLPropertyState_DIRECT )
1404 Reference< XShape > xTriggerShape;
1405 pResultSet->getPropertyValue( nHandleTrigger ) >>= xTriggerShape;
1406 bChanged |= mpMainSequence->setTrigger( pEffect, xTriggerShape );
1410 const bool bHasTextGrouping = pResultSet->getPropertyState( nHandleTextGrouping ) == STLPropertyState_DIRECT;
1411 const bool bHasAnimateForm = pResultSet->getPropertyState( nHandleAnimateForm ) == STLPropertyState_DIRECT;
1412 const bool bHasTextGroupingAuto = pResultSet->getPropertyState( nHandleTextGroupingAuto ) == STLPropertyState_DIRECT;
1413 const bool bHasTextReverse = pResultSet->getPropertyState( nHandleTextReverse ) == STLPropertyState_DIRECT;
1415 if( bHasTextGrouping || bHasAnimateForm || bHasTextGroupingAuto || bHasTextReverse )
1417 // we need to do a second pass for text grouping options
1418 // since changing them can cause effects to be removed
1419 // or replaced, we do this after we applied all other options
1420 // above
1422 sal_Int32 nTextGrouping = 0;
1423 bool bAnimateForm = true, bTextReverse = false;
1424 double fTextGroupingAuto = -1.0;
1426 if( bHasTextGrouping )
1427 pResultSet->getPropertyValue(nHandleTextGrouping) >>= nTextGrouping;
1429 if( bHasAnimateForm )
1430 pResultSet->getPropertyValue(nHandleAnimateForm) >>= bAnimateForm;
1432 if( bHasTextGroupingAuto )
1433 pResultSet->getPropertyValue(nHandleTextGroupingAuto) >>= fTextGroupingAuto;
1435 if( bHasTextReverse )
1436 pResultSet->getPropertyValue(nHandleTextReverse) >>= bTextReverse;
1438 EffectSequence const aSelectedEffects( maListSelection );
1439 EffectSequence::const_iterator iter( aSelectedEffects.begin() );
1440 const EffectSequence::const_iterator iEnd( aSelectedEffects.end() );
1441 while( iter != iEnd )
1443 CustomAnimationEffectPtr const& pEffect = (*iter++);
1445 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
1446 if( !pEffectSequence )
1447 pEffectSequence = mpMainSequence.get();
1449 sal_Int32 nGroupId = pEffect->getGroupId();
1450 CustomAnimationTextGroupPtr pTextGroup;
1451 if( (nGroupId != -1) )
1453 // use existing group
1454 pTextGroup = pEffectSequence->findGroup( nGroupId );
1456 else
1458 // somethings changed so we need a group now
1459 pTextGroup = pEffectSequence->createTextGroup( pEffect, nTextGrouping, fTextGroupingAuto, bAnimateForm, bTextReverse );
1460 bChanged = true;
1463 //#i119988#
1464 /************************************************************************/
1466 Note, the setAnimateForm means set the animation from TextGroup to Object's Shape
1467 And on the UI in means "Animate attached shape" in "Effect Option" dialog
1468 The setTextGrouping means set animation to Object's Text,
1469 the nTextGrouping is Text Animation Type
1470 nTextGrouping = -1 is "As one Object", means no text animation.
1472 The previous call order first do the setTextGrouping and then do the setAnimateForm,
1473 that will cause such defect: in the setTextGrouping, the effect has been removed,
1474 but in setAnimateForm still need this effect, then a NULL pointer of that effect will
1475 be gotten, and cause crash.
1477 []bHasAnimateForm means the UI has changed, bAnimateForm is it value
1479 So if create a new textgroup animation, the following animation will never be run!
1480 Since the \A1\B0Animate attached shape\A1\B1 is default checked.
1481 And the bHasAnimateForm default is false, and if user uncheck it the value bAnimateForm will be false,
1482 it same as the TextGroup\A1\AFs default value, also could not be run setAnimateForm.
1483 if( bHasAnimateForm )
1485 if( pTextGroup->getAnimateForm() != bAnimateForm )
1487 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1488 bChanged = true;
1492 In setTextGrouping, there are three case:
1493 1. Create new text effects for empty TextGroup
1494 2. Remove all text effects of TextGroup (nTextGrouping == -1)
1495 3. Change all the text effects\A1\AF start type
1497 So here is the right logic:
1498 If set the animation from text to shape and remove text animation,
1499 should do setAnimateForm first, then do setTextGrouping.
1500 Other case,do setTextGrouping first, then do setAnimateForm.
1503 /************************************************************************/
1505 bool bDoSetAnimateFormFirst = false;
1506 bool bNeedDoSetAnimateForm = false;
1508 if( bHasAnimateForm )
1510 if( pTextGroup.get() && pTextGroup->getAnimateForm() != bAnimateForm )
1512 if( (pTextGroup->getTextGrouping() >= 0) && (nTextGrouping == -1 ) )
1514 bDoSetAnimateFormFirst = true;
1516 bNeedDoSetAnimateForm = true;
1520 if (bDoSetAnimateFormFirst)
1522 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1523 bChanged = true;
1526 if( bHasTextGrouping )
1528 if( pTextGroup.get() && pTextGroup->getTextGrouping() != nTextGrouping )
1530 pEffectSequence->setTextGrouping( pTextGroup, nTextGrouping );
1531 bChanged = true;
1535 if (!bDoSetAnimateFormFirst && bNeedDoSetAnimateForm)
1537 if( pTextGroup.get() )
1539 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1540 bChanged = true;
1544 if( bHasTextGroupingAuto )
1546 if( pTextGroup.get() && pTextGroup->getTextGroupingAuto() != fTextGroupingAuto )
1548 pEffectSequence->setTextGroupingAuto( pTextGroup, fTextGroupingAuto );
1549 bChanged = true;
1553 if( bHasTextReverse )
1555 if( pTextGroup.get() && pTextGroup->getTextReverse() != bTextReverse )
1557 pEffectSequence->setTextReverse( pTextGroup, bTextReverse );
1558 bChanged = true;
1564 if( bChanged )
1566 mpMainSequence->rebuild();
1567 updateControls();
1568 mrBase.GetDocShell()->SetModified();
1572 void CustomAnimationPane::showOptions(const OString& sPage)
1574 STLPropertySet* pSet = createSelectionSet();
1576 VclPtrInstance< CustomAnimationDialog > pDlg(this, pSet, sPage);
1577 if( pDlg->Execute() )
1579 addUndo();
1580 changeSelection( pDlg->getResultSet(), pSet );
1581 updateControls();
1585 void CustomAnimationPane::onChangeCurrentPage()
1587 if( mxView.is() ) try
1589 Reference< XDrawPage > xNewPage( mxView->getCurrentPage() );
1590 if( xNewPage != mxCurrentPage )
1592 mxCurrentPage = xNewPage;
1593 SdPage* pPage = SdPage::getImplementation( mxCurrentPage );
1594 if( pPage )
1596 mpMainSequence = pPage->getMainSequence();
1597 mpCustomAnimationList->update( mpMainSequence );
1599 updateControls();
1602 catch( Exception& )
1604 OSL_FAIL( "sd::CustomAnimationPane::onChangeCurrentPage(), exception caught!" );
1608 bool getTextSelection( const Any& rSelection, Reference< XShape >& xShape, std::list< sal_Int16 >& rParaList )
1610 Reference< XTextRange > xSelectedText;
1611 rSelection >>= xSelectedText;
1612 if( xSelectedText.is() ) try
1614 xShape.set( xSelectedText->getText(), UNO_QUERY_THROW );
1616 Reference< XTextRangeCompare > xTextRangeCompare( xShape, UNO_QUERY_THROW );
1617 Reference< XEnumerationAccess > xParaEnumAccess( xShape, UNO_QUERY_THROW );
1618 Reference< XEnumeration > xParaEnum( xParaEnumAccess->createEnumeration(), UNO_QUERY_THROW );
1619 Reference< XTextRange > xRange;
1620 Reference< XTextRange > xStart( xSelectedText->getStart() );
1621 Reference< XTextRange > xEnd( xSelectedText->getEnd() );
1623 if( xTextRangeCompare->compareRegionEnds( xStart, xEnd ) < 0 )
1625 Reference< XTextRange > xTemp( xStart );
1626 xStart = xEnd;
1627 xEnd = xTemp;
1630 sal_Int16 nPara = 0;
1631 while( xParaEnum->hasMoreElements() )
1633 xParaEnum->nextElement() >>= xRange;
1635 // break if start of selection is prior to end of current paragraph
1636 if( xRange.is() && (xTextRangeCompare->compareRegionEnds( xStart, xRange ) >= 0 ) )
1637 break;
1639 nPara++;
1642 while( xRange.is() )
1644 if( xRange.is() && !xRange->getString().isEmpty() )
1645 rParaList.push_back( nPara );
1647 // break if end of selection is before or at end of current paragraph
1648 if( xRange.is() && xTextRangeCompare->compareRegionEnds( xEnd, xRange ) >= 0 )
1649 break;
1651 nPara++;
1653 if( xParaEnum->hasMoreElements() )
1654 xParaEnum->nextElement() >>= xRange;
1655 else
1656 xRange.clear();
1659 return true;
1661 catch( Exception& )
1663 OSL_FAIL( "sd::CustomAnimationPane::getTextSelection(), exception caught!" );
1666 return false;
1669 void CustomAnimationPane::onChange( bool bCreate )
1671 bool bHasText = true;
1673 // first create vector of targets for dialog preview
1674 std::vector< Any > aTargets;
1675 OUString sPresetId;
1676 double fDuration = 2.0f;
1678 if( bCreate )
1680 // gather shapes from the selection
1681 Reference< XSelectionSupplier > xSel( mxView, UNO_QUERY_THROW );
1682 maViewSelection = xSel->getSelection();
1684 if( maViewSelection.getValueType() == cppu::UnoType<XShapes>::get())
1686 Reference< XIndexAccess > xShapes;
1687 maViewSelection >>= xShapes;
1689 sal_Int32 nCount = xShapes->getCount();
1690 sal_Int32 nIndex;
1691 for( nIndex = 0; nIndex < nCount; nIndex++ )
1693 Any aTarget( xShapes->getByIndex( nIndex ) );
1694 aTargets.push_back( aTarget );
1695 if( bHasText )
1697 Reference< XText > xText;
1698 aTarget >>= xText;
1699 if( !xText.is() || xText->getString().isEmpty() )
1700 bHasText = false;
1704 else if ( maViewSelection.getValueType() == cppu::UnoType<XShape>::get())
1706 aTargets.push_back( maViewSelection );
1707 Reference< XText > xText;
1708 maViewSelection >>= xText;
1709 if( !xText.is() || xText->getString().isEmpty() )
1710 bHasText = false;
1712 else if ( maViewSelection.getValueType() == cppu::UnoType<XTextCursor>::get())
1714 Reference< XShape > xShape;
1715 std::list< sal_Int16 > aParaList;
1716 if( getTextSelection( maViewSelection, xShape, aParaList ) )
1718 ParagraphTarget aParaTarget;
1719 aParaTarget.Shape = xShape;
1721 std::list< sal_Int16 >::iterator aIter( aParaList.begin() );
1722 for( ; aIter != aParaList.end(); ++aIter )
1724 aParaTarget.Paragraph = (*aIter);
1725 aTargets.push_back( makeAny( aParaTarget ) );
1729 else
1731 OSL_FAIL("sd::CustomAnimationPane::onChange(), unknown view selection!" );
1732 return;
1735 else
1737 // get selected effect
1738 EffectSequence::iterator aIter( maListSelection.begin() );
1739 const EffectSequence::iterator aEnd( maListSelection.end() );
1740 while( aIter != aEnd )
1742 if( !bHasText || !(*aIter)->hasText() )
1743 bHasText = false;
1745 if( sPresetId.isEmpty() )
1747 sPresetId = (*aIter)->getPresetId();
1748 fDuration = (*aIter)->getDuration();
1751 aTargets.push_back( (*aIter++)->getTarget() );
1756 ScopedVclPtrInstance< CustomAnimationCreateDialog > pDlg( this, this, aTargets, bHasText, sPresetId, fDuration );
1757 if( pDlg->Execute() )
1759 addUndo();
1760 fDuration = pDlg->getSelectedDuration();
1761 CustomAnimationPresetPtr pDescriptor = pDlg->getSelectedPreset();
1762 if( pDescriptor.get() )
1764 if( bCreate )
1766 mpCustomAnimationList->SelectAll( false );
1768 // gather shapes from the selection
1769 std::vector< Any >::iterator aIter( aTargets.begin() );
1770 const std::vector< Any >::iterator aEnd( aTargets.end() );
1771 bool bFirst = true;
1772 for( ; aIter != aEnd; ++aIter )
1774 CustomAnimationEffectPtr pCreated = mpMainSequence->append( pDescriptor, (*aIter), fDuration );
1776 // if only one shape with text and no fill or outline is selected, animate only by first level paragraphs
1777 if( bHasText && (aTargets.size() == 1) )
1779 Reference< XShape > xShape( (*aIter), UNO_QUERY );
1780 if( xShape.is() && !hasVisibleShape( xShape ) )
1782 mpMainSequence->createTextGroup( pCreated, 1, -1.0, false, false );
1786 if( bFirst )
1787 bFirst = false;
1788 else
1789 pCreated->setNodeType( EffectNodeType::WITH_PREVIOUS );
1791 if( pCreated.get() )
1792 mpCustomAnimationList->select( pCreated );
1795 else
1797 MainSequenceRebuildGuard aGuard( mpMainSequence );
1799 // get selected effect
1800 EffectSequence::iterator aIter( maListSelection.begin() );
1801 const EffectSequence::iterator aEnd( maListSelection.end() );
1802 while( aIter != aEnd )
1804 CustomAnimationEffectPtr pEffect = (*aIter++);
1806 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
1807 if( !pEffectSequence )
1808 pEffectSequence = mpMainSequence.get();
1810 pEffectSequence->replace( pEffect, pDescriptor, fDuration );
1814 else
1816 PathKind eKind = pDlg->getCreatePathKind();
1817 if( eKind != PathKind::NONE )
1818 createPath( eKind, aTargets, fDuration );
1820 mrBase.GetDocShell()->SetModified();
1822 } // dispose pDlg
1824 updateControls();
1826 // stop running preview from dialog
1827 SlideShow::Stop( mrBase );
1830 void CustomAnimationPane::createPath( PathKind eKind, std::vector< Any >& rTargets, double fDuration)
1832 sal_uInt16 nSID = 0;
1834 switch( eKind )
1836 case PathKind::CURVE: nSID = SID_DRAW_BEZIER_NOFILL; break;
1837 case PathKind::POLYGON: nSID = SID_DRAW_POLYGON_NOFILL; break;
1838 case PathKind::FREEFORM: nSID = SID_DRAW_FREELINE_NOFILL; break;
1839 default: break;
1842 if( nSID )
1844 DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >(
1845 FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get());
1847 if( pViewShell )
1849 DrawView* pView = pViewShell->GetDrawView();
1850 if( pView )
1851 pView->UnmarkAllObj();
1853 std::vector< Any > aTargets( 1, Any( fDuration ) );
1854 aTargets.insert( aTargets.end(), rTargets.begin(), rTargets.end() );
1855 Sequence< Any > aTargetSequence( comphelper::containerToSequence( aTargets ) );
1856 const SfxUnoAnyItem aItem( SID_ADD_MOTION_PATH, Any( aTargetSequence ) );
1857 pViewShell->GetViewFrame()->GetDispatcher()->Execute( nSID, SfxCallMode::ASYNCHRON, &aItem, 0 );
1862 void CustomAnimationPane::onRemove()
1864 if( !maListSelection.empty() )
1866 addUndo();
1868 MainSequenceRebuildGuard aGuard( mpMainSequence );
1870 EffectSequence aList( maListSelection );
1872 EffectSequence::iterator aIter( aList.begin() );
1873 const EffectSequence::iterator aEnd( aList.end() );
1874 while( aIter != aEnd )
1876 CustomAnimationEffectPtr pEffect = (*aIter++);
1877 if( pEffect->getEffectSequence() )
1878 pEffect->getEffectSequence()->remove( pEffect );
1881 maListSelection.clear();
1882 mrBase.GetDocShell()->SetModified();
1886 void CustomAnimationPane::remove( CustomAnimationEffectPtr& pEffect )
1888 if( pEffect->getEffectSequence() )
1890 addUndo();
1891 pEffect->getEffectSequence()->remove( pEffect );
1892 mrBase.GetDocShell()->SetModified();
1896 void CustomAnimationPane::onChangeStart()
1898 if( mpLBStart->GetSelectEntryCount() == 1 )
1900 sal_Int16 nNodeType;
1901 sal_uInt16 nPos= mpLBStart->GetSelectEntryPos();
1902 switch( nPos )
1904 case 0: nNodeType = EffectNodeType::ON_CLICK; break;
1905 case 1: nNodeType = EffectNodeType::WITH_PREVIOUS; break;
1906 case 2: nNodeType = EffectNodeType::AFTER_PREVIOUS; break;
1907 default:
1908 return;
1911 onChangeStart( nNodeType );
1915 void CustomAnimationPane::onChangeStart( sal_Int16 nNodeType )
1917 addUndo();
1919 MainSequenceRebuildGuard aGuard( mpMainSequence );
1921 bool bNeedRebuild = false;
1923 EffectSequence::iterator aIter( maListSelection.begin() );
1924 const EffectSequence::iterator aEnd( maListSelection.end() );
1925 while( aIter != aEnd )
1927 CustomAnimationEffectPtr pEffect = (*aIter++);
1928 if( pEffect->getNodeType() != nNodeType )
1930 pEffect->setNodeType( nNodeType );
1931 bNeedRebuild = true;
1935 if( bNeedRebuild )
1937 mpMainSequence->rebuild();
1938 updateControls();
1939 mrBase.GetDocShell()->SetModified();
1943 void CustomAnimationPane::onChangeProperty()
1945 if( mpLBProperty->getSubControl() )
1947 addUndo();
1949 MainSequenceRebuildGuard aGuard( mpMainSequence );
1951 const Any aValue( mpLBProperty->getSubControl()->getValue() );
1953 bool bNeedUpdate = false;
1955 // change selected effect
1956 EffectSequence::iterator aIter( maListSelection.begin() );
1957 const EffectSequence::iterator aEnd( maListSelection.end() );
1958 while( aIter != aEnd )
1960 CustomAnimationEffectPtr pEffect = (*aIter++);
1962 if( setProperty1Value( mnPropertyType, pEffect, aValue ) )
1963 bNeedUpdate = true;
1966 if( bNeedUpdate )
1968 mpMainSequence->rebuild();
1969 updateControls();
1970 mrBase.GetDocShell()->SetModified();
1973 onPreview( false );
1977 void CustomAnimationPane::onChangeSpeed()
1979 if( mpCBSpeed->GetSelectEntryCount() == 1 )
1981 addUndo();
1983 MainSequenceRebuildGuard aGuard( mpMainSequence );
1985 double fDuration;
1987 sal_uInt16 nPos= mpCBSpeed->GetSelectEntryPos();
1989 switch( nPos )
1991 case 0: fDuration = 5.0; break;
1992 case 1: fDuration = 3.0; break;
1993 case 2: fDuration = 2.0; break;
1994 case 3: fDuration = 1.0; break;
1995 case 4: fDuration = 0.5; break;
1996 default:
1997 return;
2000 // change selected effect
2001 EffectSequence::iterator aIter( maListSelection.begin() );
2002 const EffectSequence::iterator aEnd( maListSelection.end() );
2003 while( aIter != aEnd )
2005 CustomAnimationEffectPtr pEffect = (*aIter++);
2006 pEffect->setDuration( fDuration );
2009 mpMainSequence->rebuild();
2010 updateControls();
2011 mrBase.GetDocShell()->SetModified();
2013 onPreview( false );
2017 /// this link is called when the property box is modified by the user
2018 IMPL_LINK_NOARG(CustomAnimationPane, implPropertyHdl)
2020 onChangeProperty();
2021 return 0;
2024 /// this link is called when one of the controls is modified
2025 IMPL_LINK( CustomAnimationPane, implControlHdl, Control*, pControl )
2027 if( pControl == mpPBAddEffect )
2028 onChange(true);
2029 else if( pControl == mpPBChangeEffect )
2030 onChange(false);
2031 else if( pControl == mpPBRemoveEffect )
2032 onRemove();
2033 else if( pControl == mpLBStart )
2034 onChangeStart();
2035 else if( pControl == mpCBSpeed )
2036 onChangeSpeed();
2037 else if( pControl == mpPBPropertyMore )
2038 showOptions();
2039 else if( pControl == mpPBMoveUp )
2040 moveSelection( true );
2041 else if( pControl == mpPBMoveDown )
2042 moveSelection( false );
2043 else if( pControl == mpPBPlay )
2044 onPreview( true );
2045 else if( pControl == mpCBAutoPreview )
2047 SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
2048 pOptions->SetPreviewChangedEffects( mpCBAutoPreview->IsChecked() );
2051 updateControls();
2053 return 0;
2056 IMPL_LINK_NOARG_TYPED(CustomAnimationPane, lateInitCallback, Timer *, void)
2058 // Call getPresets() to initiate the (expensive) construction of the
2059 // presets list.
2060 getPresets();
2062 // update selection and control states
2063 onSelectionChanged();
2066 void CustomAnimationPane::moveSelection( bool bUp )
2068 if( maListSelection.empty() )
2069 return;
2071 EffectSequenceHelper* pSequence = maListSelection.front()->getEffectSequence();
2072 if( pSequence == 0 )
2073 return;
2075 addUndo();
2077 bool bChanged = false;
2079 MainSequenceRebuildGuard aGuard( mpMainSequence );
2080 EffectSequence& rEffectSequence = pSequence->getSequence();
2082 if( bUp )
2084 EffectSequence::iterator aIter( maListSelection.begin() );
2085 const EffectSequence::iterator aEnd( maListSelection.end() );
2087 while( aIter != aEnd )
2089 CustomAnimationEffectPtr pEffect = (*aIter++);
2091 EffectSequence::iterator aUpEffectPos( pSequence->find( pEffect ) );
2092 if( aUpEffectPos != rEffectSequence.end() )
2094 EffectSequence::iterator aInsertPos( rEffectSequence.erase( aUpEffectPos ) );
2096 if( aInsertPos != rEffectSequence.begin() )
2098 --aInsertPos;
2099 while( (aInsertPos != rEffectSequence.begin()) && !mpCustomAnimationList->isExpanded(*aInsertPos))
2100 --aInsertPos;
2102 rEffectSequence.insert( aInsertPos, pEffect );
2104 else
2106 rEffectSequence.push_front( pEffect );
2108 bChanged = true;
2112 else
2114 EffectSequence::reverse_iterator aIter( maListSelection.rbegin() );
2115 const EffectSequence::reverse_iterator aEnd( maListSelection.rend() );
2117 while( aIter != aEnd )
2119 CustomAnimationEffectPtr pEffect = (*aIter++);
2121 EffectSequence::iterator aDownEffectPos( pSequence->find( pEffect ) );
2122 if( aDownEffectPos != rEffectSequence.end() )
2124 EffectSequence::iterator aInsertPos( rEffectSequence.erase( aDownEffectPos ) );
2126 if( aInsertPos != rEffectSequence.end() )
2128 ++aInsertPos;
2129 while( (aInsertPos != rEffectSequence.end()) && !mpCustomAnimationList->isExpanded(*aInsertPos))
2130 ++aInsertPos;
2132 rEffectSequence.insert( aInsertPos, pEffect );
2134 else
2136 rEffectSequence.push_back( pEffect );
2138 bChanged = true;
2143 if( bChanged )
2145 mpMainSequence->rebuild();
2146 updateControls();
2147 mrBase.GetDocShell()->SetModified();
2151 void CustomAnimationPane::onPreview( bool bForcePreview )
2153 if( !bForcePreview && !mpCBAutoPreview->IsChecked() )
2154 return;
2156 if( maListSelection.empty() )
2158 rtl::Reference< MotionPathTag > xMotionPathTag;
2159 MotionPathTagVector::iterator aIter;
2160 for( aIter = maMotionPathTags.begin(); aIter != maMotionPathTags.end(); ++aIter )
2162 if( (*aIter)->isSelected() )
2164 xMotionPathTag = (*aIter);
2165 break;
2169 if( xMotionPathTag.is() )
2171 MainSequencePtr pSequence( new MainSequence() );
2172 pSequence->append( xMotionPathTag->getEffect()->clone() );
2173 preview( pSequence->getRootNode() );
2175 else
2177 Reference< XAnimationNodeSupplier > xNodeSupplier( mxCurrentPage, UNO_QUERY );
2178 if( !xNodeSupplier.is() )
2179 return;
2181 preview( xNodeSupplier->getAnimationNode() );
2184 else
2186 MainSequencePtr pSequence( new MainSequence() );
2188 EffectSequence::iterator aIter( maListSelection.begin() );
2189 const EffectSequence::iterator aEnd( maListSelection.end() );
2191 while( aIter != aEnd )
2193 CustomAnimationEffectPtr pEffect = (*aIter++);
2194 pSequence->append( pEffect->clone() );
2197 preview( pSequence->getRootNode() );
2201 void CustomAnimationPane::preview( const Reference< XAnimationNode >& xAnimationNode )
2203 Reference< XParallelTimeContainer > xRoot = ParallelTimeContainer::create( ::comphelper::getProcessComponentContext() );
2204 Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 );
2205 aUserData[0].Name = "node-type";
2206 aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT;
2207 xRoot->setUserData( aUserData );
2208 xRoot->appendChild( xAnimationNode );
2210 SlideShow::StartPreview( mrBase, mxCurrentPage, xRoot );
2213 // ICustomAnimationListController
2214 void CustomAnimationPane::onSelect()
2216 maListSelection = mpCustomAnimationList->getSelection();
2217 updateControls();
2218 markShapesFromSelectedEffects();
2221 const CustomAnimationPresets& CustomAnimationPane::getPresets()
2223 if (mpCustomAnimationPresets == NULL)
2224 mpCustomAnimationPresets = &CustomAnimationPresets::getCustomAnimationPresets();
2225 return *mpCustomAnimationPresets;
2228 void CustomAnimationPane::markShapesFromSelectedEffects()
2230 if( !maSelectionLock.isLocked() )
2232 ScopeLockGuard aGuard( maSelectionLock );
2233 DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >(
2234 FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get());
2235 DrawView* pView = pViewShell ? pViewShell->GetDrawView() : NULL;
2237 if( pView )
2239 pView->UnmarkAllObj();
2240 EffectSequence::iterator aIter( maListSelection.begin() );
2241 const EffectSequence::iterator aEnd( maListSelection.end() );
2242 while( aIter != aEnd )
2244 CustomAnimationEffectPtr pEffect = (*aIter++);
2246 Reference< XShape > xShape( pEffect->getTargetShape() );
2247 SdrObject* pObj = GetSdrObjectFromXShape( xShape );
2248 if( pObj )
2249 pView->MarkObj(pObj, pView->GetSdrPageView(), false, false);
2255 void CustomAnimationPane::updatePathFromMotionPathTag( const rtl::Reference< MotionPathTag >& xTag )
2257 MainSequenceRebuildGuard aGuard( mpMainSequence );
2258 if( xTag.is() )
2260 SdrPathObj* pPathObj = xTag->getPathObj();
2261 CustomAnimationEffectPtr pEffect = xTag->getEffect();
2262 if( (pPathObj != 0) && pEffect.get() != 0 )
2264 ::svl::IUndoManager* pManager = mrBase.GetDocShell()->GetUndoManager();
2265 if( pManager )
2267 SdPage* pPage = SdPage::getImplementation( mxCurrentPage );
2268 if( pPage )
2269 pManager->AddUndoAction( new UndoAnimationPath( mrBase.GetDocShell()->GetDoc(), pPage, pEffect->getNode() ) );
2272 pEffect->updatePathFromSdrPathObj( *pPathObj );
2277 vcl::Window * createCustomAnimationPanel( vcl::Window* pParent, ViewShellBase& rBase, const css::uno::Reference<css::frame::XFrame>& rxFrame )
2279 vcl::Window* pWindow = 0;
2281 DrawDocShell* pDocSh = rBase.GetDocShell();
2282 if( pDocSh )
2284 const Size aMinSize( pParent->LogicToPixel( Size( 80, 256 ), MAP_APPFONT ) );
2285 pWindow = VclPtr<CustomAnimationPane>::Create( pParent, rBase, rxFrame, aMinSize );
2288 return pWindow;
2293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */