LibreOffice Module sd (master) 1
CustomAnimationPane.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <com/sun/star/presentation/EffectPresetClass.hpp>
21#include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
22#include <com/sun/star/animations/AnimationNodeType.hpp>
23#include <com/sun/star/animations/ParallelTimeContainer.hpp>
24#include <com/sun/star/view/XSelectionSupplier.hpp>
25#include <com/sun/star/document/XActionLockable.hpp>
26#include <com/sun/star/drawing/XDrawView.hpp>
27#include <com/sun/star/drawing/XShape.hpp>
28#include <com/sun/star/beans/XPropertySet.hpp>
29#include <com/sun/star/presentation/EffectNodeType.hpp>
30#include <com/sun/star/presentation/EffectCommands.hpp>
31#include <com/sun/star/animations/AnimationTransformType.hpp>
32#include <com/sun/star/text/XTextRangeCompare.hpp>
33#include <com/sun/star/container/XEnumerationAccess.hpp>
34#include <com/sun/star/container/XIndexAccess.hpp>
35#include <com/sun/star/presentation/ParagraphTarget.hpp>
36#include <com/sun/star/text/XText.hpp>
37#include <com/sun/star/drawing/LineStyle.hpp>
38#include <com/sun/star/drawing/FillStyle.hpp>
41#include <sfx2/dispatch.hxx>
42#include <sfx2/viewfrm.hxx>
43#include <tools/debug.hxx>
44#include "STLPropertySet.hxx"
48#include "motionpathtag.hxx"
50
51#include <comphelper/lok.hxx>
53#include <sfx2/frame.hxx>
55
56#include <svx/svxids.hrc>
57#include <DrawDocShell.hxx>
58#include <ViewShellBase.hxx>
59#include <DrawViewShell.hxx>
60#include <DrawController.hxx>
61#include <sdresid.hxx>
62#include <drawview.hxx>
63#include <slideshow.hxx>
64#include <undoanim.hxx>
65#include <optsitem.hxx>
66#include <sdmod.hxx>
68
69#include <EventMultiplexer.hxx>
70
71#include <strings.hrc>
72#include <sdpage.hxx>
73#include <app.hrc>
74
75#include <svx/strings.hrc>
76#include <svx/dialmgr.hxx>
77
78#include <algorithm>
79#include <memory>
80
81using namespace ::com::sun::star;
82using namespace ::com::sun::star::animations;
83using namespace ::com::sun::star::presentation;
84using namespace ::com::sun::star::text;
85
86using namespace ::com::sun::star::uno;
87using namespace ::com::sun::star::drawing;
88using ::com::sun::star::view::XSelectionSupplier;
89using ::com::sun::star::beans::XPropertySet;
90using ::com::sun::star::container::XIndexAccess;
91using ::com::sun::star::container::XEnumerationAccess;
92using ::com::sun::star::container::XEnumeration;
93using ::com::sun::star::text::XText;
94using ::sd::framework::FrameworkHelper;
95using ::com::sun::star::uno::UNO_QUERY;
96using ::com::sun::star::uno::UNO_QUERY_THROW;
97using ::com::sun::star::uno::Any;
98using ::com::sun::star::uno::Reference;
99using ::com::sun::star::uno::Exception;
100
101namespace sd {
102
104{
105 OUString aNone( SdResId( STR_CUSTOMANIMATION_REPEAT_NONE ) );
106 rBox.append_text(aNone);
107 rBox.append_text(OUString::number(2));
108 rBox.append_text(OUString::number(3));
109 rBox.append_text(OUString::number(4));
110 rBox.append_text(OUString::number(5));
111 rBox.append_text(OUString::number(10));
112
113 OUString aUntilClick( SdResId( STR_CUSTOMANIMATION_REPEAT_UNTIL_NEXT_CLICK ) );
114 rBox.append_text(aUntilClick);
115
116 OUString aEndOfSlide( SdResId( STR_CUSTOMANIMATION_REPEAT_UNTIL_END_OF_SLIDE ) );
117 rBox.append_text(aEndOfSlide);
118}
119
121 : PanelLayout(pParent, "CustomAnimationsPanel", "modules/simpress/ui/customanimationspanel.ui")
122 , mrBase(rBase)
123 // load resources
124 , mxFTAnimation(m_xBuilder->weld_label("effectlabel"))
125 , mxCustomAnimationList(new CustomAnimationList(m_xBuilder->weld_tree_view("custom_animation_list"),
126 m_xBuilder->weld_label("custom_animation_label"),
127 m_xBuilder->weld_widget("custom_animation_label_parent")))
128 , mxPBAddEffect(m_xBuilder->weld_button("add_effect"))
129 , mxPBRemoveEffect(m_xBuilder->weld_button("remove_effect"))
130 , mxPBMoveUp(m_xBuilder->weld_button("move_up"))
131 , mxPBMoveDown(m_xBuilder->weld_button("move_down"))
132 , mxFTCategory(m_xBuilder->weld_label("categorylabel"))
133 , mxLBCategory(m_xBuilder->weld_combo_box("categorylb"))
134 , mxFTEffect(m_xBuilder->weld_label("effect_label"))
135 , mxLBAnimation(m_xBuilder->weld_tree_view("effect_list"))
136 , mxFTStart(m_xBuilder->weld_label("start_effect"))
137 , mxLBStart(m_xBuilder->weld_combo_box("start_effect_list"))
138 , mxFTProperty(m_xBuilder->weld_label("effect_property"))
139 , mxPlaceholderBox(m_xBuilder->weld_container("placeholder"))
140 , mxPBPropertyMore(m_xBuilder->weld_button("more_properties"))
141 , mxFTDuration(m_xBuilder->weld_label("effect_duration"))
142 , mxCBXDuration(m_xBuilder->weld_metric_spin_button("anim_duration", FieldUnit::SECOND))
143 , mxFTStartDelay(m_xBuilder->weld_label("delay_label"))
144 , mxMFStartDelay(m_xBuilder->weld_metric_spin_button("delay_value", FieldUnit::SECOND))
145 , mxCBAutoPreview(m_xBuilder->weld_check_button("auto_preview"))
146 , mxPBPlay(m_xBuilder->weld_button("play"))
147 , maIdle("sd idle treeview select")
148 , mnLastSelectedAnimation(-1)
149 , mnPropertyType(nPropertyTypeNone)
150 , mnCurvePathPos(-1)
151 , mnPolygonPathPos(-1)
152 , mnFreeformPathPos(-1)
153 , maLateInitTimer("sd CustomAnimationPane maLateInitTimer")
154{
155 initialize();
156}
157
158css::ui::LayoutSize CustomAnimationPane::GetHeightForWidth(const sal_Int32 /*nWidth*/)
159{
160 sal_Int32 nMinimumHeight = get_preferred_size().Height();
161 return css::ui::LayoutSize(nMinimumHeight, -1, nMinimumHeight);
162}
163
165{
166 mxLBAnimation->connect_changed(LINK(this, CustomAnimationPane, AnimationSelectHdl));
167 mxCustomAnimationList->setController( static_cast<ICustomAnimationListController*> ( this ) );
168 mxCustomAnimationList->set_size_request(mxCustomAnimationList->get_approximate_digit_width() * 15,
169 mxCustomAnimationList->get_height_rows(4));
170
171 mxLBAnimation->set_size_request(mxLBAnimation->get_approximate_digit_width() * 15,
172 mxLBAnimation->get_height_rows(4));
173
174 maStrProperty = mxFTProperty->get_label();
175
176 mxPBAddEffect->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
177 mxPBRemoveEffect->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
178 mxLBStart->connect_changed( LINK( this, CustomAnimationPane, implControlListBoxHdl ) );
179 mxCBXDuration->connect_value_changed(LINK( this, CustomAnimationPane, DurationModifiedHdl));
180 mxPBPropertyMore->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
181 mxPBMoveUp->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
182 mxPBMoveDown->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
183 mxPBPlay->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
184 mxCBAutoPreview->connect_toggled( LINK( this, CustomAnimationPane, implToggleHdl ) );
185 mxLBCategory->connect_changed( LINK(this, CustomAnimationPane, UpdateAnimationLB) );
186 mxMFStartDelay->connect_value_changed( LINK(this, CustomAnimationPane, DelayModifiedHdl) );
187 mxMFStartDelay->connect_focus_out(LINK( this, CustomAnimationPane, DelayLoseFocusHdl));
188
189 maIdle.SetPriority(TaskPriority::DEFAULT);
190 maIdle.SetInvokeHandler(LINK(this, CustomAnimationPane, SelectionHandler));
191
192 maStrModify = mxFTEffect->get_label();
193
194 // get current controller and initialize listeners
195 try
196 {
197 mxView.set(mrBase.GetController(), UNO_QUERY);
198 addListener();
199 }
200 catch( Exception& )
201 {
202 TOOLS_WARN_EXCEPTION( "sd", "sd::CustomAnimationPane::CustomAnimationPane()" );
203 }
204
205 // tdf#137637 keep user selection during initialization
207 // get current page and update custom animation list
209
210 // Wait a short time before the presets list is created. This gives the
211 // system time to paint the control.
215}
216
218{
220
222
224 aTags.swap( maMotionPathTags );
225 for (auto const& tag : aTags)
226 tag->Dispose();
227
228 mxPBAddEffect.reset();
229 mxPBRemoveEffect.reset();
230 mxFTEffect.reset();
231 mxFTStart.reset();
232 mxLBStart.reset();
233 mxLBSubControl.reset();
234 mxFTProperty.reset();
235 mxPlaceholderBox.reset();
236 mxPBPropertyMore.reset();
237 mxFTDuration.reset();
238 mxCBXDuration.reset();
239 mxFTStartDelay.reset();
240 mxMFStartDelay.reset();
241 mxCustomAnimationList.reset();
242 mxPBMoveUp.reset();
243 mxPBMoveDown.reset();
244 mxPBPlay.reset();
245 mxCBAutoPreview.reset();
246 mxFTCategory.reset();
247 mxLBCategory.reset();
248 mxFTAnimation.reset();
249 mxLBAnimation.reset();
250}
251
253{
255 if( pManager )
256 {
258 if( pPage )
259 pManager->AddUndoAction( std::make_unique<UndoAnimation>( mrBase.GetDocShell()->GetDoc(), pPage ) );
260 }
261}
262
264{
265 Link<tools::EventMultiplexerEvent&,void> aLink( LINK(this,CustomAnimationPane,EventMultiplexerListener) );
266 mrBase.GetEventMultiplexer()->AddEventListener(aLink);
267}
268
270{
271 Link<tools::EventMultiplexerEvent&,void> aLink( LINK(this,CustomAnimationPane,EventMultiplexerListener) );
272 mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
273}
274
275IMPL_LINK(CustomAnimationPane,EventMultiplexerListener,
276 tools::EventMultiplexerEvent&, rEvent, void)
277{
278 switch (rEvent.meEventId)
279 {
281 onSelectionChanged();
282 break;
283
285 onChangeCurrentPage();
286 break;
287
289 // At this moment the controller may not yet been set at model
290 // or ViewShellBase. Take it from the view shell passed with
291 // the event.
292 if (mrBase.GetMainViewShell() != nullptr)
293 {
294 if( mrBase.GetMainViewShell()->GetShellType() == ViewShell::ST_IMPRESS )
295 {
296 mxView = mrBase.GetDrawController();
297 onSelectionChanged();
298 onChangeCurrentPage();
299 break;
300 }
301 }
302 [[fallthrough]];
304 mxView = nullptr;
305 mxCurrentPage = nullptr;
306 updateControls();
307 break;
308
310 mxView.clear();
311 onSelectionChanged();
312 onChangeCurrentPage();
313 break;
315 if (mpMainSequence && rEvent.mpUserData)
316 mxCustomAnimationList->update( mpMainSequence );
317 break;
318 default: break;
319 }
320}
321
322static sal_Int32 getPropertyType( std::u16string_view rProperty )
323{
324 if ( rProperty == u"Direction" )
326
327 if ( rProperty == u"Spokes" )
328 return nPropertyTypeSpokes;
329
330 if ( rProperty == u"Zoom" )
331 return nPropertyTypeZoom;
332
333 if ( rProperty == u"Accelerate" )
335
336 if ( rProperty == u"Decelerate" )
338
339 if ( rProperty == u"Color1" )
341
342 if ( rProperty == u"Color2" )
344
345 if ( rProperty == u"FillColor" )
347
348 if ( rProperty == u"ColorStyle" )
350
351 if ( rProperty == u"AutoReverse" )
353
354 if ( rProperty == u"FontStyle" )
355 return nPropertyTypeFont;
356
357 if ( rProperty == u"CharColor" )
359
360 if ( rProperty == u"CharHeight" )
362
363 if ( rProperty == u"CharDecoration" )
365
366 if ( rProperty == u"LineColor" )
368
369 if ( rProperty == u"Rotate" )
370 return nPropertyTypeRotate;
371
372 if ( rProperty == u"Transparency" )
374
375 if ( rProperty == u"Color" )
376 return nPropertyTypeColor;
377
378 if ( rProperty == u"Scale" )
379 return nPropertyTypeScale;
380
381 return nPropertyTypeNone;
382}
383
384OUString getPropertyName( sal_Int32 nPropertyType )
385{
386 switch( nPropertyType )
387 {
389 return SdResId(STR_CUSTOMANIMATION_DIRECTION_PROPERTY);
390
392 return SdResId(STR_CUSTOMANIMATION_SPOKES_PROPERTY);
393
395 return SdResId(STR_CUSTOMANIMATION_FIRST_COLOR_PROPERTY);
396
398 return SdResId(STR_CUSTOMANIMATION_SECOND_COLOR_PROPERTY);
399
401 return SdResId(STR_CUSTOMANIMATION_ZOOM_PROPERTY);
402
404 return SdResId(STR_CUSTOMANIMATION_FILL_COLOR_PROPERTY);
405
407 return SdResId(STR_CUSTOMANIMATION_STYLE_PROPERTY);
408
410 return SdResId(STR_CUSTOMANIMATION_FONT_PROPERTY);
411
413 return SdResId(STR_CUSTOMANIMATION_SIZE_PROPERTY);
414
416 return SdResId(STR_CUSTOMANIMATION_FONT_COLOR_PROPERTY);
417
419 return SdResId(STR_CUSTOMANIMATION_FONT_SIZE_STYLE_PROPERTY);
420
422 return SdResId(STR_CUSTOMANIMATION_FONT_STYLE_PROPERTY);
423
425 return SdResId(STR_CUSTOMANIMATION_LINE_COLOR_PROPERTY);
426
428 return SdResId(STR_CUSTOMANIMATION_AMOUNT_PROPERTY);
429
431 return SdResId(STR_CUSTOMANIMATION_COLOR_PROPERTY);
432
434 return SdResId(STR_CUSTOMANIMATION_AMOUNT_PROPERTY);
435
437 return SdResId(STR_CUSTOMANIMATION_SCALE_PROPERTY);
438 }
439
440 return OUString();
441}
442
444{
445 mxFTDuration->set_sensitive(mxView.is());
446 mxCBXDuration->set_sensitive(mxView.is());
447 mxCustomAnimationList->set_sensitive(mxView.is());
449 {
450 mxPBPlay->hide();
451 mxCBAutoPreview->set_active(false);
452 mxCBAutoPreview->hide();
453 }
454 else
455 {
456 mxPBPlay->set_sensitive(mxView.is());
457 mxCBAutoPreview->set_sensitive(mxView.is());
458 }
459
460 if (!mxView.is())
461 {
462 mxPBAddEffect->set_sensitive(false);
463 mxPBRemoveEffect->set_sensitive(false);
464 mxFTStart->set_sensitive(false);
465 mxLBStart->set_sensitive(false);
466 mxPBPropertyMore->set_sensitive(false);
467 mxPlaceholderBox->set_sensitive(false);
468 mxFTProperty->set_sensitive(false);
469 mxFTCategory->set_sensitive(false);
470 mxLBCategory->set_sensitive(false);
471 mxFTAnimation->set_sensitive(false);
472 mxLBAnimation->set_sensitive(false);
473 mxFTStartDelay->set_sensitive(false);
474 mxMFStartDelay->set_sensitive(false);
475 mxLBAnimation->clear();
477 mxCustomAnimationList->clear();
478 return;
479 }
480
481 const int nSelectionCount = maListSelection.size();
482
483 mxPBAddEffect->set_sensitive( maViewSelection.hasValue() );
484 mxPBRemoveEffect->set_sensitive(nSelectionCount != 0);
485 bool bIsSelected = (nSelectionCount > 0);
486
487 if(bIsSelected)
488 {
489 mxFTAnimation->set_sensitive(true);
490 mxLBAnimation->set_sensitive(true);
491 }
492 else
493 {
494 mxFTAnimation->set_sensitive(false);
495 mxLBAnimation->set_sensitive(false);
496 mxLBAnimation->clear();
498 }
499
500 mxLBCategory->set_sensitive(bIsSelected);
501 mxFTCategory->set_sensitive(bIsSelected);
502
503 mxFTStart->set_sensitive(nSelectionCount > 0);
504 mxLBStart->set_sensitive(nSelectionCount > 0);
505 mxPlaceholderBox->set_sensitive(nSelectionCount > 0);
506 mxPBPropertyMore->set_sensitive(nSelectionCount > 0);
507 mxFTStartDelay->set_sensitive(nSelectionCount > 0);
508 mxMFStartDelay->set_sensitive(nSelectionCount > 0);
509
510 mxFTProperty->set_label(maStrProperty);
511
512 sal_Int32 nOldPropertyType = mnPropertyType;
513
515
516 if(bIsSelected)
517 {
519
520 OUString aUIName( CustomAnimationPresets::getCustomAnimationPresets().getUINameForPresetId( pEffect->getPresetId() ) );
521
522 OUString aTemp( maStrModify );
523
524 if( !aUIName.isEmpty() )
525 {
526 aTemp += " " + aUIName;
527 mxFTEffect->set_label( aTemp );
528 }
529
530 Any aValue;
532 if (pDescriptor)
533 {
534 std::vector<OUString> aProperties( pDescriptor->getProperties() );
535 if( !aProperties.empty() )
536 {
538
540
541 aValue = getProperty1Value( mnPropertyType, pEffect );
542 }
543 }
544
545 sal_Int32 nNewPropertyType = mnPropertyType;
546 // if there is no value, then the control will be disabled, just show a disabled Direction box in that
547 // case to have something to fill the space
548 if (!aValue.hasValue())
549 nNewPropertyType = nPropertyTypeDirection;
550
551 if (!mxLBSubControl || nOldPropertyType != nNewPropertyType)
552 {
553 // for LOK destroy old widgets first
554 mxLBSubControl.reset(nullptr);
555 // then create new control, to keep correct pointers for actions
556 mxLBSubControl = SdPropertySubControl::create(nNewPropertyType, mxFTProperty.get(), mxPlaceholderBox.get(), GetFrameWeld(), aValue, pEffect->getPresetId(), LINK(this, CustomAnimationPane, implPropertyHdl));
557 }
558 else
559 {
560 mxLBSubControl->setValue(aValue, pEffect->getPresetId());
561 }
562
563 bool bEnable = aValue.hasValue();
564 mxPlaceholderBox->set_sensitive( bEnable );
565 mxFTProperty->set_sensitive( bEnable );
566
567 if (!pDescriptor)
568 {
569 mxPBPropertyMore->set_sensitive( false );
570 mxFTStartDelay->set_sensitive( false );
571 mxMFStartDelay->set_sensitive( false );
572 }
573 sal_Int32 nCategoryPos = -1;
574 switch(pEffect->getPresetClass())
575 {
576 case EffectPresetClass::ENTRANCE: nCategoryPos = 0; break;
577 case EffectPresetClass::EMPHASIS: nCategoryPos = 1; break;
578 case EffectPresetClass::EXIT: nCategoryPos = 2; break;
579 case EffectPresetClass::MOTIONPATH: nCategoryPos = 3; break;
580 default:
581 break;
582 }
583 switch(pEffect->getCommand())
584 {
585 case EffectCommands::TOGGLEPAUSE:
586 case EffectCommands::STOP:
587 case EffectCommands::PLAY:
588 nCategoryPos = 4; break;
589 default:
590 break;
591 }
592 mxLBCategory->set_active(nCategoryPos);
593
594 fillAnimationLB( pEffect->hasText() );
595
596 OUString rsPresetId = pEffect->getPresetId();
597 sal_Int32 nAnimationPos = mxLBAnimation->n_children();
598 while( nAnimationPos-- )
599 {
600 auto pEntryData = weld::fromId<CustomAnimationPresetPtr*>(mxLBAnimation->get_id(nAnimationPos));
601 if (pEntryData)
602 {
603 CustomAnimationPresetPtr& pPtr = *pEntryData;
604 if( pPtr && pPtr->getPresetId() == rsPresetId )
605 {
606 mxLBAnimation->select( nAnimationPos );
607 mnLastSelectedAnimation = nAnimationPos;
608 break;
609 }
610 }
611 }
612
613 // If preset id is missing and category is motion path.
614 if (nAnimationPos < 0 && nCategoryPos == 3)
615 {
616 if (rsPresetId == "libo-motionpath-curve")
617 {
620 }
621 else if (rsPresetId == "libo-motionpath-polygon")
622 {
625 }
626 else if (rsPresetId == "libo-motionpath-freeform-line")
627 {
630 }
631 }
632
633 sal_uInt16 nPos = 0xffff;
634
635 sal_Int16 nNodeType = pEffect->getNodeType();
636 switch( nNodeType )
637 {
638 case EffectNodeType::ON_CLICK: nPos = 0; break;
639 case EffectNodeType::WITH_PREVIOUS: nPos = 1; break;
640 case EffectNodeType::AFTER_PREVIOUS: nPos = 2; break;
641 }
642
643 mxLBStart->set_active( nPos );
644
645 double fDuration = pEffect->getDuration();
646 const bool bHasSpeed = fDuration > 0.001;
647
648 mxFTDuration->set_sensitive(bHasSpeed);
649 mxCBXDuration->set_sensitive(bHasSpeed);
650
651 if( bHasSpeed )
652 {
653 mxCBXDuration->set_value(fDuration*100.0, FieldUnit::NONE);
654 }
655
656 mxPBPropertyMore->set_sensitive(true);
657
658 mxFTStartDelay->set_sensitive(true);
659 mxMFStartDelay->set_sensitive(true);
660 double fBegin = pEffect->getBegin();
661 mxMFStartDelay->set_value(fBegin*10.0, FieldUnit::NONE);
662 }
663 else
664 {
665 // use an empty direction box to fill the space
666 if (!mxLBSubControl || (nOldPropertyType != nPropertyTypeDirection && nOldPropertyType != nPropertyTypeNone))
667 {
668 // for LOK destroy old widgets first
669 mxLBSubControl.reset(nullptr);
670 // then create new control, to keep correct pointers for actions
672 }
673 else
674 mxLBSubControl->setValue(uno::Any(), OUString());
675
676 mxPlaceholderBox->set_sensitive(false);
677 mxFTProperty->set_sensitive(false);
678 mxFTStartDelay->set_sensitive(false);
679 mxMFStartDelay->set_sensitive(false);
680 mxPBPropertyMore->set_sensitive(false);
681 mxFTDuration->set_sensitive(false);
682 mxCBXDuration->set_sensitive(false);
683 mxCBXDuration->set_text(OUString());
684 mxFTEffect->set_label(maStrModify);
685 }
686
687 bool bEnableUp = true;
688 bool bEnableDown = true;
689 if( nSelectionCount == 0 )
690 {
691 bEnableUp = false;
692 bEnableDown = false;
693 }
694 else
695 {
696 if( mpMainSequence->find( maListSelection.front() ) == mpMainSequence->getBegin() )
697 bEnableUp = false;
698
699 EffectSequence::iterator aIter( mpMainSequence->find( maListSelection.back() ) );
700 if( aIter == mpMainSequence->getEnd() )
701 {
702 bEnableDown = false;
703 }
704 else
705 {
706 do
707 {
708 ++aIter;
709 }
710 while( (aIter != mpMainSequence->getEnd()) && !(mxCustomAnimationList->isExpanded(*aIter) ) );
711
712 if( aIter == mpMainSequence->getEnd() )
713 bEnableDown = false;
714 }
715
716 if( bEnableUp || bEnableDown )
717 {
719
720 EffectSequenceHelper* pSequence = nullptr;
721 for( const CustomAnimationEffectPtr& pEffect : maListSelection )
722 {
723 if( pEffect )
724 {
725 if( pSequence == nullptr )
726 {
727 pSequence = pEffect->getEffectSequence();
728 }
729 else
730 {
731 if( pSequence != pEffect->getEffectSequence() )
732 {
733 bEnableUp = false;
734 bEnableDown = false;
735 break;
736 }
737 }
738 }
739 }
740 }
741 }
742
743 mxPBMoveUp->set_sensitive(mxView.is() && bEnableUp);
744 mxPBMoveDown->set_sensitive(mxView.is() && bEnableDown);
745
746 SdOptions* pOptions = SD_MOD()->GetSdOptions(DocumentType::Impress);
747 mxCBAutoPreview->set_active(pOptions->IsPreviewChangedEffects());
748
750}
751
752static bool updateMotionPathImpl( CustomAnimationPane& rPane, ::sd::View& rView, EffectSequence::iterator aIter, const EffectSequence::iterator& aEnd, MotionPathTagVector& rOldTags, MotionPathTagVector& rNewTags )
753{
754 bool bChanges = false;
755 while( aIter != aEnd )
756 {
757 CustomAnimationEffectPtr pEffect( *aIter++ );
758 if( pEffect && pEffect->getPresetClass() == css::presentation::EffectPresetClass::MOTIONPATH )
759 {
760 rtl::Reference< MotionPathTag > xMotionPathTag;
761 // first try to find if there is already a tag for this
762 auto aMIter = std::find_if(rOldTags.begin(), rOldTags.end(),
763 [&pEffect](const rtl::Reference<MotionPathTag>& xTag) { return xTag->getEffect() == pEffect; });
764 if (aMIter != rOldTags.end())
765 {
766 rtl::Reference< MotionPathTag > xTag( *aMIter );
767 if( !xTag->isDisposed() )
768 {
769 xMotionPathTag = xTag;
770 rOldTags.erase( aMIter );
771 }
772 }
773
774 // if not found, create new one
775 if( !xMotionPathTag.is() )
776 {
777 xMotionPathTag.set( new MotionPathTag( rPane, rView, pEffect ) );
778 bChanges = true;
779 }
780
781 if( xMotionPathTag.is() )
782 rNewTags.push_back( xMotionPathTag );
783 }
784 }
785
786 return bChanges;
787}
788
790{
791 bool bChanges = false;
792
794 aTags.swap( maMotionPathTags );
795
796 ::sd::View* pView = nullptr;
797
798 if( mxView.is() )
799 {
800 std::shared_ptr<ViewShell> xViewShell( mrBase.GetMainViewShell() );
801 if( xViewShell )
802 pView = xViewShell->GetView();
803 }
804
805 if (mpMainSequence && pView)
806 {
807 bChanges = updateMotionPathImpl( *this, *pView, mpMainSequence->getBegin(), mpMainSequence->getEnd(), aTags, maMotionPathTags );
808
809 auto rInteractiveSequenceVector = mpMainSequence->getInteractiveSequenceVector();
810 for (InteractiveSequencePtr const& pIS : rInteractiveSequenceVector)
811 {
812 bChanges |= updateMotionPathImpl( *this, *pView, pIS->getBegin(), pIS->getEnd(), aTags, maMotionPathTags );
813 }
814 }
815
816 if( !aTags.empty() )
817 {
818 bChanges = true;
819 for( rtl::Reference< MotionPathTag >& xTag : aTags )
820 {
821 xTag->Dispose();
822 }
823 }
824
825 if( bChanges && pView )
826 pView->updateHandles();
827}
828
830{
832 return;
833
835
836 if( mxView.is() ) try
837 {
838 Reference< XSelectionSupplier > xSel( mxView, UNO_QUERY_THROW );
839 maViewSelection = xSel->getSelection();
840 mxCustomAnimationList->onSelectionChanged( maViewSelection );
842 }
843 catch( Exception& )
844 {
845 TOOLS_WARN_EXCEPTION( "sd", "sd::CustomAnimationPane::onSelectionChanged()" );
846 }
847}
848
850{
851 showOptions();
852}
853
854void CustomAnimationPane::onContextMenu(const OUString &rIdent)
855{
856 if (rIdent == "onclick")
857 onChangeStart( EffectNodeType::ON_CLICK );
858 else if (rIdent == "withprev")
859 onChangeStart( EffectNodeType::WITH_PREVIOUS );
860 else if (rIdent == "afterprev")
861 onChangeStart( EffectNodeType::AFTER_PREVIOUS );
862 else if (rIdent == "options")
863 showOptions();
864 else if (rIdent == "timing")
865 showOptions("timing");
866 else if (rIdent == "remove")
867 onRemove();
868 else if (rIdent == "create" && maViewSelection.hasValue())
869 onAdd();
871}
872
873static void addValue( const std::unique_ptr<STLPropertySet>& pSet, sal_Int32 nHandle, const Any& rValue )
874{
875 switch( pSet->getPropertyState( nHandle ) )
876 {
878 // value is already ambiguous, do nothing
879 break;
881 // set to ambiguous if existing value is different
882 if( rValue != pSet->getPropertyValue( nHandle ) )
883 pSet->setPropertyState( nHandle, STLPropertyState::Ambiguous );
884 break;
886 // just set new value
887 pSet->setPropertyValue( nHandle, rValue );
888 break;
889 }
890}
891
892static sal_Int32 calcMaxParaDepth( const Reference< XShape >& xTargetShape )
893{
894 sal_Int32 nMaxParaDepth = -1;
895
896 if( xTargetShape.is() )
897 {
898 Reference< XEnumerationAccess > xText( xTargetShape, UNO_QUERY );
899 if( xText.is() )
900 {
901 Reference< XPropertySet > xParaSet;
902
903 Reference< XEnumeration > xEnumeration( xText->createEnumeration(), UNO_SET_THROW );
904 while( xEnumeration->hasMoreElements() )
905 {
906 xEnumeration->nextElement() >>= xParaSet;
907 if( xParaSet.is() )
908 {
909 sal_Int32 nParaDepth = 0;
910 xParaSet->getPropertyValue( "NumberingLevel" ) >>= nParaDepth;
911
912 if( nParaDepth > nMaxParaDepth )
913 nMaxParaDepth = nParaDepth;
914 }
915 }
916 }
917 }
918
919 return nMaxParaDepth + 1;
920}
921
923{
924 switch( nType )
925 {
929 return Any( pEffect->getPresetSubType() );
930
937 {
938 const sal_Int32 nIndex = (nPropertyTypeFirstColor == nType) ? 0 : 1;
939 return pEffect->getColor( nIndex );
940 }
941
943 return pEffect->getProperty( AnimationNodeType::SET, u"CharFontName" , EValue::To );
944
946 {
947 static constexpr OUStringLiteral aAttributeName( u"CharHeight" );
948 Any aValue( pEffect->getProperty( AnimationNodeType::SET, aAttributeName, EValue::To ) );
949 if( !aValue.hasValue() )
950 aValue = pEffect->getProperty( AnimationNodeType::ANIMATE, aAttributeName, EValue::To );
951 return aValue;
952 }
953
955 return pEffect->getTransformationProperty( AnimationTransformType::ROTATE, EValue::By);
956
958 return pEffect->getProperty( AnimationNodeType::SET, u"Opacity" , EValue::To );
959
961 return pEffect->getTransformationProperty( AnimationTransformType::SCALE, EValue::By );
962
964 {
965 Sequence< Any > aValues{
966 pEffect->getProperty( AnimationNodeType::SET, u"CharWeight" , EValue::To ),
967 pEffect->getProperty( AnimationNodeType::SET, u"CharPosture" , EValue::To ),
968 pEffect->getProperty( AnimationNodeType::SET, u"CharUnderline" , EValue::To )
969 };
970 return Any( aValues );
971 }
972 }
973
974 Any aAny;
975 return aAny;
976}
977
978bool CustomAnimationPane::setProperty1Value( sal_Int32 nType, const CustomAnimationEffectPtr& pEffect, const Any& rValue )
979{
980 bool bEffectChanged = false;
981 switch( nType )
982 {
986 {
987 OUString aPresetSubType;
988 rValue >>= aPresetSubType;
989 if( aPresetSubType != pEffect->getPresetSubType() )
990 {
992 bEffectChanged = true;
993 }
994 }
995 break;
996
1003 {
1004 const sal_Int32 nIndex = (nPropertyTypeFirstColor == nType) ? 0 : 1;
1005 Any aOldColor( pEffect->getColor( nIndex ) );
1006 if( aOldColor != rValue )
1007 {
1008 pEffect->setColor( nIndex, rValue );
1009 bEffectChanged = true;
1010 }
1011 }
1012 break;
1013
1014 case nPropertyTypeFont:
1015 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, u"CharFontName" , EValue::To, rValue );
1016 break;
1017
1019 {
1020 static constexpr OUStringLiteral aAttributeName( u"CharHeight" );
1021 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, aAttributeName, EValue::To, rValue );
1022 if( !bEffectChanged )
1023 bEffectChanged = pEffect->setProperty( AnimationNodeType::ANIMATE, aAttributeName, EValue::To, rValue );
1024 }
1025 break;
1027 bEffectChanged = pEffect->setTransformationProperty( AnimationTransformType::ROTATE, EValue::By , rValue );
1028 break;
1029
1031 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, u"Opacity" , EValue::To, rValue );
1032 break;
1033
1034 case nPropertyTypeScale:
1035 bEffectChanged = pEffect->setTransformationProperty( AnimationTransformType::SCALE, EValue::By, rValue );
1036 break;
1037
1039 {
1040 Sequence< Any > aValues(3);
1041 rValue >>= aValues;
1042 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, u"CharWeight" , EValue::To, aValues[0] );
1043 bEffectChanged |= pEffect->setProperty( AnimationNodeType::SET, u"CharPosture" , EValue::To, aValues[1] );
1044 bEffectChanged |= pEffect->setProperty( AnimationNodeType::SET, u"CharUnderline" , EValue::To, aValues[2] );
1045 }
1046 break;
1047
1048 }
1049
1050 return bEffectChanged;
1051}
1052
1053static bool hasVisibleShape( const Reference< XShape >& xShape )
1054{
1055 try
1056 {
1057 const OUString sShapeType( xShape->getShapeType() );
1058
1059 if( sShapeType == "com.sun.star.presentation.TitleTextShape" || sShapeType == "com.sun.star.presentation.OutlinerShape" ||
1060 sShapeType == "com.sun.star.presentation.SubtitleShape" || sShapeType == "com.sun.star.drawing.TextShape" )
1061 {
1062 Reference< XPropertySet > xSet( xShape, UNO_QUERY_THROW );
1063
1064 FillStyle eFillStyle;
1065 xSet->getPropertyValue( "FillStyle" ) >>= eFillStyle;
1066
1067 css::drawing::LineStyle eLineStyle;
1068 xSet->getPropertyValue( "LineStyle" ) >>= eLineStyle;
1069
1070 return eFillStyle != FillStyle_NONE || eLineStyle != css::drawing::LineStyle_NONE;
1071 }
1072 }
1073 catch( Exception& )
1074 {
1075 }
1076 return true;
1077}
1078
1079std::unique_ptr<STLPropertySet> CustomAnimationPane::createSelectionSet()
1080{
1081 std::unique_ptr<STLPropertySet> pSet = CustomAnimationDialog::createDefaultSet();
1082
1083 pSet->setPropertyValue( nHandleCurrentPage, Any( mxCurrentPage ) );
1084
1085 sal_Int32 nMaxParaDepth = 0;
1086
1087 // get options from selected effects
1090 {
1091 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
1092 if( !pEffectSequence )
1093 pEffectSequence = mpMainSequence.get();
1094
1095 if( pEffect->hasText() )
1096 {
1097 sal_Int32 n = calcMaxParaDepth(pEffect->getTargetShape());
1098 if( n > nMaxParaDepth )
1099 nMaxParaDepth = n;
1100 }
1101
1102 addValue( pSet, nHandleHasAfterEffect, Any( pEffect->hasAfterEffect() ) );
1103 addValue( pSet, nHandleAfterEffectOnNextEffect, Any( pEffect->IsAfterEffectOnNext() ) );
1104 addValue( pSet, nHandleDimColor, pEffect->getDimColor() );
1105 addValue( pSet, nHandleIterateType, Any( pEffect->getIterateType() ) );
1106
1107 // convert absolute time to percentage value
1108 // This calculation is done in float to avoid some rounding artifacts.
1109 float fIterateInterval = static_cast<float>(pEffect->getIterateInterval());
1110 if( pEffect->getDuration() )
1111 fIterateInterval = static_cast<float>(fIterateInterval / pEffect->getDuration() );
1112 fIterateInterval *= 100.0;
1113 addValue( pSet, nHandleIterateInterval, Any( static_cast<double>(fIterateInterval) ) );
1114
1115 addValue( pSet, nHandleBegin, Any( pEffect->getBegin() ) );
1116 addValue( pSet, nHandleDuration, Any( pEffect->getDuration() ) );
1117 addValue( pSet, nHandleStart, Any( pEffect->getNodeType() ) );
1118 addValue( pSet, nHandleRepeat, pEffect->getRepeatCount() );
1119 addValue( pSet, nHandleEnd, pEffect->getEnd() );
1120 addValue( pSet, nHandleRewind, Any( pEffect->getFill() ) );
1121
1122 addValue( pSet, nHandlePresetId, Any( pEffect->getPresetId() ) );
1123
1124 addValue( pSet, nHandleHasText, Any( pEffect->hasText() ) );
1125
1126 addValue( pSet, nHandleHasVisibleShape, Any( hasVisibleShape( pEffect->getTargetShape() ) ) );
1127
1128 Any aSoundSource;
1129 if( pEffect->getAudio().is() )
1130 {
1131 aSoundSource = pEffect->getAudio()->getSource();
1132 addValue( pSet, nHandleSoundVolume, Any( pEffect->getAudio()->getVolume() ) );
1133// todo addValue( pSet, nHandleSoundEndAfterSlide, makeAny( pEffect->getAudio()->getEndAfterSlide() ) );
1134// this is now stored at the XCommand parameter sequence
1135 }
1136 else if( pEffect->getCommand() == EffectCommands::STOPAUDIO )
1137 {
1138 aSoundSource <<= true;
1139 }
1140 addValue( pSet, nHandleSoundURL, aSoundSource );
1141
1142 sal_Int32 nGroupId = pEffect->getGroupId();
1143 CustomAnimationTextGroupPtr pTextGroup;
1144 if( nGroupId != -1 )
1145 pTextGroup = pEffectSequence->findGroup( nGroupId );
1146
1147 addValue( pSet, nHandleTextGrouping, Any( pTextGroup ? pTextGroup->getTextGrouping() : sal_Int32(-1) ) );
1148 addValue( pSet, nHandleAnimateForm, Any( !pTextGroup || pTextGroup->getAnimateForm() ) );
1149 addValue( pSet, nHandleTextGroupingAuto, Any( pTextGroup ? pTextGroup->getTextGroupingAuto() : -1.0 ) );
1150 addValue( pSet, nHandleTextReverse, Any( pTextGroup && pTextGroup->getTextReverse() ) );
1151
1152 if( pEffectSequence->getSequenceType() == EffectNodeType::INTERACTIVE_SEQUENCE )
1153 {
1154 InteractiveSequence* pIS = static_cast< InteractiveSequence* >( pEffectSequence );
1155 addValue( pSet, nHandleTrigger, Any( pIS->getTriggerShape() ) );
1156 }
1157
1158 CustomAnimationPresetPtr pDescriptor = rPresets.getEffectDescriptor( pEffect->getPresetId() );
1159 if( pDescriptor )
1160 {
1161 sal_Int32 nType = nPropertyTypeNone;
1162
1163 std::vector<OUString> aProperties( pDescriptor->getProperties() );
1164 if( !aProperties.empty() )
1165 nType = getPropertyType( aProperties.front() );
1166
1167 if( nType != nPropertyTypeNone )
1168 {
1171 }
1172
1173 if( pDescriptor->hasProperty( u"Accelerate" ) )
1174 {
1175 addValue( pSet, nHandleAccelerate, Any( pEffect->getAcceleration() ) );
1176 }
1177
1178 if( pDescriptor->hasProperty( u"Decelerate" ) )
1179 {
1180 addValue( pSet, nHandleDecelerate, Any( pEffect->getDecelerate() ) );
1181 }
1182
1183 if( pDescriptor->hasProperty( u"AutoReverse" ) )
1184 {
1185 addValue( pSet, nHandleAutoReverse, Any( pEffect->getAutoReverse() ) );
1186 }
1187 }
1188 }
1189
1190 addValue( pSet, nHandleMaxParaDepth, Any( nMaxParaDepth ) );
1191
1192 return pSet;
1193}
1194
1195void CustomAnimationPane::changeSelection( STLPropertySet const * pResultSet, STLPropertySet const * pOldSet )
1196{
1197 // change selected effect
1198 bool bChanged = false;
1199
1201
1203 {
1204 DBG_ASSERT( pEffect->getEffectSequence(), "sd::CustomAnimationPane::changeSelection(), dead effect in selection!" );
1205 if( !pEffect->getEffectSequence() )
1206 continue;
1207
1208 double fDuration = 0.0; // we might need this for iterate-interval
1210 {
1211 pResultSet->getPropertyValue( nHandleDuration ) >>= fDuration;
1212 }
1213 else
1214 {
1215 fDuration = pEffect->getDuration();
1216 }
1217
1219 {
1220 sal_Int16 nIterateType = 0;
1221 pResultSet->getPropertyValue( nHandleIterateType ) >>= nIterateType;
1222 if( pEffect->getIterateType() != nIterateType )
1223 {
1224 pEffect->setIterateType( nIterateType );
1225 bChanged = true;
1226 }
1227 }
1228
1229 if( pEffect->getIterateType() )
1230 {
1232 {
1233 double fIterateInterval = 0.0;
1234 pResultSet->getPropertyValue( nHandleIterateInterval ) >>= fIterateInterval;
1235 if( pEffect->getIterateInterval() != fIterateInterval )
1236 {
1237 const double f = fIterateInterval * pEffect->getDuration() / 100;
1238 pEffect->setIterateInterval( f );
1239 bChanged = true;
1240 }
1241 }
1242 }
1243
1244 double fBegin = 0.0;
1245
1247 pResultSet->getPropertyValue( nHandleBegin ) >>= fBegin;
1248 else
1249 fBegin = pEffect->getBegin();
1250
1251 if( pEffect->getBegin() != fBegin && pResultSet->getPropertyState( nHandleBegin ) == STLPropertyState::Direct)
1252 {
1253 pEffect->setBegin( fBegin );
1254 bChanged = true;
1255 }
1256
1258 {
1259 if( pEffect->getDuration() != fDuration )
1260 {
1261 pEffect->setDuration( fDuration );
1262 bChanged = true;
1263 }
1264 }
1265
1267 {
1268 sal_Int16 nNodeType = 0;
1269 pResultSet->getPropertyValue( nHandleStart ) >>= nNodeType;
1270 if( pEffect->getNodeType() != nNodeType )
1271 {
1272 pEffect->setNodeType( nNodeType );
1273 bChanged = true;
1274 }
1275 }
1276
1278 {
1279 Any aRepeatCount( pResultSet->getPropertyValue( nHandleRepeat ) );
1280 if( aRepeatCount != pEffect->getRepeatCount() )
1281 {
1282 pEffect->setRepeatCount( aRepeatCount );
1283 bChanged = true;
1284 }
1285 }
1286
1288 {
1289 Any aEndValue( pResultSet->getPropertyValue( nHandleEnd ) );
1290 if( pEffect->getEnd() != aEndValue )
1291 {
1292 pEffect->setEnd( aEndValue );
1293 bChanged = true;
1294 }
1295 }
1296
1298 {
1299 sal_Int16 nFill = 0;
1300 pResultSet->getPropertyValue( nHandleRewind ) >>= nFill;
1301 if( pEffect->getFill() != nFill )
1302 {
1303 pEffect->setFill( nFill );
1304 bChanged = true;
1305 }
1306 }
1307
1309 {
1310 bool bHasAfterEffect = false;
1311 if( pResultSet->getPropertyValue( nHandleHasAfterEffect ) >>= bHasAfterEffect )
1312 {
1313 if( pEffect->hasAfterEffect() != bHasAfterEffect )
1314 {
1315 pEffect->setHasAfterEffect( bHasAfterEffect );
1316 bChanged = true;
1317 }
1318 }
1319 }
1320
1322 {
1323 bool bAfterEffectOnNextEffect = false;
1324 if( (pResultSet->getPropertyValue( nHandleAfterEffectOnNextEffect ) >>= bAfterEffectOnNextEffect)
1325 && (pEffect->IsAfterEffectOnNext() != bAfterEffectOnNextEffect) )
1326 {
1327 pEffect->setAfterEffectOnNext( bAfterEffectOnNextEffect );
1328 bChanged = true;
1329 }
1330 }
1331
1333 {
1334 Any aDimColor( pResultSet->getPropertyValue( nHandleDimColor ) );
1335 if( pEffect->getDimColor() != aDimColor )
1336 {
1337 pEffect->setDimColor( aDimColor );
1338 bChanged = true;
1339 }
1340 }
1341
1343 {
1344 double fAccelerate = 0.0;
1345 pResultSet->getPropertyValue( nHandleAccelerate ) >>= fAccelerate;
1346 if( pEffect->getAcceleration() != fAccelerate )
1347 {
1348 pEffect->setAcceleration( fAccelerate );
1349 bChanged = true;
1350 }
1351 }
1352
1354 {
1355 double fDecelerate = 0.0;
1356 pResultSet->getPropertyValue( nHandleDecelerate ) >>= fDecelerate;
1357 if( pEffect->getDecelerate() != fDecelerate )
1358 {
1359 pEffect->setDecelerate( fDecelerate );
1360 bChanged = true;
1361 }
1362 }
1363
1365 {
1366 bool bAutoReverse = false;
1367 pResultSet->getPropertyValue( nHandleAutoReverse ) >>= bAutoReverse;
1368 if( pEffect->getAutoReverse() != bAutoReverse )
1369 {
1370 pEffect->setAutoReverse( bAutoReverse );
1371 bChanged = true;
1372 }
1373 }
1374
1376 {
1377 sal_Int32 nType = 0;
1379
1380 bChanged |= setProperty1Value( nType, pEffect, pResultSet->getPropertyValue( nHandleProperty1Value ) );
1381 }
1382
1384 {
1385 const Any aSoundSource( pResultSet->getPropertyValue( nHandleSoundURL ) );
1386
1387 if( aSoundSource.getValueType() == ::cppu::UnoType<sal_Bool>::get() )
1388 {
1389 pEffect->setStopAudio();
1390 bChanged = true;
1391 }
1392 else
1393 {
1394 OUString aSoundURL;
1395 aSoundSource >>= aSoundURL;
1396
1397 if( !aSoundURL.isEmpty() )
1398 {
1399 if( !pEffect->getAudio().is() )
1400 {
1401 pEffect->createAudio( aSoundSource );
1402 bChanged = true;
1403 }
1404 else
1405 {
1406 if( pEffect->getAudio()->getSource() != aSoundSource )
1407 {
1408 pEffect->getAudio()->setSource( aSoundSource );
1409 bChanged = true;
1410 }
1411 }
1412 }
1413 else
1414 {
1415 if( pEffect->getAudio().is() || pEffect->getStopAudio() )
1416 {
1417 pEffect->removeAudio();
1418 bChanged = true;
1419 }
1420 }
1421 }
1422 }
1423
1425 {
1426 Reference< XShape > xTriggerShape;
1427 pResultSet->getPropertyValue( nHandleTrigger ) >>= xTriggerShape;
1428 bChanged |= mpMainSequence->setTrigger( pEffect, xTriggerShape );
1429 }
1430 }
1431
1432 const bool bHasTextGrouping = pResultSet->getPropertyState( nHandleTextGrouping ) == STLPropertyState::Direct;
1433 const bool bHasAnimateForm = pResultSet->getPropertyState( nHandleAnimateForm ) == STLPropertyState::Direct;
1434 const bool bHasTextGroupingAuto = pResultSet->getPropertyState( nHandleTextGroupingAuto ) == STLPropertyState::Direct;
1435 const bool bHasTextReverse = pResultSet->getPropertyState( nHandleTextReverse ) == STLPropertyState::Direct;
1436
1437 if( bHasTextGrouping || bHasAnimateForm || bHasTextGroupingAuto || bHasTextReverse )
1438 {
1439 // we need to do a second pass for text grouping options
1440 // since changing them can cause effects to be removed
1441 // or replaced, we do this after we applied all other options
1442 // above
1443
1444 sal_Int32 nTextGrouping = 0;
1445 bool bAnimateForm = true, bTextReverse = false;
1446 double fTextGroupingAuto = -1.0;
1447
1448 if( bHasTextGrouping )
1449 pResultSet->getPropertyValue(nHandleTextGrouping) >>= nTextGrouping;
1450 else
1451 pOldSet->getPropertyValue(nHandleTextGrouping) >>= nTextGrouping;
1452
1453 if( bHasAnimateForm )
1454 pResultSet->getPropertyValue(nHandleAnimateForm) >>= bAnimateForm;
1455 else
1456 pOldSet->getPropertyValue(nHandleAnimateForm) >>= bAnimateForm;
1457
1458 if( bHasTextGroupingAuto )
1459 pResultSet->getPropertyValue(nHandleTextGroupingAuto) >>= fTextGroupingAuto;
1460 else
1461 pOldSet->getPropertyValue(nHandleTextGroupingAuto) >>= fTextGroupingAuto;
1462
1463 if( bHasTextReverse )
1464 pResultSet->getPropertyValue(nHandleTextReverse) >>= bTextReverse;
1465 else
1466 pOldSet->getPropertyValue(nHandleTextReverse) >>= bTextReverse;
1467
1468 EffectSequence const aSelectedEffects( maListSelection );
1469 for( CustomAnimationEffectPtr const& pEffect : aSelectedEffects )
1470 {
1471 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
1472 if( !pEffectSequence )
1473 pEffectSequence = mpMainSequence.get();
1474
1475 sal_Int32 nGroupId = pEffect->getGroupId();
1476 CustomAnimationTextGroupPtr pTextGroup;
1477 if( nGroupId != -1 )
1478 {
1479 // use existing group
1480 pTextGroup = pEffectSequence->findGroup( nGroupId );
1481 }
1482 else
1483 {
1484 // somethings changed so we need a group now
1485 pTextGroup = pEffectSequence->createTextGroup( pEffect, nTextGrouping, fTextGroupingAuto, bAnimateForm, bTextReverse );
1486 bChanged = true;
1487 }
1488
1489 //#i119988#
1490 /************************************************************************/
1491 /*
1492 Note, the setAnimateForm means set the animation from TextGroup to Object's Shape
1493 And on the UI in means "Animate attached shape" in "Effect Option" dialog
1494 The setTextGrouping means set animation to Object's Text,
1495 the nTextGrouping is Text Animation Type
1496 nTextGrouping = -1 is "As one Object", means no text animation.
1497
1498 The previous call order first do the setTextGrouping and then do the setAnimateForm,
1499 that will cause such defect: in the setTextGrouping, the effect has been removed,
1500 but in setAnimateForm still need this effect, then a NULL pointer of that effect will
1501 be gotten, and cause crash.
1502
1503 []bHasAnimateForm means the UI has changed, bAnimateForm is it value
1504
1505 So if create a new textgroup animation, the following animation will never be run!
1506 Since the \A1\B0Animate attached shape\A1\B1 is default checked.
1507 And the bHasAnimateForm default is false, and if user uncheck it the value bAnimateForm will be false,
1508 it same as the TextGroup\A1\AFs default value, also could not be run setAnimateForm.
1509 if( bHasAnimateForm )
1510 {
1511 if( pTextGroup->getAnimateForm() != bAnimateForm )
1512 {
1513 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1514 bChanged = true;
1515 }
1516 }
1517
1518 In setTextGrouping, there are three case:
1519 1. Create new text effects for empty TextGroup
1520 2. Remove all text effects of TextGroup (nTextGrouping == -1)
1521 3. Change all the text effects\A1\AF start type
1522
1523 So here is the right logic:
1524 If set the animation from text to shape and remove text animation,
1525 should do setAnimateForm first, then do setTextGrouping.
1526 Other case,do setTextGrouping first, then do setAnimateForm.
1527
1528 */
1529 /************************************************************************/
1530
1531 bool bDoSetAnimateFormFirst = false;
1532 bool bNeedDoSetAnimateForm = false;
1533
1534 if( bHasAnimateForm )
1535 {
1536 if( pTextGroup && pTextGroup->getAnimateForm() != bAnimateForm )
1537 {
1538 if( (pTextGroup->getTextGrouping() >= 0) && (nTextGrouping == -1 ) )
1539 {
1540 bDoSetAnimateFormFirst = true;
1541 }
1542 bNeedDoSetAnimateForm = true;
1543 }
1544 }
1545
1546 if (bDoSetAnimateFormFirst)
1547 {
1548 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1549 bChanged = true;
1550 }
1551
1552 if( bHasTextGrouping )
1553 {
1554 if( pTextGroup && pTextGroup->getTextGrouping() != nTextGrouping )
1555 {
1556 pEffectSequence->setTextGrouping( pTextGroup, nTextGrouping );
1557
1558 // All the effects of the outline object is removed so we need to
1559 // put it back. OTOH, the shape object that still has effects
1560 // in the text group is fine.
1561 if (nTextGrouping == -1 && pTextGroup->getEffects().empty())
1562 {
1563 pEffect->setTarget(Any(pEffect->getTargetShape()));
1564 pEffect->setGroupId(-1);
1565 mpMainSequence->append(pEffect);
1566 }
1567
1568 bChanged = true;
1569 }
1570 }
1571
1572 if (!bDoSetAnimateFormFirst && bNeedDoSetAnimateForm)
1573 {
1574 if( pTextGroup )
1575 {
1576 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1577 bChanged = true;
1578 }
1579 }
1580
1581 if( bHasTextGroupingAuto )
1582 {
1583 if( pTextGroup && pTextGroup->getTextGroupingAuto() != fTextGroupingAuto )
1584 {
1585 pEffectSequence->setTextGroupingAuto( pTextGroup, fTextGroupingAuto );
1586 bChanged = true;
1587 }
1588 }
1589
1590 if( bHasTextReverse )
1591 {
1592 if( pTextGroup && pTextGroup->getTextReverse() != bTextReverse )
1593 {
1594 pEffectSequence->setTextReverse( pTextGroup, bTextReverse );
1595 bChanged = true;
1596 }
1597 }
1598 }
1599 }
1600
1601 if( bChanged )
1602 {
1603 mpMainSequence->rebuild();
1606 }
1607}
1608
1609void CustomAnimationPane::showOptions(const OUString& rPage)
1610{
1611 std::unique_ptr<STLPropertySet> xSet = createSelectionSet();
1612
1613 auto xDlg = std::make_shared<CustomAnimationDialog>(GetFrameWeld(), std::move(xSet), rPage);
1614
1615 weld::DialogController::runAsync(xDlg, [xDlg, this](sal_Int32 nResult){
1616 if (nResult )
1617 {
1618 addUndo();
1619 changeSelection(xDlg->getResultSet(), xDlg->getPropertySet());
1621 }
1622 });
1623}
1624
1626{
1627 if( !mxView.is() )
1628 return;
1629
1630 try
1631 {
1632 Reference< XDrawPage > xNewPage( mxView->getCurrentPage() );
1633 if( xNewPage != mxCurrentPage )
1634 {
1635 mxCurrentPage = xNewPage;
1637 if( pPage )
1638 {
1641 }
1643 }
1644 }
1645 catch( Exception& )
1646 {
1647 TOOLS_WARN_EXCEPTION( "sd", "sd::CustomAnimationPane::onChangeCurrentPage()" );
1648 }
1649}
1650
1651static bool getTextSelection( const Any& rSelection, Reference< XShape >& xShape, std::vector< sal_Int16 >& rParaList )
1652{
1653 Reference< XTextRange > xSelectedText;
1654 rSelection >>= xSelectedText;
1655 if( xSelectedText.is() ) try
1656 {
1657 xShape.set( xSelectedText->getText(), UNO_QUERY_THROW );
1658
1659 css::uno::Reference<css::document::XActionLockable> xLockable(xShape, css::uno::UNO_QUERY);
1660 if (xLockable.is())
1661 xLockable->addActionLock();
1662 comphelper::ScopeGuard aGuard([&xLockable]()
1663 {
1664 if (xLockable.is())
1665 xLockable->removeActionLock();
1666 });
1667
1668 Reference< XTextRangeCompare > xTextRangeCompare( xShape, UNO_QUERY_THROW );
1669 Reference< XEnumerationAccess > xParaEnumAccess( xShape, UNO_QUERY_THROW );
1670 Reference< XEnumeration > xParaEnum( xParaEnumAccess->createEnumeration(), UNO_SET_THROW );
1671 Reference< XTextRange > xRange;
1672 Reference< XTextRange > xStart( xSelectedText->getStart() );
1673 Reference< XTextRange > xEnd( xSelectedText->getEnd() );
1674
1675 if( xTextRangeCompare->compareRegionEnds( xStart, xEnd ) < 0 )
1676 {
1677 Reference< XTextRange > xTemp( xStart );
1678 xStart = xEnd;
1679 xEnd = xTemp;
1680 }
1681
1682 sal_Int16 nPara = 0;
1683 while( xParaEnum->hasMoreElements() )
1684 {
1685 xParaEnum->nextElement() >>= xRange;
1686
1687 // break if start of selection is prior to end of current paragraph
1688 if( xRange.is() && (xTextRangeCompare->compareRegionEnds( xStart, xRange ) >= 0 ) )
1689 break;
1690
1691 nPara++;
1692 }
1693
1694 while( xRange.is() )
1695 {
1696 if( xRange.is() && !xRange->getString().isEmpty() )
1697 rParaList.push_back( nPara );
1698
1699 // break if end of selection is before or at end of current paragraph
1700 if( xRange.is() && xTextRangeCompare->compareRegionEnds( xEnd, xRange ) >= 0 )
1701 break;
1702
1703 nPara++;
1704
1705 if( xParaEnum->hasMoreElements() )
1706 xParaEnum->nextElement() >>= xRange;
1707 else
1708 xRange.clear();
1709 }
1710
1711 return true;
1712 }
1713 catch( Exception& )
1714 {
1715 TOOLS_WARN_EXCEPTION( "sd", "sd::CustomAnimationPane::getTextSelection()" );
1716 }
1717
1718 return false;
1719}
1720
1721namespace
1722{
1723 Reference<XShape> getTargetShape(const Any& rTarget)
1724 {
1725 Reference<XShape> xShape;
1726 rTarget >>= xShape;
1727 if( !xShape.is() )
1728 {
1729 ParagraphTarget aParaTarget;
1730 if (rTarget >>= aParaTarget)
1731 xShape = aParaTarget.Shape;
1732 }
1733 return xShape;
1734 }
1735}
1736
1738{
1739 bool bHasText = true;
1740
1741 // first create vector of targets for dialog preview
1742 std::vector< Any > aTargets;
1743
1744 // gather shapes from the selection
1745 Reference< XSelectionSupplier > xSel( mxView, UNO_QUERY_THROW );
1746 maViewSelection = xSel->getSelection();
1747
1748 if( maViewSelection.getValueType() == cppu::UnoType<XShapes>::get())
1749 {
1750 Reference< XIndexAccess > xShapes;
1751 maViewSelection >>= xShapes;
1752
1753 sal_Int32 nCount = xShapes->getCount();
1754 aTargets.reserve( nCount );
1755 for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ )
1756 {
1757 Any aTarget( xShapes->getByIndex( nIndex ) );
1758 aTargets.push_back( aTarget );
1759 if( bHasText )
1760 {
1761 Reference< XText > xText;
1762 aTarget >>= xText;
1763 if( !xText.is() || xText->getString().isEmpty() )
1764 bHasText = false;
1765 }
1766 }
1767 }
1768 else if ( maViewSelection.getValueType() == cppu::UnoType<XShape>::get())
1769 {
1770 aTargets.push_back( maViewSelection );
1771 Reference< XText > xText;
1772 maViewSelection >>= xText;
1773 if( !xText.is() || xText->getString().isEmpty() )
1774 bHasText = false;
1775 }
1776 else if ( maViewSelection.getValueType() == cppu::UnoType<XTextCursor>::get())
1777 {
1778 Reference< XShape > xShape;
1779 std::vector< sal_Int16 > aParaList;
1780 if( getTextSelection( maViewSelection, xShape, aParaList ) )
1781 {
1782 ParagraphTarget aParaTarget;
1783 aParaTarget.Shape = xShape;
1784
1785 for( const auto& rPara : aParaList )
1786 {
1787 aParaTarget.Paragraph = rPara;
1788 aTargets.push_back( Any( aParaTarget ) );
1789 }
1790 }
1791 }
1792 else
1793 {
1794 OSL_FAIL("sd::CustomAnimationPane::onAdd(), unknown view selection!" );
1795 return;
1796 }
1797
1798 CustomAnimationPresetPtr pDescriptor;
1799 mxFTCategory->set_sensitive(true);
1800 mxFTAnimation->set_sensitive(true);
1801
1802 bool bCategoryReset = false;
1803
1804 if (!mxLBCategory->get_sensitive() || mxLBCategory->get_active() == -1)
1805 {
1806 mxLBCategory->set_sensitive(true);
1807 mxLBCategory->set_active(0);
1808 bCategoryReset = true;
1809 }
1810
1811 if (bCategoryReset || !mxLBAnimation->get_sensitive() ||
1812 mxLBAnimation->get_selected_index() == -1)
1813 {
1814 mxLBAnimation->set_sensitive(true);
1815
1816 sal_Int32 nFirstEffect = fillAnimationLB(bHasText);
1817 if (nFirstEffect == -1)
1818 return;
1819
1820 mxLBAnimation->select(nFirstEffect);
1821 mnLastSelectedAnimation = nFirstEffect;
1822 }
1823
1824 auto pEntryData = weld::fromId<CustomAnimationPresetPtr*>(mxLBAnimation->get_selected_id());
1825 if (pEntryData)
1826 pDescriptor = *pEntryData;
1827
1828 if( pDescriptor )
1829 {
1830 const double fDuration = pDescriptor->getDuration();
1831 mxCBXDuration->set_value(fDuration*100.0, FieldUnit::NONE);
1832 bool bHasSpeed = pDescriptor->getDuration() > 0.001;
1833 mxCBXDuration->set_sensitive( bHasSpeed );
1834 mxFTDuration->set_sensitive( bHasSpeed );
1835
1836 mxCustomAnimationList->unselect_all();
1837
1838 // gather shapes from the selection
1839 bool bFirst = true;
1840 for( const auto& rTarget : aTargets )
1841 {
1842 css::uno::Reference<css::document::XActionLockable> xLockable(getTargetShape(rTarget), css::uno::UNO_QUERY);
1843 if (xLockable.is())
1844 xLockable->addActionLock();
1845 comphelper::ScopeGuard aGuard([&xLockable]()
1846 {
1847 if (xLockable.is())
1848 xLockable->removeActionLock();
1849 });
1850
1851 CustomAnimationEffectPtr pCreated = mpMainSequence->append( pDescriptor, rTarget, fDuration );
1852
1853 // if only one shape with text and no fill or outline is selected, animate only by first level paragraphs
1854 if( bHasText && (aTargets.size() == 1) )
1855 {
1856 Reference< XShape > xShape( rTarget, UNO_QUERY );
1857 if( xShape.is() && !hasVisibleShape( xShape ) )
1858 {
1859 mpMainSequence->createTextGroup( pCreated, 1, -1.0, false, false );
1860 }
1861 }
1862
1863 if( bFirst )
1864 bFirst = false;
1865 else
1866 pCreated->setNodeType( EffectNodeType::WITH_PREVIOUS );
1867
1868 if( pCreated )
1869 mxCustomAnimationList->select( pCreated );
1870 }
1871 }
1872
1873 PathKind ePathKind = getCreatePathKind();
1874
1875 if (ePathKind != PathKind::NONE)
1876 {
1877 createPath( ePathKind, aTargets, 0.0 );
1879 }
1880
1881 addUndo();
1883
1885
1887}
1888
1890{
1891 if( maListSelection.empty() )
1892 return;
1893
1894 addUndo();
1895
1897
1899
1900 for( CustomAnimationEffectPtr& pEffect : aList )
1901 {
1902 if( pEffect->getEffectSequence() )
1903 pEffect->getEffectSequence()->remove( pEffect );
1904 }
1905
1906 maListSelection.clear();
1908}
1909
1911{
1912 if( pEffect->getEffectSequence() )
1913 {
1914 addUndo();
1915 pEffect->getEffectSequence()->remove( pEffect );
1917 }
1918}
1919
1921{
1922 sal_Int16 nNodeType;
1923 switch( mxLBStart->get_active() )
1924 {
1925 case 0: nNodeType = EffectNodeType::ON_CLICK; break;
1926 case 1: nNodeType = EffectNodeType::WITH_PREVIOUS; break;
1927 case 2: nNodeType = EffectNodeType::AFTER_PREVIOUS; break;
1928 default:
1929 return;
1930 }
1931
1932 onChangeStart( nNodeType );
1933}
1934
1935void CustomAnimationPane::onChangeStart( sal_Int16 nNodeType )
1936{
1937 addUndo();
1938
1940
1941 bool bNeedRebuild = false;
1942
1944 {
1945 if( pEffect->getNodeType() != nNodeType )
1946 {
1947 pEffect->setNodeType( nNodeType );
1948 bNeedRebuild = true;
1949 }
1950 }
1951
1952 if( bNeedRebuild )
1953 {
1954 mpMainSequence->rebuild();
1957 }
1958}
1959
1961{
1962 double fDuration = getDuration();
1963
1964 if(fDuration < 0)
1965 return;
1966 else
1967 {
1968 addUndo();
1969
1971
1972 // change selected effect
1974 {
1975 pEffect->setDuration( fDuration );
1976 }
1977
1978 mpMainSequence->rebuild();
1981 }
1982}
1983
1985{
1986 double fDuration = 0;
1987
1988 if (!mxCBXDuration->get_text().isEmpty())
1989 fDuration = mxCBXDuration->get_value(FieldUnit::NONE) / 100.0;
1990
1991 return fDuration;
1992}
1993
1995{
1996 PathKind eKind = PathKind::NONE;
1997
1998 if (mxLBAnimation->count_selected_rows() == 1 &&
1999 mxLBCategory->get_active() == gnMotionPathPos)
2000 {
2001 const sal_Int32 nPos = mxLBAnimation->get_selected_index();
2002 if( nPos == mnCurvePathPos )
2003 {
2004 eKind = PathKind::CURVE;
2005 }
2006 else if( nPos == mnPolygonPathPos )
2007 {
2008 eKind = PathKind::POLYGON;
2009 }
2010 else if( nPos == mnFreeformPathPos )
2011 {
2012 eKind = PathKind::FREEFORM;
2013 }
2014 }
2015
2016 return eKind;
2017}
2018
2019void CustomAnimationPane::createPath( PathKind eKind, std::vector< Any >& rTargets, double fDuration)
2020{
2021 sal_uInt16 nSID = 0;
2022
2023 switch( eKind )
2024 {
2025 case PathKind::CURVE: nSID = SID_DRAW_BEZIER_NOFILL; break;
2026 case PathKind::POLYGON: nSID = SID_DRAW_POLYGON_NOFILL; break;
2027 case PathKind::FREEFORM: nSID = SID_DRAW_FREELINE_NOFILL; break;
2028 default: break;
2029 }
2030
2031 if( !nSID )
2032 return;
2033
2034 DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >(
2035 FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get());
2036
2037 if( pViewShell )
2038 {
2039 DrawView* pView = pViewShell->GetDrawView();
2040 if( pView )
2041 pView->UnmarkAllObj();
2042
2043 std::vector< Any > aTargets( 1, Any( fDuration ) );
2044 aTargets.insert( aTargets.end(), rTargets.begin(), rTargets.end() );
2045 Sequence< Any > aTargetSequence( comphelper::containerToSequence( aTargets ) );
2046 const SfxUnoAnyItem aItem( SID_ADD_MOTION_PATH, Any( aTargetSequence ) );
2047 pViewShell->GetViewFrame()->GetDispatcher()->ExecuteList( nSID, SfxCallMode::ASYNCHRON, {&aItem} );
2048 }
2049}
2050
2051
2054{
2055 if (!mxLBSubControl)
2056 return;
2057
2058 addUndo();
2059
2060 MainSequenceRebuildGuard aGuard( mpMainSequence );
2061
2062 const Any aValue(mxLBSubControl->getValue());
2063
2064 bool bNeedUpdate = false;
2065
2066 // change selected effect
2067 for( const CustomAnimationEffectPtr& pEffect : maListSelection )
2068 {
2069 if( setProperty1Value( mnPropertyType, pEffect, aValue ) )
2070 bNeedUpdate = true;
2071 }
2072
2073 if( bNeedUpdate )
2074 {
2075 mpMainSequence->rebuild();
2076 updateControls();
2077 mrBase.GetDocShell()->SetModified();
2078 }
2079
2080 onPreview( false );
2081}
2082
2084{
2085 addUndo();
2086}
2087
2089{
2090 double fBegin = mxMFStartDelay->get_value(FieldUnit::NONE);
2091
2092 //sequence rebuild only when the control loses focus
2093 MainSequenceRebuildGuard aGuard( mpMainSequence );
2094
2095 // change selected effect
2096 for( CustomAnimationEffectPtr& pEffect : maListSelection )
2097 {
2098 pEffect->setBegin( fBegin/10.0 );
2099 }
2100
2101 mpMainSequence->rebuild();
2102 updateControls();
2103 mrBase.GetDocShell()->SetModified();
2104}
2105
2107{
2108 maIdle.Start();
2109}
2110
2112{
2113 if (mxLBAnimation->has_grab()) // tdf#136474 try again later
2114 {
2115 maIdle.Start();
2116 return;
2117 }
2118
2119 int nSelected = mxLBAnimation->get_selected_index();
2120 if (nSelected == -1)
2121 return;
2122
2123 // tdf#99137, the selected entry may also be a subcategory title, so not an effect
2124 // just skip it and move to the next one in this case
2125 if (mxLBAnimation->get_text_emphasis(nSelected, 0))
2126 {
2127 if (nSelected == 0 || nSelected > mnLastSelectedAnimation)
2128 mxLBAnimation->select(++nSelected);
2129 else
2130 mxLBAnimation->select(--nSelected);
2131 }
2132
2133 mnLastSelectedAnimation = nSelected;
2134
2135 CustomAnimationPresetPtr* pPreset = weld::fromId<CustomAnimationPresetPtr*>(mxLBAnimation->get_id(nSelected));
2136 PathKind ePathKind = getCreatePathKind();
2137
2138 if ( ePathKind != PathKind::NONE )
2139 {
2140 std::vector< Any > aTargets;
2141 MainSequenceRebuildGuard aGuard( mpMainSequence );
2142
2143 for( const CustomAnimationEffectPtr& pEffect : maListSelection )
2144 {
2145 aTargets.push_back( pEffect->getTarget() );
2146
2147 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
2148 if( !pEffectSequence )
2149 pEffectSequence = mpMainSequence.get();
2150
2151 // delete the old animation, new one will be appended
2152 // by createPath and SID_ADD_MOTION_PATH therein
2153 pEffectSequence->remove( pEffect );
2154 }
2155
2156 createPath( ePathKind, aTargets, 0.0 );
2157 updateMotionPathTags();
2158 return;
2159 }
2160
2161 CustomAnimationPresetPtr pDescriptor(*pPreset);
2162 const double fDuration = (*pPreset)->getDuration();
2163 MainSequenceRebuildGuard aGuard( mpMainSequence );
2164
2165 // get selected effect
2166 for( const CustomAnimationEffectPtr& pEffect : maListSelection )
2167 {
2168 // Dispose the deprecated motion path tag. It will be rebuilt later.
2169 if (pEffect->getPresetClass() == css::presentation::EffectPresetClass::MOTIONPATH)
2170 {
2171 for (auto const& xTag: maMotionPathTags)
2172 {
2173 if(xTag->getEffect() == pEffect && !xTag->isDisposed())
2174 xTag->Dispose();
2175 }
2176 }
2177
2178 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
2179 if( !pEffectSequence )
2180 pEffectSequence = mpMainSequence.get();
2181
2182 pEffectSequence->replace( pEffect, pDescriptor, fDuration );
2183 }
2184
2185 addUndo();
2186 onPreview(false);
2187}
2188
2190{
2191 //FIXME: first effect only? what if there is more?
2192 CustomAnimationEffectPtr pEffect = maListSelection.front();
2193 fillAnimationLB( pEffect->hasText() );
2194}
2195
2197{
2198 if (!mxCBXDuration->get_text().isEmpty())
2199 {
2200 double duration_value = static_cast<double>(mxCBXDuration->get_value(FieldUnit::NONE));
2201 if(duration_value <= 0.0)
2202 {
2203 mxCBXDuration->set_value(1, FieldUnit::NONE);
2204 }
2205 onChangeSpeed();
2206 }
2207}
2208
2209namespace
2210{
2211 void InsertCategory(weld::TreeView& rLBAnimation, const OUString& rMotionPathLabel)
2212 {
2213 int nRow = rLBAnimation.n_children();
2214 rLBAnimation.append_text(rMotionPathLabel);
2215 rLBAnimation.set_text_emphasis(nRow, true, 0);
2216 rLBAnimation.set_text_align(nRow, 0.5, 0);
2217 }
2218}
2219
2221{
2222 PresetCategoryList rCategoryList;
2223 sal_uInt16 nPosition = mxLBCategory->get_active();
2225 switch(nPosition)
2226 {
2227 case 0:rCategoryList = rPresets.getEntrancePresets();break;
2228 case 1:rCategoryList = rPresets.getEmphasisPresets();break;
2229 case 2:rCategoryList = rPresets.getExitPresets();break;
2230 case 3:rCategoryList = rPresets.getMotionPathsPresets();break;
2231 case 4:rCategoryList = rPresets.getMiscPresets();break;
2232 }
2233
2234 sal_Int32 nFirstEffect = -1;
2235
2236 int nOldEntryCount = mxLBAnimation->n_children();
2237 int nOldScrollPos = mxLBAnimation->vadjustment_get_value();
2238
2239 mxLBAnimation->freeze();
2240 mxLBAnimation->clear();
2242
2243 if (nPosition == gnMotionPathPos)
2244 {
2245 OUString sMotionPathLabel( SdResId( STR_CUSTOMANIMATION_USERPATH ) );
2246 InsertCategory(*mxLBAnimation, sMotionPathLabel);
2247 mnCurvePathPos = mxLBAnimation->n_children();
2248 mxLBAnimation->append_text( SvxResId(STR_ObjNameSingulCOMBLINE) );
2249 mxLBAnimation->set_text_emphasis(mnCurvePathPos, false, 0);
2251 mxLBAnimation->append_text( SvxResId(STR_ObjNameSingulPOLY) );
2252 mxLBAnimation->set_text_emphasis(mnPolygonPathPos, false, 0);
2254 mxLBAnimation->append_text( SvxResId(STR_ObjNameSingulFREELINE) );
2255 mxLBAnimation->set_text_emphasis(mnFreeformPathPos, false, 0);
2256 }
2257
2258 for (const PresetCategoryPtr& pCategory : rCategoryList)
2259 {
2260 if( pCategory )
2261 {
2262 InsertCategory(*mxLBAnimation, pCategory->maLabel);
2263
2264 int nPos = mxLBAnimation->n_children();
2265
2266 std::vector< CustomAnimationPresetPtr > aSortedVector =
2267 pCategory->maEffects;
2268
2269 for( const CustomAnimationPresetPtr& pDescriptor : aSortedVector )
2270 {
2271 // ( !isTextOnly || ( isTextOnly && bHasText ) ) <=> !isTextOnly || bHasText
2272 if( pDescriptor && ( !pDescriptor->isTextOnly() || bHasText ) )
2273 {
2274 auto pCustomPtr = new CustomAnimationPresetPtr(pDescriptor);
2275 OUString sId = weld::toId(pCustomPtr);
2276 mxLBAnimation->append(sId, pDescriptor->getLabel());
2277 mxLBAnimation->set_text_emphasis(nPos, false, 0);
2278
2279 if (nFirstEffect == -1)
2280 nFirstEffect = nPos;
2281
2282 ++nPos;
2283 }
2284 }
2285 }
2286 }
2287
2288 mxLBAnimation->thaw();
2289
2290 if (mxLBAnimation->n_children() == nOldEntryCount)
2291 mxLBAnimation->vadjustment_set_value(nOldScrollPos);
2292
2293 return nFirstEffect;
2294}
2295
2297{
2298 implControlHdl(&rBtn);
2299}
2300
2301IMPL_LINK(CustomAnimationPane, implClickHdl, weld::Button&, rBtn, void)
2302{
2303 implControlHdl(&rBtn);
2304}
2305
2306IMPL_LINK( CustomAnimationPane, implControlListBoxHdl, weld::ComboBox&, rListBox, void )
2307{
2308 implControlHdl(&rListBox);
2309}
2310
2313{
2314 if (pControl == mxPBAddEffect.get())
2315 onAdd();
2316 else if (pControl == mxPBRemoveEffect.get())
2317 onRemove();
2318 else if (pControl == mxLBStart.get())
2319 onChangeStart();
2320 else if (pControl == mxPBPropertyMore.get())
2321 showOptions();
2322 else if (pControl == mxPBMoveUp.get())
2323 moveSelection( true );
2324 else if (pControl == mxPBMoveDown.get())
2325 moveSelection( false );
2326 else if (pControl == mxPBPlay.get())
2327 onPreview( true );
2328 else if (pControl == mxCBAutoPreview.get())
2329 {
2330 SdOptions* pOptions = SD_MOD()->GetSdOptions(DocumentType::Impress);
2331 pOptions->SetPreviewChangedEffects(mxCBAutoPreview->get_active());
2332 }
2333}
2334
2335IMPL_LINK_NOARG(CustomAnimationPane, lateInitCallback, Timer *, void)
2336{
2337 // Call getPresets() to initiate the (expensive) construction of the
2338 // presets list.
2340
2341 // update selection and control states
2342 onSelectionChanged();
2343}
2344
2346{
2347 if( maListSelection.empty() )
2348 return;
2349
2350 EffectSequenceHelper* pSequence = maListSelection.front()->getEffectSequence();
2351 if( pSequence == nullptr )
2352 return;
2353
2354 addUndo();
2355
2356 bool bChanged = false;
2357
2359 EffectSequence& rEffectSequence = pSequence->getSequence();
2360
2361 if( bUp )
2362 {
2363 for( const CustomAnimationEffectPtr& pEffect : maListSelection )
2364 {
2365 EffectSequence::iterator aUpEffectPos( pSequence->find( pEffect ) );
2366 // coverity[copy_paste_error : FALSE] - this is correct, checking if it exists
2367 if( aUpEffectPos != rEffectSequence.end() )
2368 {
2369 EffectSequence::iterator aInsertPos( rEffectSequence.erase( aUpEffectPos ) );
2370
2371 if( aInsertPos != rEffectSequence.begin() )
2372 {
2373 --aInsertPos;
2374 while( (aInsertPos != rEffectSequence.begin()) && !mxCustomAnimationList->isExpanded(*aInsertPos))
2375 --aInsertPos;
2376 rEffectSequence.insert( aInsertPos, pEffect );
2377 }
2378 else
2379 {
2380 rEffectSequence.push_front( pEffect );
2381 }
2382 bChanged = true;
2383 }
2384 }
2385 }
2386 else
2387 {
2388 EffectSequence::reverse_iterator aIter( maListSelection.rbegin() );
2389 const EffectSequence::reverse_iterator aEnd( maListSelection.rend() );
2390
2391 while( aIter != aEnd )
2392 {
2393 CustomAnimationEffectPtr pEffect = *aIter++;
2394
2395 EffectSequence::iterator aDownEffectPos( pSequence->find( pEffect ) );
2396 // coverity[copy_paste_error : FALSE] - this is correct, checking if it exists
2397 if( aDownEffectPos != rEffectSequence.end() )
2398 {
2399 EffectSequence::iterator aInsertPos( rEffectSequence.erase( aDownEffectPos ) );
2400
2401 if( aInsertPos != rEffectSequence.end() )
2402 {
2403 ++aInsertPos;
2404 // Advance over rolled-up (un-expanded) items, unless we just moved it there.
2405 while( (aInsertPos != rEffectSequence.end())
2406 && !mxCustomAnimationList->isExpanded(*aInsertPos)
2407 && (std::find(maListSelection.begin(), maListSelection.end(), *aInsertPos)
2408 == maListSelection.end())
2409 )
2410 ++aInsertPos;
2411 rEffectSequence.insert( aInsertPos, pEffect );
2412 }
2413 else
2414 {
2415 rEffectSequence.push_back( pEffect );
2416 }
2417 bChanged = true;
2418 }
2419 }
2420 }
2421
2422 if( bChanged )
2423 {
2424 mpMainSequence->rebuild();
2427 }
2428}
2429
2430void CustomAnimationPane::onPreview( bool bForcePreview )
2431{
2432 if (!bForcePreview && !mxCBAutoPreview->get_active())
2433 return;
2434
2435 // No preview in LOK.
2437 return;
2438
2439 if( maListSelection.empty() )
2440 {
2441 rtl::Reference< MotionPathTag > xMotionPathTag;
2442 auto aIter = std::find_if(maMotionPathTags.begin(), maMotionPathTags.end(),
2443 [](const MotionPathTagVector::value_type& rxMotionPathTag) { return rxMotionPathTag->isSelected(); });
2444 if (aIter != maMotionPathTags.end())
2445 xMotionPathTag = *aIter;
2446
2447 if( xMotionPathTag.is() )
2448 {
2449 MainSequencePtr pSequence = std::make_shared<MainSequence>();
2450 pSequence->append( xMotionPathTag->getEffect()->clone() );
2451 preview( pSequence->getRootNode() );
2452 }
2453 else
2454 {
2455 Reference< XAnimationNodeSupplier > xNodeSupplier( mxCurrentPage, UNO_QUERY );
2456 if( !xNodeSupplier.is() )
2457 return;
2458
2459 preview( xNodeSupplier->getAnimationNode() );
2460 }
2461 }
2462 else
2463 {
2464 MainSequencePtr pSequence = std::make_shared<MainSequence>();
2465
2466 for( const CustomAnimationEffectPtr& pEffect : maListSelection )
2467 {
2468 pSequence->append( pEffect->clone() );
2469 }
2470
2471 preview( pSequence->getRootNode() );
2472 }
2473}
2474
2475void CustomAnimationPane::preview( const Reference< XAnimationNode >& xAnimationNode )
2476{
2477 Reference< XParallelTimeContainer > xRoot = ParallelTimeContainer::create( ::comphelper::getProcessComponentContext() );
2478 Sequence< css::beans::NamedValue > aUserData
2479 { { "node-type", css::uno::Any(css::presentation::EffectNodeType::TIMING_ROOT) } };
2480 xRoot->setUserData( aUserData );
2481 xRoot->appendChild( xAnimationNode );
2482
2484}
2485
2486// ICustomAnimationListController
2488{
2489 maListSelection = mxCustomAnimationList->getSelection();
2491
2492 // mark shapes from selected effects
2494 return;
2495
2496 // tdf#145030 if nothing is selected in the effects list, leave the selection of
2497 // objects in the slide untouched
2498 if (maListSelection.empty())
2499 return;
2500
2502 DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >(
2503 FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get());
2504 DrawView* pView = pViewShell ? pViewShell->GetDrawView() : nullptr;
2505
2506 if( pView )
2507 {
2508 pView->UnmarkAllObj();
2509 for( const CustomAnimationEffectPtr& pEffect : maListSelection )
2510 {
2511 Reference< XShape > xShape( pEffect->getTargetShape() );
2513 if( pObj )
2514 pView->MarkObj(pObj, pView->GetSdrPageView());
2515 }
2516 }
2517}
2518
2519// ICustomAnimationListController
2520// pEffectInsertBefore may be null if moving to end of list.
2521void CustomAnimationPane::onDragNDropComplete(std::vector< CustomAnimationEffectPtr > pEffectsDragged, CustomAnimationEffectPtr pEffectInsertBefore)
2522{
2523 if ( !mpMainSequence )
2524 return;
2525
2526 addUndo();
2527
2529
2530 // Move all selected effects
2531 for( auto const& pEffectDragged : pEffectsDragged )
2532 {
2533 // Move this dragged effect and any hidden sub-effects
2534 EffectSequence::iterator aIter = mpMainSequence->find( pEffectDragged );
2535 const EffectSequence::iterator aEnd( mpMainSequence->getEnd() );
2536
2537 while( aIter != aEnd )
2538 {
2539 CustomAnimationEffectPtr pEffect = *aIter++;
2540
2541 // Update model with new location (function triggers a rebuild)
2542 // target may be null, which will insert at the end.
2543 mpMainSequence->moveToBeforeEffect( pEffect, pEffectInsertBefore );
2544 // Done moving effect and its hidden sub-effects when *next* effect is visible.
2545 if (aIter != aEnd && mxCustomAnimationList->isVisible(*aIter))
2546 break;
2547 }
2548 }
2549
2552}
2553
2555{
2557 if( !xTag.is() )
2558 return;
2559
2560 SdrPathObj* pPathObj = xTag->getPathObj();
2561 CustomAnimationEffectPtr pEffect = xTag->getEffect();
2562 if( (pPathObj != nullptr) && pEffect )
2563 {
2565 if( pManager )
2566 {
2568 if( pPage )
2569 pManager->AddUndoAction( std::make_unique<UndoAnimationPath>( mrBase.GetDocShell()->GetDoc(), pPage, pEffect->getNode() ) );
2570 }
2571
2572 pEffect->updatePathFromSdrPathObj( *pPathObj );
2573 }
2574}
2575
2576}
2577
2578/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
@ EditViewSelection
The selection in the center pane has changed.
@ Disposing
The EventMultiplexer itself is being disposed.
@ EndTextEdit
Text editing in one of the shapes in the MainViewShell has ended.
@ MainViewRemoved
The current MainViewShell (the ViewShell displayed in the center pane) has been removed.
@ MainViewAdded
A new ViewShell has been made the MainViewShell.
@ CurrentPageChanged
The current page has changed.
PropertiesInfo aProperties
virtual weld::Window * GetFrameWeld() const
Size get_preferred_size() const
bool IsPreviewChangedEffects() const
Definition: optsitem.hxx:271
void SetPreviewChangedEffects(bool bOn)
Definition: optsitem.hxx:315
static SdPage * getImplementation(const css::uno::Reference< css::drawing::XDrawPage > &xPage)
returns the SdPage implementation for the given XDrawPage or 0 if not available
Definition: sdpage.cxx:2682
std::shared_ptr< sd::MainSequence > const & getMainSequence()
returns a helper class to manipulate effects inside the main sequence
void UnmarkAllObj(SdrPageView const *pPV=nullptr)
bool MarkObj(const Point &rPnt, short nTol=-2, bool bToggle=false, bool bDeep=false)
static SdrObject * getSdrObjectFromXShape(const css::uno::Reference< css::uno::XInterface > &xInt)
SdrPageView * GetSdrPageView() const
const SfxPoolItem * ExecuteList(sal_uInt16 nSlot, SfxCallMode nCall, std::initializer_list< SfxPoolItem const * > args, std::initializer_list< SfxPoolItem const * > internalargs=std::initializer_list< SfxPoolItem const * >())
virtual void AddUndoAction(std::unique_ptr< SfxUndoAction > pAction, bool bTryMerg=false)
SfxDispatcher * GetDispatcher()
css::uno::Reference< css::frame::XController > GetController() const
constexpr tools::Long Height() const
void SetPriority(TaskPriority ePriority)
void Stop()
void SetTimeout(sal_uInt64 nTimeoutMs)
void SetInvokeHandler(const Link< Timer *, void > &rLink)
virtual void Start(bool bStartTimer=true) override
static std::unique_ptr< STLPropertySet > createDefaultSet()
virtual ~CustomAnimationPane() override
std::unique_ptr< weld::TreeView > mxLBAnimation
std::unique_ptr< weld::MetricSpinButton > mxCBXDuration
void createPath(PathKind eKind, std::vector< ::com::sun::star::uno::Any > &rTargets, double fDuration)
virtual void onDragNDropComplete(std::vector< CustomAnimationEffectPtr > pEffectsDragged, CustomAnimationEffectPtr pEffectInsertBefore) override
void preview(const css::uno::Reference< css::animations::XAnimationNode > &xAnimationNode)
void onPreview(bool bForcePreview)
std::unique_ptr< weld::Button > mxPBAddEffect
std::unique_ptr< weld::Label > mxFTDuration
std::unique_ptr< weld::Label > mxFTCategory
void changeSelection(STLPropertySet const *pResultSet, STLPropertySet const *pOldSet)
std::unique_ptr< weld::Button > mxPBPlay
std::unique_ptr< SdPropertySubControl > mxLBSubControl
static bool setProperty1Value(sal_Int32 nType, const CustomAnimationEffectPtr &pEffect, const css::uno::Any &rValue)
virtual void onDoubleClick() override
sal_Int32 fillAnimationLB(bool bHasText)
std::unique_ptr< CustomAnimationList > mxCustomAnimationList
std::unique_ptr< weld::Label > mxFTProperty
MotionPathTagVector maMotionPathTags
Timer maLateInitTimer
The CustomAnimationPresets is initialized either on demand or after a short time after the constructi...
static sal_Int32 const gnMotionPathPos
virtual void onSelect() override
std::unique_ptr< weld::MetricSpinButton > mxMFStartDelay
void showOptions(const OUString &sPage={})
css::uno::Reference< css::drawing::XDrawView > mxView
std::unique_ptr< weld::Label > mxFTStart
std::unique_ptr< weld::Button > mxPBMoveUp
std::unique_ptr< weld::Label > mxFTStartDelay
std::unique_ptr< STLPropertySet > createSelectionSet()
css::uno::Reference< css::drawing::XDrawPage > mxCurrentPage
std::unique_ptr< weld::ComboBox > mxLBStart
std::unique_ptr< weld::Label > mxFTAnimation
std::unique_ptr< weld::Button > mxPBRemoveEffect
void implControlHdl(const weld::Widget *pControl)
this link is called when one of the controls is modified
void updatePathFromMotionPathTag(const rtl::Reference< MotionPathTag > &xTag)
std::unique_ptr< weld::CheckButton > mxCBAutoPreview
std::unique_ptr< weld::Button > mxPBMoveDown
std::unique_ptr< weld::ComboBox > mxLBCategory
std::unique_ptr< weld::Button > mxPBPropertyMore
std::unique_ptr< weld::Label > mxFTEffect
CustomAnimationPane(weld::Widget *pParent, ViewShellBase &rBase)
std::unique_ptr< weld::Container > mxPlaceholderBox
void remove(CustomAnimationEffectPtr const &pEffect)
virtual void onContextMenu(const OUString &rIdent) override
virtual css::ui::LayoutSize GetHeightForWidth(const sal_Int32 nWidth) override
static css::uno::Any getProperty1Value(sal_Int32 nType, const CustomAnimationEffectPtr &pEffect)
SAL_DLLPRIVATE const PresetCategoryList & getEmphasisPresets() const
SAL_DLLPRIVATE void changePresetSubType(const CustomAnimationEffectPtr &pEffect, const OUString &rPresetSubType) const
SAL_DLLPRIVATE const PresetCategoryList & getMotionPathsPresets() const
SAL_DLLPRIVATE const PresetCategoryList & getExitPresets() const
CustomAnimationPresetPtr getEffectDescriptor(const OUString &rPresetId) const
static const CustomAnimationPresets & getCustomAnimationPresets()
This method gets presets instance, which is localized for the current user's locale.
SAL_DLLPRIVATE const PresetCategoryList & getMiscPresets() const
SAL_DLLPRIVATE const PresetCategoryList & getEntrancePresets() const
virtual SfxUndoManager * GetUndoManager() override
Definition: docshell.cxx:363
virtual void SetModified(bool=true) override
Definition: docshell.cxx:421
SdDrawDocument * GetDoc()
Base class of the stacked shells that provide graphical views to Draw and Impress documents and editi...
DrawView * GetDrawView() const
Derivative of sd::View; contains also a pointer to the document.
Definition: drawview.hxx:35
SAL_DLLPRIVATE void setTextGroupingAuto(const CustomAnimationTextGroupPtr &pTextGroup, double fTextGroupingAuto)
SAL_DLLPRIVATE void replace(const CustomAnimationEffectPtr &pEffect, const CustomAnimationPresetPtr &pDescriptor, double fDuration)
SAL_DLLPRIVATE sal_Int32 getSequenceType() const
SAL_DLLPRIVATE const css::uno::Reference< css::drawing::XShape > & getTriggerShape() const
SAL_DLLPRIVATE void setTextGrouping(const CustomAnimationTextGroupPtr &pTextGroup, sal_Int32 nTextGrouping)
SAL_DLLPRIVATE EffectSequence::iterator find(const CustomAnimationEffectPtr &pEffect)
CustomAnimationTextGroupPtr createTextGroup(const CustomAnimationEffectPtr &pEffect, sal_Int32 nTextGrouping, double fTextGroupingAuto, bool bAnimateForm, bool bTextReverse)
SAL_DLLPRIVATE void setTextReverse(const CustomAnimationTextGroupPtr &pTextGroup, bool bAnimateForm)
SAL_DLLPRIVATE EffectSequence & getSequence()
SAL_DLLPRIVATE CustomAnimationTextGroupPtr findGroup(sal_Int32 nGroupId)
SAL_DLLPRIVATE void setAnimateForm(const CustomAnimationTextGroupPtr &pTextGroup, bool bAnimateForm)
SAL_DLLPRIVATE void remove(const CustomAnimationEffectPtr &pEffect)
Base class for all functions.
STLPropertyState getPropertyState(sal_Int32 nHandle) const
css::uno::Any getPropertyValue(sal_Int32 nHandle) const
bool isLocked() const
Definition: scopelock.hxx:32
static std::unique_ptr< SdPropertySubControl > create(sal_Int32 nType, weld::Label *pLabel, weld::Container *pParent, weld::Window *pTopLevel, const css::uno::Any &rValue, const OUString &rPresetId, const Link< LinkParamNone *, void > &rModifyHdl)
static void Stop(ViewShellBase const &rBase)
Definition: slideshow.cxx:201
static bool StartPreview(ViewShellBase const &rBase, const css::uno::Reference< css::drawing::XDrawPage > &xDrawPage, const css::uno::Reference< css::animations::XAnimationNode > &xAnimationNode)
Definition: slideshow.cxx:189
SfxViewShell descendant that the stacked Draw/Impress shells are based on.
std::shared_ptr< ViewShell > GetMainViewShell() const
Return the main view shell stacked on the called ViewShellBase object.
std::shared_ptr< tools::EventMultiplexer > const & GetEventMultiplexer() const
Return an event multiplexer.
DrawDocShell * GetDocShell() const
SD_DLLPUBLIC SfxViewFrame * GetViewFrame() const
Definition: viewshel.cxx:118
void updateHandles()
Definition: sdview.cxx:1122
void append_text(const OUString &rStr)
static bool runAsync(const std::shared_ptr< DialogController > &rController, const std::function< void(sal_Int32)> &)
virtual void set_text_align(int row, double fAlign, int col)=0
void append_text(const OUString &rStr)
virtual int n_children() const=0
virtual void set_text_emphasis(int row, bool bOn, int col)=0
int nCount
#define DBG_ASSERT(sCon, aError)
#define TOOLS_WARN_EXCEPTION(area, stream)
SVXCORE_DLLPUBLIC OUString SvxResId(TranslateId aId)
float u
OUString aUIName
FilterGroup & rTarget
FieldUnit
sal_Int32 nIndex
sal_Int64 n
sal_uInt16 nPos
@ Exception
enum SAL_DLLPUBLIC_RTTI FillStyle
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
const sal_Int32 nHandleEnd
std::list< CustomAnimationEffectPtr > EffectSequence
const sal_Int32 nPropertyTypeFillColor
const sal_Int32 nHandleTrigger
static void addValue(const std::unique_ptr< STLPropertySet > &pSet, sal_Int32 nHandle, const Any &rValue)
const sal_Int32 nPropertyTypeDirection
const sal_Int32 nHandleProperty1Type
IMPL_LINK_NOARG(MainSequence, onTimerHdl, Timer *, void)
const sal_Int32 nHandleIterateType
const sal_Int32 nPropertyTypeAutoReverse
const sal_Int32 nHandleRepeat
const sal_Int32 nPropertyTypeZoom
const sal_Int32 nPropertyTypeScale
void fillRepeatComboBox(weld::ComboBox &rBox)
static bool hasVisibleShape(const Reference< XShape > &xShape)
const sal_Int32 nPropertyTypeFont
const sal_Int32 nHandleCurrentPage
const sal_Int32 nPropertyTypeSpokes
const sal_Int32 nPropertyTypeColorStyle
std::shared_ptr< MainSequence > MainSequencePtr
const sal_Int32 nHandleBegin
const sal_Int32 nPropertyTypeCharHeightStyle
const sal_Int32 nPropertyTypeSecondColor
std::vector< PresetCategoryPtr > PresetCategoryList
const sal_Int32 nHandleDimColor
const sal_Int32 nPropertyTypeLineColor
std::shared_ptr< CustomAnimationTextGroup > CustomAnimationTextGroupPtr
std::vector< rtl::Reference< MotionPathTag > > MotionPathTagVector
std::shared_ptr< InteractiveSequence > InteractiveSequencePtr
std::shared_ptr< CustomAnimationPreset > CustomAnimationPresetPtr
const sal_Int32 nHandleAccelerate
const sal_Int32 nHandleSoundVolume
const sal_Int32 nPropertyTypeColor
const sal_Int32 nHandleAfterEffectOnNextEffect
const sal_Int32 nHandlePresetId
const sal_Int32 nHandleSoundURL
const sal_Int32 nHandleTextGroupingAuto
const sal_Int32 nHandleDecelerate
const sal_Int32 nHandleTextGrouping
const sal_Int32 nPropertyTypeFirstColor
const sal_Int32 nHandleIterateInterval
const sal_Int32 nHandleStart
const sal_Int32 nHandleHasVisibleShape
OUString getPropertyName(sal_Int32 nPropertyType)
IMPL_LINK(SdCharHeightPropertyBox, implMenuSelectHdl, const OUString &, rIdent, void)
std::shared_ptr< CustomAnimationEffect > CustomAnimationEffectPtr
static bool updateMotionPathImpl(CustomAnimationPane &rPane, ::sd::View &rView, EffectSequence::iterator aIter, const EffectSequence::iterator &aEnd, MotionPathTagVector &rOldTags, MotionPathTagVector &rNewTags)
std::shared_ptr< PresetCategory > PresetCategoryPtr
const sal_Int32 nPropertyTypeCharDecoration
const sal_Int32 nHandleHasText
const sal_Int32 nPropertyTypeCharHeight
const sal_Int32 nHandleAutoReverse
const sal_Int32 nHandleRewind
const sal_Int32 nHandleMaxParaDepth
const sal_Int32 nHandleProperty1Value
const sal_Int32 nPropertyTypeRotate
static bool getTextSelection(const Any &rSelection, Reference< XShape > &xShape, std::vector< sal_Int16 > &rParaList)
const sal_Int32 nHandleDuration
const sal_Int32 nPropertyTypeAccelerate
const sal_Int32 nHandleTextReverse
const sal_Int32 nPropertyTypeCharColor
const sal_Int32 nHandleAnimateForm
const sal_Int32 nPropertyTypeDecelerate
const sal_Int32 nPropertyTypeNone
const sal_Int32 nHandleHasAfterEffect
static sal_Int32 getPropertyType(std::u16string_view rProperty)
const sal_Int32 nPropertyTypeTransparency
static sal_Int32 calcMaxParaDepth(const Reference< XShape > &xTargetShape)
OUString toId(const void *pValue)
QPRO_FUNC_TYPE nType
sal_Int32 nHandle
OUString SdResId(TranslateId aId)
Definition: sdmod.cxx:83
#define SD_MOD()
Definition: sdmod.hxx:184
uno::Reference< presentation::XSlideShowView > mxView
OUString sId