xref: /AOO41X/main/sd/source/ui/animations/CustomAnimationPane.cxx (revision b862c97c327d912ac6f569bb343850715f80ed9c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sd.hxx"
26 
27 #include <com/sun/star/presentation/EffectPresetClass.hpp>
28 #include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
29 #include <com/sun/star/view/XSelectionSupplier.hpp>
30 #include <com/sun/star/drawing/XDrawView.hpp>
31 #include <com/sun/star/drawing/XShape.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/presentation/EffectNodeType.hpp>
34 #include <com/sun/star/presentation/EffectCommands.hpp>
35 #include <com/sun/star/animations/AnimationTransformType.hpp>
36 #include <com/sun/star/text/XTextRangeCompare.hpp>
37 #include <com/sun/star/container/XEnumerationAccess.hpp>
38 #include <com/sun/star/container/XIndexAccess.hpp>
39 #include <com/sun/star/presentation/ParagraphTarget.hpp>
40 #include <com/sun/star/text/XText.hpp>
41 #include <com/sun/star/awt/XWindow.hpp>
42 #include <com/sun/star/drawing/LineStyle.hpp>
43 #include <com/sun/star/drawing/FillStyle.hpp>
44 #include <comphelper/processfactory.hxx>
45 #include <sfx2/dispatch.hxx>
46 #include "STLPropertySet.hxx"
47 #include "CustomAnimationPane.hxx"
48 #include "CustomAnimationDialog.hxx"
49 #include "CustomAnimationCreateDialog.hxx"
50 #include "CustomAnimationPane.hrc"
51 #include "CustomAnimation.hrc"
52 #include "CustomAnimationList.hxx"
53 #include <vcl/lstbox.hxx>
54 #include <vcl/fixed.hxx>
55 
56 #include <vcl/button.hxx>
57 #include <vcl/combobox.hxx>
58 #include <vcl/scrbar.hxx>
59 
60 #include <comphelper/sequence.hxx>
61 #include <sfx2/frame.hxx>
62 #include <sfx2/sidebar/Theme.hxx>
63 
64 #include <svx/unoapi.hxx>
65 #include <svx/svxids.hrc>
66 #include <DrawDocShell.hxx>
67 #include <ViewShellBase.hxx>
68 #include "DrawViewShell.hxx"
69 #include "DrawController.hxx"
70 #include "sdresid.hxx"
71 #include "drawview.hxx"
72 #include "slideshow.hxx"
73 #include "undoanim.hxx"
74 #include "optsitem.hxx"
75 #include "sddll.hxx"
76 #include "framework/FrameworkHelper.hxx"
77 
78 #include "EventMultiplexer.hxx"
79 #include "DialogListBox.hxx"
80 
81 #include "glob.hrc"
82 #include "sdpage.hxx"
83 #include "drawdoc.hxx"
84 #include "app.hrc"
85 
86 #include <memory>
87 #include <algorithm>
88 
89 #include <basegfx/polygon/b2dpolypolygontools.hxx>
90 #include <basegfx/matrix/b2dhommatrix.hxx>
91 #include <basegfx/range/b2drange.hxx>
92 
93 using namespace ::com::sun::star;
94 using namespace ::com::sun::star::animations;
95 using namespace ::com::sun::star::presentation;
96 using namespace ::com::sun::star::text;
97 
98 using ::rtl::OUString;
99 using namespace ::com::sun::star::uno;
100 using namespace ::com::sun::star::drawing;
101 using ::com::sun::star::view::XSelectionSupplier;
102 using ::com::sun::star::view::XSelectionChangeListener;
103 using ::com::sun::star::frame::XController;
104 using ::com::sun::star::frame::XModel;
105 using ::com::sun::star::beans::XPropertySet;
106 using ::com::sun::star::beans::XPropertyChangeListener;
107 using ::com::sun::star::container::XIndexAccess;
108 using ::com::sun::star::container::XEnumerationAccess;
109 using ::com::sun::star::container::XEnumeration;
110 using ::com::sun::star::text::XText;
111 using ::sd::framework::FrameworkHelper;
112 
113 namespace sd {
114 
115 // --------------------------------------------------------------------
116 
fillDurationComboBox(ComboBox * pBox)117 void fillDurationComboBox( ComboBox* pBox )
118 {
119     static const double gdVerySlow = 5.0;
120     static const double gdSlow = 3.0;
121     static const double gdNormal = 2.0;
122     static const double gdFast = 1.0;
123     static const double gdVeryFast = 0.5;
124 
125     String aVerySlow( SdResId( STR_CUSTOMANIMATION_DURATION_VERY_SLOW ) );
126     pBox->SetEntryData( pBox->InsertEntry( aVerySlow ), (void*)&gdVerySlow );
127 
128     String aSlow( SdResId( STR_CUSTOMANIMATION_DURATION_SLOW ) );
129     pBox->SetEntryData( pBox->InsertEntry( aSlow ), (void*)&gdSlow );
130 
131     String aNormal( SdResId( STR_CUSTOMANIMATION_DURATION_NORMAL ) );
132     pBox->SetEntryData( pBox->InsertEntry( aNormal ), (void*)&gdNormal );
133 
134     String aFast( SdResId( STR_CUSTOMANIMATION_DURATION_FAST ) );
135     pBox->SetEntryData( pBox->InsertEntry( aFast ), (void*)&gdFast );
136 
137     String aVeryFast( SdResId( STR_CUSTOMANIMATION_DURATION_VERY_FAST ) );
138     pBox->SetEntryData( pBox->InsertEntry( aVeryFast ), (void*)&gdVeryFast );
139 }
140 
fillRepeatComboBox(ComboBox * pBox)141 void fillRepeatComboBox( ComboBox* pBox )
142 {
143     String aNone( SdResId( STR_CUSTOMANIMATION_REPEAT_NONE ) );
144     pBox->SetEntryData( pBox->InsertEntry( aNone ), (void*)((sal_Int32)0) );
145 
146     pBox->SetEntryData( pBox->InsertEntry( String::CreateFromInt32( 2 ) ), (void*)((sal_Int32)1) );
147     pBox->SetEntryData( pBox->InsertEntry( String::CreateFromInt32( 3 ) ), (void*)((sal_Int32)3) );
148     pBox->SetEntryData( pBox->InsertEntry( String::CreateFromInt32( 4 ) ), (void*)((sal_Int32)4) );
149     pBox->SetEntryData( pBox->InsertEntry( String::CreateFromInt32( 5 ) ), (void*)((sal_Int32)5) );
150     pBox->SetEntryData( pBox->InsertEntry( String::CreateFromInt32( 10 ) ), (void*)((sal_Int32)10) );
151 
152     String aUntilClick( SdResId( STR_CUSTOMANIMATION_REPEAT_UNTIL_NEXT_CLICK ) );
153     pBox->SetEntryData( pBox->InsertEntry( aUntilClick ), (void*)((sal_Int32)-1) );
154 
155     String aEndOfSlide( SdResId( STR_CUSTOMANIMATION_REPEAT_UNTIL_END_OF_SLIDE ) );
156     pBox->SetEntryData( pBox->InsertEntry( aEndOfSlide ), (void*)((sal_Int32)-2) );
157 }
158 
159 // --------------------------------------------------------------------
160 
CustomAnimationPane(::Window * pParent,ViewShellBase & rBase,const Size & rMinSize)161 CustomAnimationPane::CustomAnimationPane( ::Window* pParent, ViewShellBase& rBase, const Size& rMinSize )
162 :   Control( pParent, SdResId(DLG_CUSTOMANIMATIONPANE) ),
163     mrBase( rBase ),
164     mpCustomAnimationPresets(NULL),
165     mnPropertyType( nPropertyTypeNone ),
166     maMinSize( rMinSize ),
167     mxModel( rBase.GetDocShell()->GetDoc()->getUnoModel(), UNO_QUERY ),
168     maLateInitTimer()
169 {
170     // load resources
171     mpFLEffect = new FixedLine( this, SdResId( FL_EFFECT ) );
172 
173     mpPBAddEffect = new PushButton( this, SdResId( PB_ADD_EFFECT ) );
174     mpPBChangeEffect = new PushButton( this, SdResId( PB_CHANGE_EFFECT ) );
175     mpPBRemoveEffect = new PushButton( this, SdResId( PB_REMOVE_EFFECT ) );
176 
177     mpFLModify = new FixedLine( this, SdResId( FL_MODIFY ) );
178 
179     mpFTStart = new FixedText( this, SdResId( FT_START ) );
180     mpLBStart = new ListBox( this, SdResId( LB_START ) );
181     mpFTProperty = new FixedText( this, SdResId( FT_PROPERTY ) );
182     mpLBProperty = new PropertyControl( this, SdResId( LB_PROPERTY ) );
183     mpPBPropertyMore = new PushButton( this, SdResId( PB_PROPERTY_MORE ) );
184 
185     mpFTSpeed = new FixedText( this, SdResId( FT_SPEED ) );
186     mpCBSpeed = new ComboBox( this, SdResId( CB_SPEED ) );
187 
188     mpCustomAnimationList = new CustomAnimationList( this, SdResId( CT_CUSTOM_ANIMATION_LIST ), this );
189 
190     mpPBMoveUp = new PushButton( this, SdResId( PB_MOVE_UP ) );
191     mpPBMoveDown = new PushButton( this, SdResId( PB_MOVE_DOWN ) );
192     mpFTChangeOrder = new FixedText( this, SdResId( FT_CHANGE_ORDER ) );
193     mpFLSeperator1 = new FixedLine( this, SdResId( FL_SEPERATOR1 ) );
194     mpPBPlay = new PushButton( this, SdResId( PB_PLAY ) );
195     mpPBSlideShow = new PushButton( this, SdResId( PB_SLIDE_SHOW ) );
196     mpFLSeperator2 = new FixedLine( this, SdResId( FL_SEPERATOR2 ) );
197     mpCBAutoPreview = new CheckBox( this, SdResId( CB_AUTOPREVIEW ) );
198 
199     maStrProperty = mpFTProperty->GetText();
200 
201     FreeResource();
202 
203     // use bold font for group headings (same font for all fixed lines):
204     Font font( mpFLEffect->GetFont() );
205     font.SetWeight( WEIGHT_BOLD );
206     mpFLEffect->SetFont( font );
207     mpFLModify->SetFont( font );
208 
209     fillDurationComboBox( mpCBSpeed );
210     mpPBMoveUp->SetSymbol( SYMBOL_ARROW_UP );
211     mpPBMoveDown->SetSymbol( SYMBOL_ARROW_DOWN );
212 
213     mpPBAddEffect->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
214     mpPBChangeEffect->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
215     mpPBRemoveEffect->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
216     mpLBStart->SetSelectHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
217     mpCBSpeed->SetSelectHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
218     mpPBPropertyMore->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
219     mpPBMoveUp->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
220     mpPBMoveDown->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
221     mpPBPlay->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
222     mpPBSlideShow->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
223     mpCBAutoPreview->SetClickHdl( LINK( this, CustomAnimationPane, implControlHdl ) );
224 
225     maStrModify = mpFLEffect->GetText();
226 
227     // resize controls according to current size
228     updateLayout();
229 
230     // get current controller and initialize listeners
231     try
232     {
233         mxView = Reference< XDrawView >::query(mrBase.GetController());
234         addListener();
235     }
236     catch( Exception& e )
237     {
238         (void)e;
239         DBG_ERROR( "sd::CustomAnimationPane::CustomAnimationPane(), Exception cought!" );
240     }
241 
242     // get current page and update custom animation list
243     onChangeCurrentPage();
244 
245     // Wait a short time before the presets list is created.  This gives the
246     // system time to paint the control.
247     maLateInitTimer.SetTimeout(100);
248     maLateInitTimer.SetTimeoutHdl(LINK(this, CustomAnimationPane, lateInitCallback));
249     maLateInitTimer.Start();
250 
251     UpdateLook();
252 }
253 
~CustomAnimationPane()254 CustomAnimationPane::~CustomAnimationPane()
255 {
256     maLateInitTimer.Stop();
257 
258     removeListener();
259 
260     MotionPathTagVector aTags;
261     aTags.swap( maMotionPathTags );
262     MotionPathTagVector::iterator aIter;
263     for( aIter = aTags.begin(); aIter != aTags.end(); aIter++ )
264         (*aIter)->Dispose();
265 
266     delete mpFLModify;
267     delete mpPBAddEffect;
268     delete mpPBChangeEffect;
269     delete mpPBRemoveEffect;
270     delete mpFLEffect;
271     delete mpFTStart;
272     delete mpLBStart;
273     delete mpFTProperty;
274     delete mpLBProperty;
275     delete mpPBPropertyMore;
276     delete mpFTSpeed;
277     delete mpCBSpeed;
278     delete mpCustomAnimationList;
279     delete mpFTChangeOrder;
280     delete mpPBMoveUp;
281     delete mpPBMoveDown;
282     delete mpFLSeperator1;
283     delete mpPBPlay;
284     delete mpPBSlideShow;
285     delete mpFLSeperator2;
286     delete mpCBAutoPreview;
287 }
288 
addUndo()289 void CustomAnimationPane::addUndo()
290 {
291     ::svl::IUndoManager* pManager = mrBase.GetDocShell()->GetUndoManager();
292     if( pManager )
293     {
294         SdPage* pPage = SdPage::getImplementation( mxCurrentPage );
295         if( pPage )
296             pManager->AddUndoAction( new UndoAnimation( mrBase.GetDocShell()->GetDoc(), pPage ) );
297     }
298 }
299 
Resize()300 void CustomAnimationPane::Resize()
301 {
302     updateLayout();
303 }
304 
StateChanged(StateChangedType nStateChange)305 void CustomAnimationPane::StateChanged( StateChangedType nStateChange )
306 {
307     Control::StateChanged( nStateChange );
308 
309     if( nStateChange == STATE_CHANGE_VISIBLE )
310         updateMotionPathTags();
311 }
312 
KeyInput(const KeyEvent & rKEvt)313 void CustomAnimationPane::KeyInput( const KeyEvent& rKEvt )
314 {
315     if( mpCustomAnimationList )
316         mpCustomAnimationList->KeyInput( rKEvt );
317 }
318 
addListener()319 void CustomAnimationPane::addListener()
320 {
321     Link aLink( LINK(this,CustomAnimationPane,EventMultiplexerListener) );
322     mrBase.GetEventMultiplexer()->AddEventListener (
323         aLink,
324         tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION
325         | tools::EventMultiplexerEvent::EID_CURRENT_PAGE
326         | tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
327         | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
328         | tools::EventMultiplexerEvent::EID_DISPOSING
329         | tools::EventMultiplexerEvent::EID_END_TEXT_EDIT);
330 }
331 
removeListener()332 void CustomAnimationPane::removeListener()
333 {
334     Link aLink( LINK(this,CustomAnimationPane,EventMultiplexerListener) );
335     mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
336 }
337 
IMPL_LINK(CustomAnimationPane,EventMultiplexerListener,tools::EventMultiplexerEvent *,pEvent)338 IMPL_LINK(CustomAnimationPane,EventMultiplexerListener,
339     tools::EventMultiplexerEvent*,pEvent)
340 {
341     switch (pEvent->meEventId)
342     {
343         case tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION:
344             onSelectionChanged();
345             break;
346 
347         case tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
348             onChangeCurrentPage();
349             break;
350 
351         case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
352             // At this moment the controller may not yet been set at model
353             // or ViewShellBase.  Take it from the view shell passed with
354             // the event.
355             if( bool(mrBase.GetMainViewShell()) )
356             {
357                 if( mrBase.GetMainViewShell()->GetShellType() == ViewShell::ST_IMPRESS )
358                 {
359                     mxView = Reference<XDrawView>::query(mrBase.GetDrawController());
360                     onSelectionChanged();
361                     onChangeCurrentPage();
362                     break;
363                 }
364             }
365         // fall through intended
366         case tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
367             mxView = 0;
368             mxCurrentPage = 0;
369             updateControls();
370             break;
371 
372         case tools::EventMultiplexerEvent::EID_DISPOSING:
373             mxView = Reference<XDrawView>();
374             onSelectionChanged();
375             onChangeCurrentPage();
376             break;
377         case tools::EventMultiplexerEvent::EID_END_TEXT_EDIT:
378             if( mpMainSequence.get() && pEvent->mpUserData )
379                 mpCustomAnimationList->update( mpMainSequence );
380             break;
381     }
382     return 0;
383 }
384 
385 
updateLayout()386 void CustomAnimationPane::updateLayout()
387 {
388     Size aPaneSize( GetSizePixel() );
389     if( aPaneSize.Width() < maMinSize.Width() )
390         aPaneSize.Width() = maMinSize.Width();
391 
392     if( aPaneSize.Height() < maMinSize.Height() )
393         aPaneSize.Height() = maMinSize.Height();
394 
395     Point aOffset( LogicToPixel( Point(3,3), MAP_APPFONT ) );
396     Point aCursor( aOffset );
397 
398     // place the modify fixed line
399 
400     // place the "modify effect" fixed line
401     Size aSize( mpFLModify->GetSizePixel() );
402     aSize.Width() = aPaneSize.Width() - 2 * aOffset.X();
403 
404     mpFLModify->SetPosSizePixel( aCursor, aSize );
405 
406     aCursor.Y() += aSize.Height() + aOffset.Y();
407 
408     const int nButtonExtraWidth = 4 * aOffset.X();
409 
410     // the "add effect" button is placed top-left
411     Size aCtrlSize( mpPBAddEffect->GetSizePixel() );
412     aCtrlSize.setWidth( mpPBAddEffect->CalcMinimumSize( aSize.Width() ).getWidth() + nButtonExtraWidth );
413     mpPBAddEffect->SetPosSizePixel( aCursor, aCtrlSize );
414 
415     aCursor.X() += aOffset.X() + aCtrlSize.Width();
416 
417     // place the "change effect" button
418 
419     // if the "change" button does not fit right of the "add effect", put it on the next line
420     aCtrlSize = mpPBChangeEffect->GetSizePixel();
421     aCtrlSize.setWidth( mpPBChangeEffect->CalcMinimumSize( aSize.Width() ).getWidth() + nButtonExtraWidth );
422     if( ( aCursor.X() + aCtrlSize.Width() + aOffset.X() ) > aPaneSize.Width() )
423     {
424         aCursor.X() = aOffset.X();
425         aCursor.Y() += aCtrlSize.Height() + aOffset.Y();
426     }
427     mpPBChangeEffect->SetPosSizePixel( aCursor, aCtrlSize );
428 
429     aCursor.X() += aOffset.X() + aCtrlSize.Width();
430 
431     // place the "remove effect" button
432 
433     // if the "remove" button does not fit right of the "add effect", put it on the next line
434     aCtrlSize = mpPBRemoveEffect->GetSizePixel();
435     aCtrlSize.setWidth( mpPBRemoveEffect->CalcMinimumSize( aSize.Width() ).getWidth() + nButtonExtraWidth );
436     if( ( aCursor.X() + aCtrlSize.Width() + aOffset.X() ) > aPaneSize.Width() )
437     {
438         aCursor.X() = aOffset.X();
439         aCursor.Y() += aCtrlSize.Height() + aOffset.Y();
440     }
441 
442     mpPBRemoveEffect->SetPosSizePixel( aCursor, aCtrlSize );
443 
444     aCursor.X() = aOffset.X();
445     aCursor.Y() += aCtrlSize.Height() + 2 * aOffset.Y();
446 
447     // place the "modify effect" fixed line
448     aSize = mpFLEffect->GetSizePixel();
449     aSize.Width() = aPaneSize.Width() - 2 * aOffset.X();
450 
451     mpFLEffect->SetPosSizePixel( aCursor, aSize );
452 
453     aCursor.Y() += aSize.Height() + aOffset.Y();
454 
455     // ---------------------------------------------------------------------------
456     // place the properties controls
457 
458     // calc minimum width for fixedtext
459 
460     Size aFixedTextSize( mpFTStart->CalcMinimumSize() );
461     long nWidth = aFixedTextSize.Width();
462     aFixedTextSize = mpFTProperty->CalcMinimumSize();
463     nWidth = std::max( nWidth, aFixedTextSize.Width() );
464     aFixedTextSize = mpFTSpeed->CalcMinimumSize();
465     aFixedTextSize.Width() = std::max( nWidth, aFixedTextSize.Width() ) + aOffset.X();
466     mpFTStart->SetSizePixel(aFixedTextSize);
467     mpFTProperty->SetSizePixel(aFixedTextSize);
468     mpFTSpeed->SetSizePixel(aFixedTextSize);
469 
470     aSize = mpPBPropertyMore->GetSizePixel();
471 
472     // place the "start" fixed text
473 
474     Point aFTPos( aCursor );
475     Point aLBPos( aCursor );
476     Size aListBoxSize( LogicToPixel( Size( 60, 12 ), MAP_APPFONT ) );
477     long nDeltaY = aListBoxSize.Height() + aOffset.Y();
478 
479     // linebreak?
480     if( (aFixedTextSize.Width() + aListBoxSize.Width() + aSize.Width() + 4 * aOffset.X()) > aPaneSize.Width() )
481     {
482         // y position for list box is below fixed text
483         aLBPos.Y() += aFixedTextSize.Height() + aOffset.Y();
484 
485         // height of fixed text + list box + something = 2 * list box
486         nDeltaY = aListBoxSize.Height() +  aFixedTextSize.Height() + 2*aOffset.Y();
487     }
488     else
489     {
490         // x position for list box is right of fixed text
491         aLBPos.X() += aFixedTextSize.Width() + aOffset.X();
492 
493         if( aListBoxSize.Height() > aFixedTextSize.Height() )
494             aFTPos.Y() = aLBPos.Y() + ((aListBoxSize.Height() - aFixedTextSize.Height()) >> 1);
495         else
496             aLBPos.Y() = aFTPos.Y() + ((aFixedTextSize.Height() - aListBoxSize.Height()) >> 1);
497     }
498 
499     // width of the listbox is from its left side until end of pane
500     aListBoxSize.Width() = aPaneSize.Width() - aLBPos.X() - aSize.Width() - 2 * aOffset.X();
501 
502     mpFTStart->SetPosPixel( aFTPos );
503     mpLBStart->SetPosSizePixel( aLBPos, aListBoxSize );
504 
505     aFTPos.Y() += nDeltaY; aLBPos.Y() += nDeltaY;
506 
507     mpFTProperty->SetPosPixel( aFTPos );
508     mpLBProperty->SetPosSizePixel( aLBPos, aListBoxSize );
509     mpLBProperty->Resize();
510 
511     Point aMorePos( aLBPos );
512     aMorePos.X() += aListBoxSize.Width() + aOffset.X();
513     mpPBPropertyMore->SetPosPixel( aMorePos );
514 
515     aFTPos.Y() += nDeltaY; aLBPos.Y() += nDeltaY;
516 
517     mpFTSpeed->SetPosPixel( aFTPos );
518     mpCBSpeed->SetPosSizePixel( aLBPos, aListBoxSize );
519 
520     aFTPos.Y() += nDeltaY + aOffset.Y();
521 
522     Point aListPos( aFTPos );
523 
524     // positionate the buttons on the bottom
525 
526     // place the auto preview checkbox
527     aCursor = Point( aOffset.X(), aPaneSize.Height() - mpCBAutoPreview->GetSizePixel().Height() - aOffset.Y() );
528     mpCBAutoPreview->SetPosPixel( aCursor );
529 
530     // place the seperator 2 fixed line
531     aCursor.Y() -= /* aOffset.Y() + */ mpFLSeperator2->GetSizePixel().Height();
532     aSize = mpFLSeperator2->GetSizePixel();
533     aSize.Width() = aPaneSize.Width() - 2 * aOffset.X();
534     mpFLSeperator2->SetPosSizePixel( aCursor, aSize );
535 
536     // next, layout and place the play and slide show buttons
537     aCtrlSize = mpPBSlideShow->GetSizePixel();
538     aCtrlSize.setWidth( mpPBSlideShow->CalcMinimumSize( aSize.Width() ).getWidth() + nButtonExtraWidth );
539 
540     Size aPlaySize( mpPBPlay->GetSizePixel() );
541     aPlaySize.setWidth( mpPBPlay->CalcMinimumSize( aSize.Width() ).getWidth() + nButtonExtraWidth );
542 
543     aCursor.Y() -= aCtrlSize.Height() /* + aOffset.Y() */;
544 
545     // do we need two lines for the buttons?
546     int aTestWidth = aCursor.X() + mpPBPlay->GetSizePixel().Width() + 2 * aOffset.X() + mpPBSlideShow->GetSizePixel().Width();
547     if( aTestWidth > aPaneSize.Width() )
548     {
549         mpPBSlideShow->SetPosSizePixel( aCursor, aCtrlSize );
550         aCursor.Y() -= aCtrlSize.Height() + aOffset.Y();
551         mpPBPlay->SetPosSizePixel( aCursor, aPlaySize );
552     }
553     else
554     {
555         mpPBPlay->SetPosSizePixel( aCursor, aPlaySize );
556         aCursor.X() += aPlaySize.Width() + aOffset.X();
557         mpPBSlideShow->SetPosSizePixel( aCursor, aCtrlSize );
558     }
559 
560     // place the seperator 1 fixed line
561     aCursor.X() = aOffset.X();
562     aCursor.Y() -= /* aOffset.Y() + */ mpFLSeperator1->GetSizePixel().Height();
563     aSize = mpFLSeperator1->GetSizePixel();
564     aSize.Width() = aPaneSize.Width() - 2 * aOffset.X();
565     mpFLSeperator1->SetPosSizePixel( aCursor, aSize );
566 
567     // place the move down button
568     aSize = mpPBMoveDown->GetSizePixel();
569 
570     aCursor.X() = aPaneSize.Width() - aOffset.X() - aSize.Width();
571     aCursor.Y() -= aOffset.Y() + aSize.Height();
572     mpPBMoveDown->SetPosPixel( aCursor );
573 
574     aCursor.X() -= aOffset.X() + aSize.Width();
575     mpPBMoveUp->SetPosPixel( aCursor );
576 
577     // Place the change order label.
578     // Its width has to be calculated dynamically so that is can be
579     // displayed flush right without having too much space to the buttons
580     // with some languages or truncated text with others.
581     mpFTChangeOrder->SetSizePixel(mpFTChangeOrder->CalcMinimumSize());
582 
583     aCursor.X() -= aOffset.X() + mpFTChangeOrder->GetSizePixel().Width();
584     aCursor.Y() += (aSize.Height() - mpFTChangeOrder->GetSizePixel().Height()) >> 1;
585     mpFTChangeOrder->SetPosPixel( aCursor );
586 
587     // positionate the custom animation list control
588     Size aCustomAnimationListSize( aPaneSize.Width() - aListPos.X() - aOffset.X(), aCursor.Y() - aListPos.Y() - 2 * aOffset.Y() );
589     mpCustomAnimationList->SetPosSizePixel( aListPos, aCustomAnimationListSize );
590 }
591 
getPropertyType(const OUString & rProperty)592 static sal_Int32 getPropertyType( const OUString& rProperty )
593 {
594     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Direction") ) )
595         return nPropertyTypeDirection;
596 
597     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Spokes") ) )
598         return nPropertyTypeSpokes;
599 
600     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Zoom") ) )
601         return nPropertyTypeZoom;
602 
603     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Accelerate") ) )
604         return nPropertyTypeAccelerate;
605 
606     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Decelerate") ) )
607         return nPropertyTypeDecelerate;
608 
609     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Color1") ) )
610         return nPropertyTypeFirstColor;
611 
612     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Color2") ) )
613         return nPropertyTypeSecondColor;
614 
615     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("FillColor") ) )
616         return nPropertyTypeFillColor;
617 
618     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ColorStyle") ) )
619         return nPropertyTypeColorStyle;
620 
621     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("AutoReverse") ) )
622         return nPropertyTypeAutoReverse;
623 
624     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("FontStyle") ) )
625         return nPropertyTypeFont;
626 
627     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CharColor") ) )
628         return nPropertyTypeCharColor;
629 
630     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CharHeight") ) )
631         return nPropertyTypeCharHeight;
632 
633     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CharDecoration") ) )
634         return nPropertyTypeCharDecoration;
635 
636     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("LineColor") ) )
637         return nPropertyTypeLineColor;
638 
639     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Rotate") ) )
640         return nPropertyTypeRotate;
641 
642     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Transparency") ) )
643         return nPropertyTypeTransparency;
644 
645     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Color") ) )
646         return nPropertyTypeColor;
647 
648     if( rProperty.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Scale") ) )
649         return nPropertyTypeScale;
650 
651     return nPropertyTypeNone;
652 }
653 
getPropertyName(sal_Int32 nPropertyType)654 OUString getPropertyName( sal_Int32 nPropertyType )
655 {
656     switch( nPropertyType )
657     {
658     case nPropertyTypeDirection:
659         return OUString( String( SdResId( STR_CUSTOMANIMATION_DIRECTION_PROPERTY ) ) );
660 
661     case nPropertyTypeSpokes:
662         return OUString( String( SdResId( STR_CUSTOMANIMATION_SPOKES_PROPERTY ) ) );
663 
664     case nPropertyTypeFirstColor:
665         return OUString( String( SdResId( STR_CUSTOMANIMATION_FIRST_COLOR_PROPERTY ) ) );
666 
667     case nPropertyTypeSecondColor:
668         return OUString( String( SdResId( STR_CUSTOMANIMATION_SECOND_COLOR_PROPERTY ) ) );
669 
670     case nPropertyTypeZoom:
671         return OUString( String( SdResId( STR_CUSTOMANIMATION_ZOOM_PROPERTY ) ) );
672 
673     case nPropertyTypeFillColor:
674         return OUString( String( SdResId( STR_CUSTOMANIMATION_FILL_COLOR_PROPERTY ) ) );
675 
676     case nPropertyTypeColorStyle:
677         return OUString( String( SdResId( STR_CUSTOMANIMATION_STYLE_PROPERTY ) ) );
678 
679     case nPropertyTypeFont:
680         return OUString( String( SdResId( STR_CUSTOMANIMATION_FONT_PROPERTY ) ) );
681 
682     case nPropertyTypeCharHeight:
683         return OUString( String( SdResId( STR_CUSTOMANIMATION_SIZE_PROPERTY ) ) );
684 
685     case nPropertyTypeCharColor:
686         return OUString( String( SdResId( STR_CUSTOMANIMATION_FONT_COLOR_PROPERTY ) ) );
687 
688     case nPropertyTypeCharHeightStyle:
689         return OUString( String( SdResId( STR_CUSTOMANIMATION_FONT_SIZE_STYLE_PROPERTY ) ) );
690 
691     case nPropertyTypeCharDecoration:
692         return OUString( String( SdResId( STR_CUSTOMANIMATION_FONT_STYLE_PROPERTY ) ) );
693 
694     case nPropertyTypeLineColor:
695         return OUString( String( SdResId( STR_CUSTOMANIMATION_LINE_COLOR_PROPERTY ) ) );
696 
697     case nPropertyTypeRotate:
698         return OUString( String( SdResId( STR_CUSTOMANIMATION_AMOUNT_PROPERTY ) ) );
699 
700     case nPropertyTypeColor:
701         return OUString( String( SdResId( STR_CUSTOMANIMATION_COLOR_PROPERTY ) ) );
702 
703     case nPropertyTypeTransparency:
704         return OUString( String( SdResId( STR_CUSTOMANIMATION_AMOUNT_PROPERTY ) ) );
705 
706     case nPropertyTypeScale:
707         return OUString( String( SdResId( STR_CUSTOMANIMATION_SCALE_PROPERTY ) ) );
708     }
709 
710     OUString aStr;
711     return aStr;
712 }
713 
updateControls()714 void CustomAnimationPane::updateControls()
715 {
716     mpFLModify->Enable( mxView.is() );
717     mpFTSpeed->Enable( mxView.is() );
718     mpCBSpeed->Enable( mxView.is() );
719     mpCustomAnimationList->Enable( mxView.is() );
720     mpFTChangeOrder->Enable( mxView.is() );
721     mpPBMoveUp->Enable( mxView.is() );
722     mpPBMoveDown->Enable( mxView.is() );
723     mpFLSeperator1->Enable( mxView.is() );
724     mpPBPlay->Enable( mxView.is() );
725     mpPBSlideShow->Enable( mxView.is() );
726     mpFLSeperator2->Enable( mxView.is() );
727     mpCBAutoPreview->Enable( mxView.is() );
728 
729     if( !mxView.is() )
730     {
731         mpPBAddEffect->Enable( sal_False );
732         mpPBChangeEffect->Enable( sal_False );
733         mpPBRemoveEffect->Enable( sal_False );
734         mpFLEffect->Enable( sal_False );
735         mpFTStart->Enable( sal_False );
736         mpLBStart->Enable( sal_False );
737         mpPBPropertyMore->Enable( sal_False );
738         mpLBProperty->Enable( sal_False );
739         mpFTProperty->Enable( sal_False );
740         mpCustomAnimationList->clear();
741         return;
742     }
743 
744     const int nSelectionCount = maListSelection.size();
745 
746     mpPBAddEffect->Enable( maViewSelection.hasValue() );
747     mpPBChangeEffect->Enable( nSelectionCount);
748     mpPBRemoveEffect->Enable(nSelectionCount);
749 
750     mpFLEffect->Enable(nSelectionCount > 0);
751     mpFTStart->Enable(nSelectionCount > 0);
752     mpLBStart->Enable(nSelectionCount > 0);
753     mpPBPropertyMore->Enable(nSelectionCount > 0);
754 
755 //  mpPBPlay->Enable(nSelectionCount > 0);
756 
757     mpFTProperty->SetText( maStrProperty );
758 
759     mnPropertyType = nPropertyTypeNone;
760 
761     if( nSelectionCount == 1 )
762     {
763         CustomAnimationEffectPtr pEffect = maListSelection.front();
764 
765         OUString aUIName( getPresets().getUINameForPresetId( pEffect->getPresetId() ) );
766 
767         OUString aTemp( maStrModify );
768 
769         if( aUIName.getLength() )
770         {
771             aTemp += OUString( (sal_Unicode)' ' );
772             aTemp += aUIName;
773         }
774         mpFLEffect->SetText( aTemp );
775 
776         CustomAnimationPresetPtr pDescriptor = getPresets().getEffectDescriptor( pEffect->getPresetId() );
777         if( pDescriptor.get() )
778         {
779             PropertySubControl* pSubControl = NULL;
780 
781             Any aValue;
782 
783             UStringList aProperties( pDescriptor->getProperties() );
784             if( aProperties.size() >= 1 )
785             {
786                 OUString aProperty( aProperties.front() );
787 
788                 mnPropertyType = getPropertyType( aProperties.front() );
789 
790                 mpFTProperty->SetText( getPropertyName( mnPropertyType )  );
791 
792                 aValue = getProperty1Value( mnPropertyType, pEffect );
793             }
794 
795             if( aValue.hasValue() )
796             {
797                 pSubControl = mpLBProperty->getSubControl();
798                 if( !pSubControl || (pSubControl->getControlType() != mnPropertyType) )
799                 {
800                     pSubControl = PropertySubControl::create( mnPropertyType, this, aValue, pEffect->getPresetId(), LINK( this, CustomAnimationPane, implPropertyHdl ) );
801                     mpLBProperty->setSubControl( pSubControl );
802                 }
803                 else
804                 {
805                     pSubControl->setValue( aValue, pEffect->getPresetId() );
806                 }
807             }
808             else
809             {
810                 mpLBProperty->setSubControl( 0 );
811             }
812 
813             bool bEnable = (pSubControl != 0) && (pSubControl->getControl()->IsEnabled());
814             mpLBProperty->Enable( bEnable );
815             mpFTProperty->Enable( bEnable );
816         }
817         else
818         {
819             mpLBProperty->setSubControl( 0 );
820             mpFTProperty->Enable( sal_False );
821             mpLBProperty->Enable( sal_False );
822             mpPBPropertyMore->Enable( sal_False );
823         }
824 
825         //
826         // ---
827         //
828         sal_uInt16 nPos = 0xffff;
829 
830         sal_Int16 nNodeType = pEffect->getNodeType();
831         switch( nNodeType )
832         {
833         case EffectNodeType::ON_CLICK:          nPos = 0; break;
834         case EffectNodeType::WITH_PREVIOUS:     nPos = 1; break;
835         case EffectNodeType::AFTER_PREVIOUS:    nPos = 2; break;
836         }
837 
838         mpLBStart->SelectEntryPos( nPos );
839 
840         double fDuration = pEffect->getDuration();
841         const bool bHasSpeed = fDuration > 0.001;
842 
843         mpFTSpeed->Enable(bHasSpeed);
844         mpCBSpeed->Enable(bHasSpeed);
845 
846         if( bHasSpeed )
847         {
848             if( fDuration == 5.0 )
849                 nPos = 0;
850             else if( fDuration == 3.0 )
851                 nPos = 1;
852             else if( fDuration == 2.0 )
853                 nPos = 2;
854             else if( fDuration == 1.0 )
855                 nPos = 3;
856             else if( fDuration == 0.5 )
857                 nPos = 4;
858             else
859                 nPos = 0xffff;
860 
861             mpCBSpeed->SelectEntryPos( nPos );
862         }
863 
864         mpPBPropertyMore->Enable( sal_True );
865 
866         mpFTChangeOrder->Enable( sal_True );
867     }
868     else
869     {
870         mpLBProperty->setSubControl( 0 );
871         mpFTProperty->Enable( sal_False );
872         mpLBProperty->Enable( sal_False );
873         mpPBPropertyMore->Enable( sal_False );
874         mpFTSpeed->Enable(sal_False);
875         mpCBSpeed->Enable(sal_False);
876         mpFTChangeOrder->Enable( sal_False );
877         mpLBStart->SetNoSelection();
878         mpCBSpeed->SetNoSelection();
879         mpFLEffect->SetText( maStrModify );
880     }
881 
882     bool bEnableUp = true;
883     bool bEnableDown = true;
884     if( nSelectionCount == 0 )
885     {
886         bEnableUp = false;
887         bEnableDown = false;
888     }
889     else
890     {
891         if( mpMainSequence->find( maListSelection.front() ) == mpMainSequence->getBegin() )
892             bEnableUp = false;
893 
894         EffectSequence::iterator aIter( mpMainSequence->find( maListSelection.back() ) );
895         if( aIter == mpMainSequence->getEnd() )
896         {
897             bEnableDown = false;
898         }
899         else
900         {
901             do
902             {
903                 aIter++;
904             }
905             while( (aIter != mpMainSequence->getEnd()) && !(mpCustomAnimationList->isExpanded((*aIter)) ) );
906 
907             if( aIter == mpMainSequence->getEnd() )
908                 bEnableDown = false;
909         }
910 
911         if( bEnableUp || bEnableDown )
912         {
913             MainSequenceRebuildGuard aGuard( mpMainSequence );
914 
915             EffectSequenceHelper* pSequence = 0;
916             EffectSequence::iterator aRebuildIter( maListSelection.begin() );
917             const EffectSequence::iterator aRebuildEnd( maListSelection.end() );
918             while( aRebuildIter != aRebuildEnd )
919             {
920                 CustomAnimationEffectPtr pEffect = (*aRebuildIter++);
921 
922                 if( pEffect.get() )
923                 {
924                     if( pSequence == 0 )
925                     {
926                         pSequence = pEffect->getEffectSequence();
927                     }
928                     else
929                     {
930                         if( pSequence != pEffect->getEffectSequence() )
931                         {
932                             bEnableUp = false;
933                             bEnableDown = false;
934                             break;
935                         }
936                     }
937                 }
938             }
939         }
940     }
941 
942     mpPBMoveUp->Enable(bEnableUp);
943     mpPBMoveDown->Enable(bEnableDown);
944 
945     SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
946     mpCBAutoPreview->Check( pOptions->IsPreviewChangedEffects() == sal_True );
947 
948     updateMotionPathTags();
949 }
950 
updateMotionPathImpl(CustomAnimationPane & rPane,::sd::View & rView,EffectSequence::iterator aIter,EffectSequence::iterator aEnd,MotionPathTagVector & rOldTags,MotionPathTagVector & rNewTags)951 static bool updateMotionPathImpl( CustomAnimationPane& rPane, ::sd::View& rView,  EffectSequence::iterator aIter, EffectSequence::iterator aEnd, MotionPathTagVector& rOldTags, MotionPathTagVector& rNewTags )
952 {
953     bool bChanges = false;
954     while( aIter != aEnd )
955     {
956         CustomAnimationEffectPtr pEffect( (*aIter++) );
957         if( pEffect.get() && pEffect->getPresetClass() == ::com::sun::star::presentation::EffectPresetClass::MOTIONPATH )
958         {
959             rtl::Reference< MotionPathTag > xMotionPathTag;
960             // first try to find if there is already a tag for this
961             MotionPathTagVector::iterator aMIter( rOldTags.begin() );
962             for( ; aMIter != rOldTags.end(); aMIter++ )
963             {
964                 rtl::Reference< MotionPathTag > xTag( (*aMIter) );
965                 if( xTag->getEffect() == pEffect )
966                 {
967                     if( !xTag->isDisposed() )
968                     {
969                         xMotionPathTag = xTag;
970                         rOldTags.erase( aMIter );
971                     }
972                     break;
973                 }
974             }
975 
976             // if not found, create new one
977             if( !xMotionPathTag.is() )
978             {
979                 xMotionPathTag.set( new MotionPathTag( rPane, rView, pEffect ) );
980                 bChanges = true;
981             }
982 
983             if( xMotionPathTag.is() )
984                 rNewTags.push_back( xMotionPathTag );
985         }
986     }
987 
988     return bChanges;
989 }
990 
updateMotionPathTags()991 void CustomAnimationPane::updateMotionPathTags()
992 {
993     bool bChanges = false;
994 
995     MotionPathTagVector aTags;
996     aTags.swap( maMotionPathTags );
997 
998     ::sd::View* pView = 0;
999 
1000     if( mxView.is() )
1001     {
1002         ::boost::shared_ptr<ViewShell> xViewShell( mrBase.GetMainViewShell() );
1003         if( xViewShell.get() )
1004             pView = xViewShell->GetView();
1005     }
1006 
1007     if( IsVisible() && mpMainSequence.get() && pView )
1008     {
1009         bChanges = updateMotionPathImpl( *this, *pView, mpMainSequence->getBegin(), mpMainSequence->getEnd(), aTags, maMotionPathTags );
1010 
1011         const InteractiveSequenceList& rISL = mpMainSequence->getInteractiveSequenceList();
1012         InteractiveSequenceList::const_iterator aISI( rISL.begin() );
1013         while( aISI != rISL.end() )
1014         {
1015             InteractiveSequencePtr pIS( (*aISI++) );
1016             bChanges |= updateMotionPathImpl( *this, *pView, pIS->getBegin(), pIS->getEnd(), aTags, maMotionPathTags );
1017         }
1018     }
1019 
1020     if( !aTags.empty() )
1021     {
1022         bChanges = true;
1023         MotionPathTagVector::iterator aIter( aTags.begin() );
1024         while( aIter != aTags.end() )
1025         {
1026             rtl::Reference< MotionPathTag > xTag( (*aIter++) );
1027             xTag->Dispose();
1028         }
1029     }
1030 
1031     if( bChanges && pView )
1032         pView->updateHandles();
1033 }
1034 
onSelectionChanged()1035 void CustomAnimationPane::onSelectionChanged()
1036 {
1037     if( !maSelectionLock.isLocked() )
1038     {
1039         ScopeLockGuard aGuard( maSelectionLock );
1040 
1041         if( mxView.is() ) try
1042         {
1043             Reference< XSelectionSupplier >  xSel( mxView, UNO_QUERY_THROW );
1044             if (xSel.is())
1045             {
1046                 maViewSelection = xSel->getSelection();
1047                 mpCustomAnimationList->onSelectionChanged( maViewSelection );
1048                 updateControls();
1049             }
1050         }
1051         catch( Exception& )
1052         {
1053             DBG_ERROR( "sd::CustomAnimationPane::onSelectionChanged(), Exception catched!" );
1054         }
1055     }
1056 }
1057 
onDoubleClick()1058 void CustomAnimationPane::onDoubleClick()
1059 {
1060     showOptions();
1061 }
1062 
onContextMenu(sal_uInt16 nSelectedPopupEntry)1063 void CustomAnimationPane::onContextMenu( sal_uInt16 nSelectedPopupEntry )
1064 {
1065     switch( nSelectedPopupEntry )
1066     {
1067     case CM_WITH_CLICK:     onChangeStart( EffectNodeType::ON_CLICK ); break;
1068     case CM_WITH_PREVIOUS:  onChangeStart( EffectNodeType::WITH_PREVIOUS  ); break;
1069     case CM_AFTER_PREVIOUS: onChangeStart( EffectNodeType::AFTER_PREVIOUS ); break;
1070     case CM_OPTIONS:        showOptions(); break;
1071     case CM_DURATION:       showOptions(RID_TP_CUSTOMANIMATION_DURATION); break;
1072     case CM_REMOVE:         onRemove(); break;
1073     case CM_CREATE:         if( maViewSelection.hasValue() ) onChange( true ); break;
1074     }
1075 
1076     updateControls();
1077 }
1078 
1079 
1080 
1081 
DataChanged(const DataChangedEvent & rEvent)1082 void CustomAnimationPane::DataChanged (const DataChangedEvent& rEvent)
1083 {
1084     (void)rEvent;
1085     UpdateLook();
1086 }
1087 
1088 
1089 
1090 
UpdateLook(void)1091 void CustomAnimationPane::UpdateLook (void)
1092 {
1093     const Wallpaper aBackground (
1094         ::sfx2::sidebar::Theme::GetWallpaper(
1095             ::sfx2::sidebar::Theme::Paint_PanelBackground));
1096     SetBackground(aBackground);
1097     if (mpFLModify != NULL)
1098         mpFLModify->SetBackground(aBackground);
1099     if (mpFLEffect != NULL)
1100         mpFLEffect->SetBackground(aBackground);
1101     if (mpFTStart != NULL)
1102         mpFTStart->SetBackground(aBackground);
1103     if (mpFTProperty != NULL)
1104         mpFTProperty->SetBackground(aBackground);
1105     if (mpFTSpeed != NULL)
1106         mpFTSpeed->SetBackground(aBackground);
1107     if (mpFTChangeOrder != NULL)
1108         mpFTChangeOrder->SetBackground(aBackground);
1109     if (mpFLSeperator1 != NULL)
1110         mpFLSeperator1->SetBackground(aBackground);
1111     if (mpFLSeperator2 != NULL)
1112         mpFLSeperator2->SetBackground(aBackground);
1113 }
1114 
1115 
1116 
1117 
addValue(STLPropertySet * pSet,sal_Int32 nHandle,const Any & rValue)1118 void addValue( STLPropertySet* pSet, sal_Int32 nHandle, const Any& rValue )
1119 {
1120     switch( pSet->getPropertyState( nHandle ) )
1121     {
1122     case STLPropertyState_AMBIGUOUS:
1123         // value is already ambiguous, do nothing
1124         break;
1125     case STLPropertyState_DIRECT:
1126         // set to ambiguous if existing value is different
1127         if( rValue != pSet->getPropertyValue( nHandle ) )
1128             pSet->setPropertyState( nHandle, STLPropertyState_AMBIGUOUS );
1129         break;
1130     case STLPropertyState_DEFAULT:
1131         // just set new value
1132         pSet->setPropertyValue( nHandle, rValue );
1133         break;
1134     }
1135 }
1136 
calcMaxParaDepth(Reference<XShape> xTargetShape)1137 static sal_Int32 calcMaxParaDepth( Reference< XShape > xTargetShape )
1138 {
1139     sal_Int32 nMaxParaDepth = -1;
1140 
1141     if( xTargetShape.is() )
1142     {
1143         Reference< XEnumerationAccess > xText( xTargetShape, UNO_QUERY );
1144         if( xText.is() )
1145         {
1146             Reference< XPropertySet > xParaSet;
1147             const OUString strNumberingLevel( RTL_CONSTASCII_USTRINGPARAM("NumberingLevel") );
1148 
1149             Reference< XEnumeration > xEnumeration( xText->createEnumeration(), UNO_QUERY_THROW );
1150             while( xEnumeration->hasMoreElements() )
1151             {
1152                 xEnumeration->nextElement() >>= xParaSet;
1153                 if( xParaSet.is() )
1154                 {
1155                     sal_Int32 nParaDepth = 0;
1156                     xParaSet->getPropertyValue( strNumberingLevel ) >>= nParaDepth;
1157 
1158                     if( nParaDepth > nMaxParaDepth )
1159                         nMaxParaDepth = nParaDepth;
1160                 }
1161             }
1162         }
1163     }
1164 
1165     return nMaxParaDepth + 1;
1166 }
1167 
getProperty1Value(sal_Int32 nType,CustomAnimationEffectPtr pEffect)1168 Any CustomAnimationPane::getProperty1Value( sal_Int32 nType, CustomAnimationEffectPtr pEffect )
1169 {
1170     switch( nType )
1171     {
1172     case nPropertyTypeDirection:
1173     case nPropertyTypeSpokes:
1174     case nPropertyTypeZoom:
1175         return makeAny( pEffect->getPresetSubType() );
1176 
1177     case nPropertyTypeColor:
1178     case nPropertyTypeFillColor:
1179     case nPropertyTypeFirstColor:
1180     case nPropertyTypeSecondColor:
1181     case nPropertyTypeCharColor:
1182     case nPropertyTypeLineColor:
1183         {
1184             const sal_Int32 nIndex = (nPropertyTypeFirstColor == nType) ? 0 : 1;
1185             return pEffect->getColor( nIndex );
1186         }
1187 
1188     case nPropertyTypeFont:
1189         return pEffect->getProperty( AnimationNodeType::SET, OUString( RTL_CONSTASCII_USTRINGPARAM("CharFontName") ), VALUE_TO );
1190 
1191     case nPropertyTypeCharHeight:
1192         {
1193             const OUString aAttributeName( RTL_CONSTASCII_USTRINGPARAM( "CharHeight" ) );
1194             Any aValue( pEffect->getProperty( AnimationNodeType::SET, aAttributeName, VALUE_TO ) );
1195             if( !aValue.hasValue() )
1196                 aValue = pEffect->getProperty( AnimationNodeType::ANIMATE, aAttributeName, VALUE_TO );
1197             return aValue;
1198         }
1199 
1200     case nPropertyTypeRotate:
1201         return pEffect->getTransformationProperty( AnimationTransformType::ROTATE, VALUE_BY);
1202 
1203     case nPropertyTypeTransparency:
1204         return pEffect->getProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("Opacity")), VALUE_TO );
1205 
1206     case nPropertyTypeScale:
1207         return pEffect->getTransformationProperty( AnimationTransformType::SCALE, VALUE_BY );
1208 
1209     case nPropertyTypeCharDecoration:
1210         {
1211             Sequence< Any > aValues(3);
1212             aValues[0] = pEffect->getProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharWeight")), VALUE_TO );
1213             aValues[1] = pEffect->getProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharPosture")), VALUE_TO );
1214             aValues[2] = pEffect->getProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharUnderline")), VALUE_TO );
1215             return makeAny( aValues );
1216         }
1217     }
1218 
1219     Any aAny;
1220     return aAny;
1221 }
1222 
setProperty1Value(sal_Int32 nType,CustomAnimationEffectPtr pEffect,const Any & rValue)1223 bool CustomAnimationPane::setProperty1Value( sal_Int32 nType, CustomAnimationEffectPtr pEffect, const Any& rValue )
1224 {
1225     bool bEffectChanged = false;
1226     switch( nType )
1227     {
1228     case nPropertyTypeDirection:
1229     case nPropertyTypeSpokes:
1230     case nPropertyTypeZoom:
1231         {
1232             OUString aPresetSubType;
1233             rValue >>= aPresetSubType;
1234             if( aPresetSubType != pEffect->getPresetSubType() )
1235             {
1236                 getPresets().changePresetSubType( pEffect, aPresetSubType );
1237                 bEffectChanged = true;
1238             }
1239         }
1240         break;
1241 
1242     case nPropertyTypeFillColor:
1243     case nPropertyTypeColor:
1244     case nPropertyTypeFirstColor:
1245     case nPropertyTypeSecondColor:
1246     case nPropertyTypeCharColor:
1247     case nPropertyTypeLineColor:
1248         {
1249             const sal_Int32 nIndex = (nPropertyTypeFirstColor == nType) ? 0 : 1;
1250             Any aOldColor( pEffect->getColor( nIndex ) );
1251             if( aOldColor != rValue )
1252             {
1253                 pEffect->setColor( nIndex, rValue );
1254                 bEffectChanged = true;
1255             }
1256         }
1257         break;
1258 
1259     case nPropertyTypeFont:
1260         bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, OUString( RTL_CONSTASCII_USTRINGPARAM( "CharFontName" ) ), VALUE_TO, rValue );
1261         break;
1262 
1263     case nPropertyTypeCharHeight:
1264         {
1265             const OUString aAttributeName( RTL_CONSTASCII_USTRINGPARAM( "CharHeight" ) );
1266             bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, aAttributeName, VALUE_TO, rValue );
1267             if( !bEffectChanged )
1268                 bEffectChanged = pEffect->setProperty( AnimationNodeType::ANIMATE, aAttributeName, VALUE_TO, rValue );
1269         }
1270         break;
1271     case nPropertyTypeRotate:
1272         bEffectChanged = pEffect->setTransformationProperty( AnimationTransformType::ROTATE, VALUE_BY , rValue );
1273         break;
1274 
1275     case nPropertyTypeTransparency:
1276         bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, OUString( RTL_CONSTASCII_USTRINGPARAM("Opacity") ), VALUE_TO, rValue );
1277         break;
1278 
1279     case nPropertyTypeScale:
1280         bEffectChanged = pEffect->setTransformationProperty( AnimationTransformType::SCALE, VALUE_BY, rValue );
1281         break;
1282 
1283     case nPropertyTypeCharDecoration:
1284         {
1285             Sequence< Any > aValues(3);
1286             rValue >>= aValues;
1287             bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharWeight")), VALUE_TO, aValues[0] );
1288             bEffectChanged |= pEffect->setProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharPosture")), VALUE_TO, aValues[1] );
1289             bEffectChanged |= pEffect->setProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharUnderline")), VALUE_TO, aValues[2] );
1290         }
1291         break;
1292 
1293     }
1294 
1295     return bEffectChanged;
1296 }
1297 
hasVisibleShape(const Reference<XShape> & xShape)1298 static sal_Bool hasVisibleShape( const Reference< XShape >& xShape )
1299 {
1300     try
1301     {
1302         const OUString sShapeType( xShape->getShapeType() );
1303 
1304         if( sShapeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.presentation.TitleTextShape") ) ||
1305             sShapeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.presentation.OutlinerShape") ) ||
1306             sShapeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.presentation.SubtitleShape") ) ||
1307             sShapeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.drawing.TextShape") ) )
1308         {
1309             const OUString sFillStyle( RTL_CONSTASCII_USTRINGPARAM("FillStyle" ) );
1310             const OUString sLineStyle( RTL_CONSTASCII_USTRINGPARAM("LineStyle" ) );
1311             Reference< XPropertySet > xSet( xShape, UNO_QUERY_THROW );
1312 
1313             FillStyle eFillStyle;
1314             xSet->getPropertyValue( sFillStyle ) >>= eFillStyle;
1315 
1316             ::com::sun::star::drawing::LineStyle eLineStyle;
1317             xSet->getPropertyValue( sLineStyle ) >>= eLineStyle;
1318 
1319             return eFillStyle != FillStyle_NONE || eLineStyle != ::com::sun::star::drawing::LineStyle_NONE;
1320         }
1321     }
1322     catch( Exception& e )
1323     {
1324         (void)e;
1325     }
1326     return sal_True;
1327 }
1328 
createSelectionSet()1329 STLPropertySet* CustomAnimationPane::createSelectionSet()
1330 {
1331     STLPropertySet* pSet = CustomAnimationDialog::createDefaultSet();
1332 
1333     pSet->setPropertyValue( nHandleCurrentPage, makeAny( mxCurrentPage ) );
1334 
1335     sal_Int32 nMaxParaDepth = 0;
1336 
1337     // get options from selected effects
1338     EffectSequence::iterator aIter( maListSelection.begin() );
1339     const EffectSequence::iterator aEnd( maListSelection.end() );
1340     const CustomAnimationPresets& rPresets (getPresets());
1341     while( aIter != aEnd )
1342     {
1343         CustomAnimationEffectPtr pEffect = (*aIter++);
1344 
1345         EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
1346         if( !pEffectSequence )
1347             pEffectSequence = mpMainSequence.get();
1348 
1349         if( pEffect->hasText() )
1350         {
1351             sal_Int32 n = calcMaxParaDepth(pEffect->getTargetShape());
1352             if( n > nMaxParaDepth )
1353                 nMaxParaDepth = n;
1354         }
1355 
1356         addValue( pSet, nHandleHasAfterEffect, makeAny( pEffect->hasAfterEffect() ) );
1357         addValue( pSet, nHandleAfterEffectOnNextEffect, makeAny( pEffect->IsAfterEffectOnNext() ? sal_True : sal_False ) );
1358         addValue( pSet, nHandleDimColor, pEffect->getDimColor() );
1359         addValue( pSet, nHandleIterateType, makeAny( pEffect->getIterateType() ) );
1360 
1361         // convert absolute time to percentage value
1362         // This calculation is done in float to avoid some rounding artifacts.
1363         float fIterateInterval = (float)pEffect->getIterateInterval();
1364         if( pEffect->getDuration() )
1365             fIterateInterval = (float)(fIterateInterval / pEffect->getDuration() );
1366         fIterateInterval *= 100.0;
1367         addValue( pSet, nHandleIterateInterval, makeAny( (double)fIterateInterval ) );
1368 
1369         addValue( pSet, nHandleBegin, makeAny( pEffect->getBegin() ) );
1370         addValue( pSet, nHandleDuration, makeAny( pEffect->getDuration() ) );
1371         addValue( pSet, nHandleStart, makeAny( pEffect->getNodeType() ) );
1372         addValue( pSet, nHandleRepeat, makeAny( pEffect->getRepeatCount() ) );
1373         addValue( pSet, nHandleEnd, pEffect->getEnd() );
1374         addValue( pSet, nHandleRewind, makeAny( pEffect->getFill() ) );
1375 
1376         addValue( pSet, nHandlePresetId, makeAny( pEffect->getPresetId() ) );
1377 
1378         addValue( pSet, nHandleHasText, makeAny( (sal_Bool)pEffect->hasText() ) );
1379 
1380         addValue( pSet, nHandleHasVisibleShape, Any( hasVisibleShape( pEffect->getTargetShape() ) ) );
1381 
1382         Any aSoundSource;
1383         if( pEffect->getAudio().is() )
1384         {
1385             aSoundSource = pEffect->getAudio()->getSource();
1386             addValue( pSet, nHandleSoundVolumne, makeAny( pEffect->getAudio()->getVolume() ) );
1387 // todo     addValue( pSet, nHandleSoundEndAfterSlide, makeAny( pEffect->getAudio()->getEndAfterSlide() ) );
1388 // this is now stored at the XCommand parameter sequence
1389         }
1390         else if( pEffect->getCommand() == EffectCommands::STOPAUDIO )
1391         {
1392             aSoundSource = makeAny( (sal_Bool)sal_True );
1393         }
1394         addValue( pSet, nHandleSoundURL, aSoundSource );
1395 
1396         sal_Int32 nGroupId = pEffect->getGroupId();
1397         CustomAnimationTextGroupPtr pTextGroup;
1398         if( nGroupId != -1 )
1399             pTextGroup = pEffectSequence->findGroup( nGroupId );
1400 
1401         addValue( pSet, nHandleTextGrouping, makeAny( pTextGroup.get() ? pTextGroup->getTextGrouping() : (sal_Int32)-1 ) );
1402         addValue( pSet, nHandleAnimateForm, makeAny( pTextGroup.get() ? (sal_Bool)pTextGroup->getAnimateForm() : sal_True ) );
1403         addValue( pSet, nHandleTextGroupingAuto, makeAny( pTextGroup.get() ? pTextGroup->getTextGroupingAuto() : (double)-1.0 ) );
1404         addValue( pSet, nHandleTextReverse, makeAny( pTextGroup.get() ? (sal_Bool)pTextGroup->getTextReverse() : sal_False ) );
1405 
1406         if( pEffectSequence->getSequenceType() == EffectNodeType::INTERACTIVE_SEQUENCE  )
1407         {
1408             InteractiveSequence* pIS = static_cast< InteractiveSequence* >( pEffectSequence );
1409             addValue( pSet, nHandleTrigger, makeAny( pIS->getTriggerShape() ) );
1410         }
1411 
1412         //
1413 
1414         CustomAnimationPresetPtr pDescriptor = rPresets.getEffectDescriptor( pEffect->getPresetId() );
1415         if( pDescriptor.get() )
1416         {
1417             sal_Int32 nType = nPropertyTypeNone;
1418 
1419             UStringList aProperties( pDescriptor->getProperties() );
1420             if( aProperties.size() >= 1 )
1421                 nType = getPropertyType( aProperties.front() );
1422 
1423             if( nType != nPropertyTypeNone )
1424             {
1425                 addValue( pSet, nHandleProperty1Type, makeAny( nType ) );
1426                 addValue( pSet, nHandleProperty1Value, getProperty1Value( nType, pEffect ) );
1427             }
1428 
1429             if( pDescriptor->hasProperty( OUString( RTL_CONSTASCII_USTRINGPARAM( "Accelerate" ) ) ) )
1430             {
1431                 addValue( pSet, nHandleAccelerate, makeAny( pEffect->getAcceleration() ) );
1432             }
1433 
1434             if( pDescriptor->hasProperty( OUString( RTL_CONSTASCII_USTRINGPARAM( "Decelerate" ) ) ) )
1435             {
1436                 addValue( pSet, nHandleDecelerate, makeAny( pEffect->getDecelerate() ) );
1437             }
1438 
1439             if( pDescriptor->hasProperty( OUString( RTL_CONSTASCII_USTRINGPARAM( "AutoReverse" ) ) ) )
1440             {
1441                 addValue( pSet, nHandleAutoReverse, makeAny( pEffect->getAutoReverse() ) );
1442             }
1443         }
1444     }
1445 
1446     addValue( pSet, nHandleMaxParaDepth, makeAny( nMaxParaDepth ) );
1447 
1448     return pSet;
1449 }
1450 
changeSelection(STLPropertySet * pResultSet,STLPropertySet * pOldSet)1451 void CustomAnimationPane::changeSelection( STLPropertySet* pResultSet, STLPropertySet* pOldSet )
1452 {
1453     // change selected effect
1454     bool bChanged = false;
1455 
1456     MainSequenceRebuildGuard aGuard( mpMainSequence );
1457 
1458     EffectSequence::iterator aIter( maListSelection.begin() );
1459     const EffectSequence::iterator aEnd( maListSelection.end() );
1460     while( aIter != aEnd )
1461     {
1462         CustomAnimationEffectPtr pEffect = (*aIter++);
1463 
1464         DBG_ASSERT( pEffect->getEffectSequence(), "sd::CustomAnimationPane::changeSelection(), dead effect in selection!" );
1465         if( !pEffect->getEffectSequence() )
1466             continue;
1467 
1468         double fDuration = 0.0; // we might need this for iterate-interval
1469         if( pResultSet->getPropertyState( nHandleDuration ) == STLPropertyState_DIRECT )
1470         {
1471             pResultSet->getPropertyValue( nHandleDuration ) >>= fDuration;
1472         }
1473         else
1474         {
1475             fDuration = pEffect->getDuration();
1476         }
1477 
1478         if( pResultSet->getPropertyState( nHandleIterateType ) == STLPropertyState_DIRECT )
1479         {
1480             sal_Int16 nIterateType = 0;
1481             pResultSet->getPropertyValue( nHandleIterateType ) >>= nIterateType;
1482             if( pEffect->getIterateType() != nIterateType )
1483             {
1484                 pEffect->setIterateType( nIterateType );
1485                 bChanged = true;
1486             }
1487         }
1488 
1489         if( pEffect->getIterateType() )
1490         {
1491             if( pResultSet->getPropertyState( nHandleIterateInterval ) == STLPropertyState_DIRECT )
1492             {
1493                 double fIterateInterval = 0.0;
1494                 pResultSet->getPropertyValue( nHandleIterateInterval ) >>= fIterateInterval;
1495                 if( pEffect->getIterateInterval() != fIterateInterval )
1496                 {
1497                     const double f = fIterateInterval * pEffect->getDuration() / 100;
1498                     pEffect->setIterateInterval( f );
1499                     bChanged = true;
1500                 }
1501             }
1502         }
1503 
1504         if( pResultSet->getPropertyState( nHandleBegin ) == STLPropertyState_DIRECT )
1505         {
1506             double fBegin = 0.0;
1507             pResultSet->getPropertyValue( nHandleBegin ) >>= fBegin;
1508             if( pEffect->getBegin() != fBegin )
1509             {
1510                 pEffect->setBegin( fBegin );
1511                 bChanged = true;
1512             }
1513         }
1514 
1515         if( pResultSet->getPropertyState( nHandleDuration ) == STLPropertyState_DIRECT )
1516         {
1517             if( pEffect->getDuration() != fDuration )
1518             {
1519                 pEffect->setDuration( fDuration );
1520                 bChanged = true;
1521             }
1522         }
1523 
1524         if( pResultSet->getPropertyState( nHandleStart ) == STLPropertyState_DIRECT )
1525         {
1526             sal_Int16 nNodeType = 0;
1527             pResultSet->getPropertyValue( nHandleStart ) >>= nNodeType;
1528             if( pEffect->getNodeType() != nNodeType )
1529             {
1530                 pEffect->setNodeType( nNodeType );
1531                 bChanged = true;
1532             }
1533         }
1534 
1535         if( pResultSet->getPropertyState( nHandleRepeat ) == STLPropertyState_DIRECT )
1536         {
1537             Any aRepeatCount( pResultSet->getPropertyValue( nHandleRepeat ) );
1538             if( aRepeatCount != pEffect->getRepeatCount() )
1539             {
1540                 pEffect->setRepeatCount( aRepeatCount );
1541                 bChanged = true;
1542             }
1543         }
1544 
1545         if( pResultSet->getPropertyState( nHandleEnd ) == STLPropertyState_DIRECT )
1546         {
1547             Any aEndValue( pResultSet->getPropertyValue( nHandleEnd ) );
1548             if( pEffect->getEnd() != aEndValue )
1549             {
1550                 pEffect->setEnd( aEndValue );
1551                 bChanged = true;
1552             }
1553         }
1554 
1555         if( pResultSet->getPropertyState( nHandleRewind ) == STLPropertyState_DIRECT )
1556         {
1557             sal_Int16 nFill = 0;
1558             pResultSet->getPropertyValue( nHandleRewind ) >>= nFill;
1559             if( pEffect->getFill() != nFill )
1560             {
1561                 pEffect->setFill( nFill );
1562                 bChanged = true;
1563             }
1564         }
1565 
1566         if( pResultSet->getPropertyState( nHandleHasAfterEffect ) == STLPropertyState_DIRECT )
1567         {
1568             sal_Bool bHasAfterEffect = sal_False;
1569             if( pResultSet->getPropertyValue( nHandleHasAfterEffect )  >>= bHasAfterEffect )
1570             {
1571                 if( pEffect->hasAfterEffect() != bHasAfterEffect )
1572                 {
1573                     pEffect->setHasAfterEffect( bHasAfterEffect );
1574                     bChanged = true;
1575                 }
1576             }
1577         }
1578 
1579         if( pResultSet->getPropertyState( nHandleAfterEffectOnNextEffect ) == STLPropertyState_DIRECT )
1580         {
1581             sal_Bool bAfterEffectOnNextEffect = sal_False;
1582             if( (pResultSet->getPropertyValue( nHandleAfterEffectOnNextEffect ) >>= bAfterEffectOnNextEffect) && ((pEffect->IsAfterEffectOnNext() ? sal_True : sal_False) != bAfterEffectOnNextEffect) )
1583             {
1584                 pEffect->setAfterEffectOnNext( bAfterEffectOnNextEffect );
1585                 bChanged = true;
1586             }
1587         }
1588 
1589         if( pResultSet->getPropertyState( nHandleDimColor ) == STLPropertyState_DIRECT )
1590         {
1591             Any aDimColor( pResultSet->getPropertyValue( nHandleDimColor ) );
1592             if( pEffect->getDimColor() != aDimColor )
1593             {
1594                 pEffect->setDimColor( aDimColor );
1595                 bChanged = true;
1596             }
1597         }
1598 
1599         if( pResultSet->getPropertyState( nHandleAccelerate ) == STLPropertyState_DIRECT )
1600         {
1601             double fAccelerate = 0.0;
1602             pResultSet->getPropertyValue( nHandleAccelerate ) >>= fAccelerate;
1603             if( pEffect->getAcceleration() != fAccelerate )
1604             {
1605                 pEffect->setAcceleration( fAccelerate );
1606                 bChanged = true;
1607             }
1608         }
1609 
1610         if( pResultSet->getPropertyState( nHandleDecelerate ) == STLPropertyState_DIRECT )
1611         {
1612             double fDecelerate = 0.0;
1613             pResultSet->getPropertyValue( nHandleDecelerate ) >>= fDecelerate;
1614             if( pEffect->getDecelerate() != fDecelerate )
1615             {
1616                 pEffect->setDecelerate( fDecelerate );
1617                 bChanged = true;
1618             }
1619         }
1620 
1621         if( pResultSet->getPropertyState( nHandleAutoReverse ) == STLPropertyState_DIRECT )
1622         {
1623             sal_Bool bAutoReverse = sal_False;
1624             pResultSet->getPropertyValue( nHandleAutoReverse ) >>= bAutoReverse;
1625             if( pEffect->getAutoReverse() != bAutoReverse )
1626             {
1627                 pEffect->setAutoReverse( bAutoReverse );
1628                 bChanged = true;
1629             }
1630         }
1631 
1632         if( pResultSet->getPropertyState( nHandleProperty1Value ) == STLPropertyState_DIRECT )
1633         {
1634             sal_Int32 nType = 0;
1635             pOldSet->getPropertyValue( nHandleProperty1Type ) >>= nType;
1636 
1637             bChanged |= setProperty1Value( nType, pEffect, pResultSet->getPropertyValue( nHandleProperty1Value ) );
1638         }
1639 
1640         if( pResultSet->getPropertyState( nHandleSoundURL ) == STLPropertyState_DIRECT )
1641         {
1642             const Any aSoundSource( pResultSet->getPropertyValue( nHandleSoundURL ) );
1643 
1644             if( aSoundSource.getValueType() == ::getCppuType((const sal_Bool*)0) )
1645             {
1646                 pEffect->setStopAudio();
1647                 bChanged = true;
1648             }
1649             else
1650             {
1651                 OUString aSoundURL;
1652                 aSoundSource >>= aSoundURL;
1653 
1654                 if( aSoundURL.getLength() )
1655                 {
1656                     if( !pEffect->getAudio().is() )
1657                     {
1658                         pEffect->createAudio( aSoundSource );
1659                         bChanged = true;
1660                     }
1661                     else
1662                     {
1663                         if( pEffect->getAudio()->getSource() != aSoundSource )
1664                         {
1665                             pEffect->getAudio()->setSource( aSoundSource );
1666                             bChanged = true;
1667                         }
1668                     }
1669                 }
1670                 else
1671                 {
1672                     if( pEffect->getAudio().is() || pEffect->getStopAudio() )
1673                     {
1674                         pEffect->removeAudio();
1675                         bChanged = true;
1676                     }
1677                 }
1678             }
1679         }
1680 
1681         if( pResultSet->getPropertyState( nHandleTrigger ) == STLPropertyState_DIRECT )
1682         {
1683             Reference< XShape > xTriggerShape;
1684             pResultSet->getPropertyValue( nHandleTrigger ) >>= xTriggerShape;
1685             bChanged |= mpMainSequence->setTrigger( pEffect, xTriggerShape );
1686         }
1687     }
1688 
1689     const bool bHasTextGrouping = pResultSet->getPropertyState( nHandleTextGrouping ) == STLPropertyState_DIRECT;
1690     const bool bHasAnimateForm = pResultSet->getPropertyState( nHandleAnimateForm ) == STLPropertyState_DIRECT;
1691     const bool bHasTextGroupingAuto = pResultSet->getPropertyState( nHandleTextGroupingAuto ) == STLPropertyState_DIRECT;
1692     const bool bHasTextReverse = pResultSet->getPropertyState( nHandleTextReverse ) == STLPropertyState_DIRECT;
1693 
1694     if( bHasTextGrouping || bHasAnimateForm || bHasTextGroupingAuto || bHasTextReverse )
1695     {
1696         // we need to do a second pass for text grouping options
1697         // since changing them can cause effects to be removed
1698         // or replaced, we do this after we aplied all other options
1699         // above
1700 
1701         sal_Int32 nTextGrouping = 0;
1702         sal_Bool bAnimateForm = sal_True, bTextReverse = sal_False;
1703         double fTextGroupingAuto = -1.0;
1704 
1705         if( bHasTextGrouping )
1706             pResultSet->getPropertyValue(nHandleTextGrouping) >>= nTextGrouping;
1707 
1708         if( bHasAnimateForm )
1709             pResultSet->getPropertyValue(nHandleAnimateForm) >>= bAnimateForm;
1710 
1711         if( bHasTextGroupingAuto )
1712             pResultSet->getPropertyValue(nHandleTextGroupingAuto) >>= fTextGroupingAuto;
1713 
1714         if( bHasTextReverse )
1715             pResultSet->getPropertyValue(nHandleTextReverse) >>= bTextReverse;
1716 
1717         EffectSequence const aSelectedEffects( maListSelection );
1718         EffectSequence::const_iterator iter( aSelectedEffects.begin() );
1719         const EffectSequence::const_iterator iEnd( aSelectedEffects.end() );
1720         while( iter != iEnd )
1721         {
1722             CustomAnimationEffectPtr const& pEffect = (*iter++);
1723 
1724             EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
1725             if( !pEffectSequence )
1726                 pEffectSequence = mpMainSequence.get();
1727 
1728             sal_Int32 nGroupId = pEffect->getGroupId();
1729             CustomAnimationTextGroupPtr pTextGroup;
1730             if( (nGroupId != -1) )
1731             {
1732                 // use existing group
1733                 pTextGroup = pEffectSequence->findGroup( nGroupId );
1734             }
1735             else
1736             {
1737                 // somethings changed so we need a group now
1738                 pTextGroup = pEffectSequence->createTextGroup( pEffect, nTextGrouping, fTextGroupingAuto, bAnimateForm, bTextReverse );
1739                 bChanged = true;
1740             }
1741 
1742             //#Bug 119988#
1743             /************************************************************************/
1744             /*
1745             Note, the setAnimateForm means set the animation from TextGroup to Object's Shape
1746             And on the UI in means "Animate attached shape" in "Effect Option" dialog
1747             The setTextGrouping means set animation to Object's Text,
1748             the nTextGrouping is Text Animation Type
1749             nTextGrouping = -1 is "As one Object", means no text animation.
1750 
1751             The previous call order first do the setTextGrouping and then do the setAnimateForm,
1752             that will cause such defect: in the setTextGrouping, the effect has been removed,
1753             but in setAnimateForm still need this effect, then a NULL pointer of that effect will
1754             be gotten, and cause crash.
1755 
1756             []bHasAnimateForm means the UI has changed, bAnimateForm is it value
1757 
1758             So if create a new textgroup animation, the following animation will never be run!
1759             Since the ��Animate attached shape�� is default checked.
1760             And the bHasAnimateForm default is false, and if user uncheck it the value bAnimateForm will be false,
1761             it same as the TextGroup��s default value, also could not be run setAnimateForm.
1762             if( bHasAnimateForm )
1763             {
1764             if( pTextGroup->getAnimateForm() != bAnimateForm )
1765             {
1766             pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1767             bChanged = true;
1768             }
1769             }
1770 
1771             In setTextGrouping, there are three case:
1772             1.  Create new text effects for empty TextGroup
1773             2.  Remove all text effects of TextGroup (nTextGrouping == -1)
1774             3.  Change all the text effects�� start type
1775 
1776             So here is the right logic:
1777             If set the animation from text to shape and remove text animation,
1778             should do setAnimateForm first, then do setTextGrouping.
1779             Other case,do setTextGrouping first, then do setAnimateForm.
1780 
1781             */
1782             /************************************************************************/
1783 
1784             bool    bDoSetAnimateFormFirst = false;
1785             bool    bNeedDoSetAnimateForm = false;
1786 
1787             if( bHasAnimateForm )
1788             {
1789                 if( pTextGroup->getAnimateForm() != bAnimateForm )
1790                 {
1791                     if( (pTextGroup->getTextGrouping() >= 0) && (nTextGrouping == -1 ) )
1792                     {
1793                         bDoSetAnimateFormFirst = true;
1794                     }
1795                     bNeedDoSetAnimateForm = true;
1796                 }
1797             }
1798 
1799             if (bDoSetAnimateFormFirst)
1800             {
1801                 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1802                 bChanged = true;
1803             }
1804 
1805             if( bHasTextGrouping )
1806             {
1807                 if( (pTextGroup->getTextGrouping() != nTextGrouping) )
1808                 {
1809                     pEffectSequence->setTextGrouping( pTextGroup, nTextGrouping );
1810                     bChanged = true;
1811                 }
1812             }
1813 
1814             if (!bDoSetAnimateFormFirst&&bNeedDoSetAnimateForm)
1815             {
1816                 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm );
1817                 bChanged = true;
1818             }
1819 
1820             if( bHasTextGroupingAuto )
1821             {
1822                 if( pTextGroup->getTextGroupingAuto() != fTextGroupingAuto )
1823                 {
1824                     pEffectSequence->setTextGroupingAuto( pTextGroup, fTextGroupingAuto );
1825                     bChanged = true;
1826                 }
1827             }
1828 
1829             if( bHasTextReverse )
1830             {
1831                 if( pTextGroup->getTextReverse() != bTextReverse )
1832                 {
1833                     pEffectSequence->setTextReverse( pTextGroup, bTextReverse );
1834                     bChanged = true;
1835                 }
1836             }
1837         }
1838     }
1839 
1840     if( bChanged )
1841     {
1842         mpMainSequence->rebuild();
1843         updateControls();
1844         mrBase.GetDocShell()->SetModified();
1845     }
1846 }
1847 
showOptions(sal_uInt16 nPage)1848 void CustomAnimationPane::showOptions( sal_uInt16 nPage /* = 0 */ )
1849 {
1850     STLPropertySet* pSet = createSelectionSet();
1851 
1852     CustomAnimationDialog* pDlg = new CustomAnimationDialog( this, pSet, nPage );
1853     if( pDlg->Execute() )
1854     {
1855         addUndo();
1856         changeSelection( pDlg->getResultSet(), pSet );
1857         updateControls();
1858     }
1859 
1860     delete pDlg;
1861 }
1862 
onChangeCurrentPage()1863 void CustomAnimationPane::onChangeCurrentPage()
1864 {
1865     if( mxView.is() ) try
1866     {
1867         Reference< XDrawPage > xNewPage( mxView->getCurrentPage() );
1868         if( xNewPage != mxCurrentPage )
1869         {
1870             mxCurrentPage = xNewPage;
1871             SdPage* pPage = SdPage::getImplementation( mxCurrentPage );
1872             if( pPage )
1873             {
1874                 mpMainSequence = pPage->getMainSequence();
1875                 mpCustomAnimationList->update( mpMainSequence );
1876             }
1877             updateControls();
1878         }
1879     }
1880     catch( Exception& )
1881     {
1882         DBG_ERROR( "sd::CustomAnimationPane::onChangeCurrentPage(), exception catched!" );
1883     }
1884 }
1885 
getTextSelection(const Any & rSelection,Reference<XShape> & xShape,std::list<sal_Int16> & rParaList)1886 bool getTextSelection( const Any& rSelection, Reference< XShape >& xShape, std::list< sal_Int16 >& rParaList )
1887 {
1888     Reference< XTextRange > xSelectedText;
1889     rSelection >>= xSelectedText;
1890     if( xSelectedText.is() ) try
1891     {
1892         xShape.set( xSelectedText->getText(), UNO_QUERY_THROW );
1893 
1894         Reference< XTextRangeCompare > xTextRangeCompare( xShape, UNO_QUERY_THROW );
1895         Reference< XEnumerationAccess > xParaEnumAccess( xShape, UNO_QUERY_THROW );
1896         Reference< XEnumeration > xParaEnum( xParaEnumAccess->createEnumeration(), UNO_QUERY_THROW );
1897         Reference< XTextRange > xRange;
1898         Reference< XTextRange > xStart( xSelectedText->getStart() );
1899         Reference< XTextRange > xEnd( xSelectedText->getEnd() );
1900 
1901         if( xTextRangeCompare->compareRegionEnds( xStart, xEnd ) < 0 )
1902         {
1903             Reference< XTextRange > xTemp( xStart );
1904             xStart = xEnd;
1905             xEnd = xTemp;
1906         }
1907 
1908         sal_Int16 nPara = 0;
1909         while( xParaEnum->hasMoreElements() )
1910         {
1911             xParaEnum->nextElement() >>= xRange;
1912 
1913             // break if start of selection is prior to end of current paragraph
1914             if( xRange.is() && (xTextRangeCompare->compareRegionEnds( xStart, xRange ) >= 0 ) )
1915                 break;
1916 
1917             nPara++;
1918         }
1919 
1920         while( xRange.is() )
1921         {
1922             if( xRange.is() && xRange->getString().getLength() )
1923                 rParaList.push_back( nPara );
1924 
1925             // break if end of selection is before or at end of current paragraph
1926             if( xRange.is() && xTextRangeCompare->compareRegionEnds( xEnd, xRange ) >= 0 )
1927                 break;
1928 
1929             nPara++;
1930 
1931             if( xParaEnum->hasMoreElements() )
1932                 xParaEnum->nextElement() >>= xRange;
1933             else
1934                 xRange.clear();
1935         }
1936 
1937         return true;
1938     }
1939     catch( Exception& e )
1940     {
1941         (void)e;
1942         DBG_ERROR( "sd::CustomAnimationPane::getTextSelection(), exception cought!" );
1943     }
1944 
1945     return false;
1946 }
1947 
onChange(bool bCreate)1948 void CustomAnimationPane::onChange( bool bCreate )
1949 {
1950     bool bHasText = true;
1951 
1952     // first create vector of targets for dialog preview
1953     std::vector< Any > aTargets;
1954     OUString sPresetId;
1955     double fDuration = 2.0f;
1956 
1957     if( bCreate )
1958     {
1959         // gather shapes from the selection
1960         Reference< XSelectionSupplier >  xSel( mxView, UNO_QUERY_THROW );
1961         maViewSelection = xSel->getSelection();
1962 
1963         if( maViewSelection.getValueType() == ::getCppuType((const Reference< XShapes >*)0) )
1964         {
1965             Reference< XIndexAccess > xShapes;
1966             maViewSelection >>= xShapes;
1967 
1968             sal_Int32 nCount = xShapes->getCount();
1969             sal_Int32 nIndex;
1970             for( nIndex = 0; nIndex < nCount; nIndex++ )
1971             {
1972                 Any aTarget( xShapes->getByIndex( nIndex ) );
1973                 aTargets.push_back( aTarget );
1974                 if( bHasText )
1975                 {
1976                     Reference< XText > xText;
1977                     aTarget >>= xText;
1978                     if( !xText.is() || xText->getString().getLength() == 0 )
1979                         bHasText = false;
1980                 }
1981             }
1982         }
1983         else if ( maViewSelection.getValueType() == ::getCppuType((const Reference< XShape >*)0) )
1984         {
1985             aTargets.push_back( maViewSelection );
1986             Reference< XText > xText;
1987             maViewSelection >>= xText;
1988             if( !xText.is() || xText->getString().getLength() == 0 )
1989                 bHasText = false;
1990         }
1991         else if ( maViewSelection.getValueType() == ::getCppuType((const Reference< XTextCursor >*)0) )
1992         {
1993             Reference< XShape > xShape;
1994             std::list< sal_Int16 > aParaList;
1995             if( getTextSelection( maViewSelection, xShape, aParaList ) )
1996             {
1997                 ParagraphTarget aParaTarget;
1998                 aParaTarget.Shape = xShape;
1999 
2000                 std::list< sal_Int16 >::iterator aIter( aParaList.begin() );
2001                 for( ; aIter != aParaList.end(); aIter++ )
2002                 {
2003                     aParaTarget.Paragraph = (*aIter);
2004                     aTargets.push_back( makeAny( aParaTarget ) );
2005                 }
2006             }
2007         }
2008         else
2009         {
2010             DBG_ERROR("sd::CustomAnimationPane::onChange(), unknown view selection!" );
2011             return;
2012         }
2013     }
2014     else
2015     {
2016         // get selected effect
2017         EffectSequence::iterator aIter( maListSelection.begin() );
2018         const EffectSequence::iterator aEnd( maListSelection.end() );
2019         while( aIter != aEnd )
2020         {
2021             if( !bHasText || !(*aIter)->hasText() )
2022                 bHasText = false;
2023 
2024             if( sPresetId.getLength() == 0 )
2025             {
2026                 sPresetId = (*aIter)->getPresetId();
2027                 fDuration = (*aIter)->getDuration();
2028             }
2029 
2030             aTargets.push_back( (*aIter++)->getTarget() );
2031         }
2032     }
2033 
2034     CustomAnimationCreateDialog* pDlg = new CustomAnimationCreateDialog( this, this, aTargets, bHasText, sPresetId, fDuration );
2035     if( pDlg->Execute() )
2036     {
2037         addUndo();
2038         fDuration = pDlg->getSelectedDuration();
2039         CustomAnimationPresetPtr pDescriptor = pDlg->getSelectedPreset();
2040         if( pDescriptor.get() )
2041         {
2042             if( bCreate )
2043             {
2044                 mpCustomAnimationList->SelectAll( sal_False );
2045 
2046                 // gather shapes from the selection
2047                 std::vector< Any >::iterator aIter( aTargets.begin() );
2048                 const std::vector< Any >::iterator aEnd( aTargets.end() );
2049                 bool bFirst = true;
2050                 for( ; aIter != aEnd; aIter++ )
2051                 {
2052                     CustomAnimationEffectPtr pCreated = mpMainSequence->append( pDescriptor, (*aIter), fDuration );
2053 
2054                     // if only one shape with text and no fill or outline is selected, animate only by first level paragraphs
2055                     if( bHasText && (aTargets.size() == 1) )
2056                     {
2057                         Reference< XShape > xShape( (*aIter), UNO_QUERY );
2058                         if( xShape.is() && !hasVisibleShape( xShape ) )
2059                         {
2060                             mpMainSequence->createTextGroup( pCreated, 1, -1.0, sal_False, sal_False );
2061                         }
2062                     }
2063 
2064                     if( bFirst )
2065                         bFirst = false;
2066                     else
2067                         pCreated->setNodeType( EffectNodeType::WITH_PREVIOUS );
2068 
2069                     if( pCreated.get() )
2070                     {
2071                         mpCustomAnimationList->select( pCreated );
2072                     }
2073                 }
2074             }
2075             else
2076             {
2077                 MainSequenceRebuildGuard aGuard( mpMainSequence );
2078 
2079                 // get selected effect
2080                 EffectSequence::iterator aIter( maListSelection.begin() );
2081                 const EffectSequence::iterator aEnd( maListSelection.end() );
2082                 while( aIter != aEnd )
2083                 {
2084                     CustomAnimationEffectPtr pEffect = (*aIter++);
2085 
2086                     EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
2087                     if( !pEffectSequence )
2088                         pEffectSequence = mpMainSequence.get();
2089 
2090                     pEffectSequence->replace( pEffect, pDescriptor, fDuration );
2091                 }
2092             }
2093         }
2094         else
2095         {
2096             PathKind eKind = pDlg->getCreatePathKind();
2097             if( eKind != NONE )
2098                 createPath( eKind, aTargets, fDuration );
2099         }
2100         mrBase.GetDocShell()->SetModified();
2101     }
2102 
2103     delete pDlg;
2104 
2105     updateControls();
2106 
2107     // stop running preview from dialog
2108     SlideShow::Stop( mrBase );
2109 }
2110 
createPath(PathKind eKind,std::vector<Any> & rTargets,double fDuration)2111 void CustomAnimationPane::createPath( PathKind eKind, std::vector< Any >& rTargets, double fDuration)
2112 {
2113     sal_uInt16 nSID = 0;
2114 
2115     switch( eKind )
2116     {
2117     case CURVE:     nSID = SID_DRAW_BEZIER_NOFILL; break;
2118     case POLYGON:   nSID = SID_DRAW_POLYGON_NOFILL; break;
2119     case FREEFORM:  nSID = SID_DRAW_FREELINE_NOFILL; break;
2120     default: break;
2121     }
2122 
2123     if( nSID )
2124     {
2125         DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >(
2126             FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get());
2127 
2128         if( pViewShell )
2129         {
2130             DrawView* pView = pViewShell->GetDrawView();
2131             if( pView )
2132                 pView->UnmarkAllObj();
2133 
2134             std::vector< Any > aTargets( 1, Any( fDuration ) );
2135             aTargets.insert( aTargets.end(), rTargets.begin(), rTargets.end() );
2136             Sequence< Any > aTargetSequence( comphelper::containerToSequence( aTargets ) );
2137             const SfxUnoAnyItem aItem( SID_ADD_MOTION_PATH, Any( aTargetSequence ) );
2138             pViewShell->GetViewFrame()->GetDispatcher()->Execute( nSID, SFX_CALLMODE_ASYNCHRON, &aItem, 0 );
2139         }
2140     }
2141 }
2142 
onRemove()2143 void CustomAnimationPane::onRemove()
2144 {
2145     if( !maListSelection.empty() )
2146     {
2147         addUndo();
2148 
2149         MainSequenceRebuildGuard aGuard( mpMainSequence );
2150 
2151         EffectSequence aList( maListSelection );
2152 
2153         EffectSequence::iterator aIter( aList.begin() );
2154         const EffectSequence::iterator aEnd( aList.end() );
2155         while( aIter != aEnd )
2156         {
2157             CustomAnimationEffectPtr pEffect = (*aIter++);
2158             if( pEffect->getEffectSequence() )
2159                 pEffect->getEffectSequence()->remove( pEffect );
2160         }
2161 
2162         maListSelection.clear();
2163         mrBase.GetDocShell()->SetModified();
2164     }
2165 }
2166 
remove(CustomAnimationEffectPtr & pEffect)2167 void CustomAnimationPane::remove( CustomAnimationEffectPtr& pEffect )
2168 {
2169     if( pEffect->getEffectSequence() )
2170     {
2171         addUndo();
2172         pEffect->getEffectSequence()->remove( pEffect );
2173         mrBase.GetDocShell()->SetModified();
2174     }
2175 }
2176 
onChangeStart()2177 void CustomAnimationPane::onChangeStart()
2178 {
2179     if( mpLBStart->GetSelectEntryCount() == 1 )
2180     {
2181         sal_Int16 nNodeType;
2182         sal_uInt16 nPos= mpLBStart->GetSelectEntryPos();
2183         switch( nPos )
2184         {
2185         case 0: nNodeType = EffectNodeType::ON_CLICK; break;
2186         case 1: nNodeType = EffectNodeType::WITH_PREVIOUS; break;
2187         case 2: nNodeType = EffectNodeType::AFTER_PREVIOUS; break;
2188         default:
2189             return;
2190         }
2191 
2192         onChangeStart( nNodeType );
2193     }
2194 }
2195 
onChangeStart(sal_Int16 nNodeType)2196 void CustomAnimationPane::onChangeStart( sal_Int16 nNodeType )
2197 {
2198     addUndo();
2199 
2200     MainSequenceRebuildGuard aGuard( mpMainSequence );
2201 
2202     bool bNeedRebuild = false;
2203 
2204     EffectSequence::iterator aIter( maListSelection.begin() );
2205     const EffectSequence::iterator aEnd( maListSelection.end() );
2206     while( aIter != aEnd )
2207     {
2208         CustomAnimationEffectPtr pEffect = (*aIter++);
2209         if( pEffect->getNodeType() != nNodeType )
2210         {
2211             pEffect->setNodeType( nNodeType );
2212             bNeedRebuild = true;
2213         }
2214     }
2215 
2216     if( bNeedRebuild )
2217     {
2218         mpMainSequence->rebuild();
2219         updateControls();
2220         mrBase.GetDocShell()->SetModified();
2221     }
2222 }
2223 
onChangeProperty()2224 void CustomAnimationPane::onChangeProperty()
2225 {
2226     if( mpLBProperty->getSubControl() )
2227     {
2228         addUndo();
2229 
2230         MainSequenceRebuildGuard aGuard( mpMainSequence );
2231 
2232         const Any aValue( mpLBProperty->getSubControl()->getValue() );
2233 
2234         bool bNeedUpdate = false;
2235 
2236         // change selected effect
2237         EffectSequence::iterator aIter( maListSelection.begin() );
2238         const EffectSequence::iterator aEnd( maListSelection.end() );
2239         while( aIter != aEnd )
2240         {
2241             CustomAnimationEffectPtr pEffect = (*aIter++);
2242 
2243             if( setProperty1Value( mnPropertyType, pEffect, aValue ) )
2244                 bNeedUpdate = true;
2245         }
2246 
2247         if( bNeedUpdate )
2248         {
2249             mpMainSequence->rebuild();
2250             updateControls();
2251             mrBase.GetDocShell()->SetModified();
2252         }
2253 
2254         onPreview( false );
2255     }
2256 }
2257 
onChangeSpeed()2258 void CustomAnimationPane::onChangeSpeed()
2259 {
2260     if( mpCBSpeed->GetSelectEntryCount() == 1 )
2261     {
2262         addUndo();
2263 
2264         MainSequenceRebuildGuard aGuard( mpMainSequence );
2265 
2266         double fDuration;
2267 
2268         sal_uInt16 nPos= mpCBSpeed->GetSelectEntryPos();
2269 
2270         switch( nPos )
2271         {
2272         case 0: fDuration = 5.0; break;
2273         case 1: fDuration = 3.0; break;
2274         case 2: fDuration = 2.0; break;
2275         case 3: fDuration = 1.0; break;
2276         case 4: fDuration = 0.5; break;
2277         default:
2278             return;
2279         }
2280 
2281         // change selected effect
2282         EffectSequence::iterator aIter( maListSelection.begin() );
2283         const EffectSequence::iterator aEnd( maListSelection.end() );
2284         while( aIter != aEnd )
2285         {
2286             CustomAnimationEffectPtr pEffect = (*aIter++);
2287             pEffect->setDuration( fDuration );
2288         }
2289 
2290         mpMainSequence->rebuild();
2291         updateControls();
2292         mrBase.GetDocShell()->SetModified();
2293 
2294         onPreview( false );
2295     }
2296 }
2297 
2298 /// this link is called when the property box is modified by the user
IMPL_LINK(CustomAnimationPane,implPropertyHdl,Control *,EMPTYARG)2299 IMPL_LINK( CustomAnimationPane, implPropertyHdl, Control*, EMPTYARG )
2300 {
2301     onChangeProperty();
2302     return 0;
2303 }
2304 
2305 /// this link is called when one of the controls is modified
IMPL_LINK(CustomAnimationPane,implControlHdl,Control *,pControl)2306 IMPL_LINK( CustomAnimationPane, implControlHdl, Control*, pControl )
2307 {
2308     if( pControl == mpPBAddEffect )
2309         onChange(true);
2310     else if( pControl == mpPBChangeEffect )
2311         onChange(false);
2312     else if( pControl == mpPBRemoveEffect )
2313         onRemove();
2314     else if( pControl == mpLBStart )
2315         onChangeStart();
2316     else if( pControl == mpCBSpeed )
2317         onChangeSpeed();
2318     else if( pControl == mpPBPropertyMore )
2319         showOptions();
2320     else if( pControl == mpPBMoveUp )
2321         moveSelection( true );
2322     else if( pControl == mpPBMoveDown )
2323         moveSelection( false );
2324     else if( pControl == mpPBPlay )
2325         onPreview( true );
2326     else if( pControl == mpPBSlideShow )
2327     {
2328         mrBase.StartPresentation();
2329     }
2330     else if( pControl == mpCBAutoPreview )
2331     {
2332         SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
2333         pOptions->SetPreviewChangedEffects( mpCBAutoPreview->IsChecked() ? sal_True : sal_False );
2334     }
2335 
2336     updateControls();
2337 
2338     return 0;
2339 }
2340 
IMPL_LINK(CustomAnimationPane,lateInitCallback,Timer *,EMPTYARG)2341 IMPL_LINK(CustomAnimationPane, lateInitCallback, Timer*, EMPTYARG )
2342 {
2343     // Call getPresets() to initiate the (expensive) construction of the
2344     // presets list.
2345     getPresets();
2346 
2347     // update selection and control states
2348     onSelectionChanged();
2349 
2350     return 0;
2351 }
2352 
moveSelection(bool bUp)2353 void CustomAnimationPane::moveSelection( bool bUp )
2354 {
2355     if( maListSelection.empty() )
2356         return;
2357 
2358     EffectSequenceHelper* pSequence = maListSelection.front()->getEffectSequence();
2359     if( pSequence == 0 )
2360         return;
2361 
2362     addUndo();
2363 
2364     bool bChanged = false;
2365 
2366     MainSequenceRebuildGuard aGuard( mpMainSequence );
2367     EffectSequence& rEffectSequence = pSequence->getSequence();
2368 
2369     if( bUp )
2370     {
2371         EffectSequence::iterator aIter( maListSelection.begin() );
2372         const EffectSequence::iterator aEnd( maListSelection.end() );
2373 
2374         while( aIter != aEnd )
2375         {
2376             CustomAnimationEffectPtr pEffect = (*aIter++);
2377 
2378             EffectSequence::iterator aEffectPos( pSequence->find( pEffect ) );
2379             if( aEffectPos != rEffectSequence.end() )
2380             {
2381                 EffectSequence::iterator aInsertPos( rEffectSequence.erase( aEffectPos ) );
2382 
2383                 if( aInsertPos != rEffectSequence.begin() )
2384                 {
2385                     aInsertPos--;
2386                     while( (aInsertPos != rEffectSequence.begin()) && !mpCustomAnimationList->isExpanded(*aInsertPos))
2387                         aInsertPos--;
2388 
2389                     rEffectSequence.insert( aInsertPos, pEffect );
2390                 }
2391                 else
2392                 {
2393                     rEffectSequence.push_front( pEffect );
2394                 }
2395                 bChanged = true;
2396             }
2397         }
2398     }
2399     else
2400     {
2401         EffectSequence::reverse_iterator aIter( maListSelection.rbegin() );
2402         const EffectSequence::reverse_iterator aEnd( maListSelection.rend() );
2403 
2404         while( aIter != aEnd )
2405         {
2406             CustomAnimationEffectPtr pEffect = (*aIter++);
2407 
2408             EffectSequence::iterator aEffectPos( pSequence->find( pEffect ) );
2409             if( aEffectPos != rEffectSequence.end() )
2410             {
2411                 EffectSequence::iterator aInsertPos( rEffectSequence.erase( aEffectPos ) );
2412 
2413                 if( aInsertPos != rEffectSequence.end() )
2414                 {
2415                     aInsertPos++;
2416                     while( (aInsertPos != rEffectSequence.end()) && !mpCustomAnimationList->isExpanded(*aInsertPos))
2417                         aInsertPos++;
2418 
2419                     rEffectSequence.insert( aInsertPos, pEffect );
2420                 }
2421                 else
2422                 {
2423                     rEffectSequence.push_back( pEffect );
2424                 }
2425                 bChanged = true;
2426             }
2427         }
2428     }
2429 
2430     if( bChanged )
2431     {
2432         mpMainSequence->rebuild();
2433         updateControls();
2434         mrBase.GetDocShell()->SetModified();
2435     }
2436 }
2437 
onPreview(bool bForcePreview)2438 void CustomAnimationPane::onPreview( bool bForcePreview )
2439 {
2440     if( !bForcePreview && !mpCBAutoPreview->IsChecked() )
2441         return;
2442 
2443     if( maListSelection.empty() )
2444     {
2445         rtl::Reference< MotionPathTag > xMotionPathTag;
2446         MotionPathTagVector::iterator aIter;
2447         for( aIter = maMotionPathTags.begin(); aIter != maMotionPathTags.end(); aIter++ )
2448         {
2449             if( (*aIter)->isSelected() )
2450             {
2451                 xMotionPathTag = (*aIter);
2452                 break;
2453             }
2454         }
2455 
2456         if( xMotionPathTag.is() )
2457         {
2458             MainSequencePtr pSequence( new MainSequence() );
2459             pSequence->append( xMotionPathTag->getEffect()->clone() );
2460             preview( pSequence->getRootNode() );
2461         }
2462         else
2463         {
2464             Reference< XAnimationNodeSupplier > xNodeSupplier( mxCurrentPage, UNO_QUERY );
2465             if( !xNodeSupplier.is() )
2466                 return;
2467 
2468             preview( xNodeSupplier->getAnimationNode() );
2469         }
2470     }
2471     else
2472     {
2473         MainSequencePtr pSequence( new MainSequence() );
2474 
2475         EffectSequence::iterator aIter( maListSelection.begin() );
2476         const EffectSequence::iterator aEnd( maListSelection.end() );
2477 
2478         while( aIter != aEnd )
2479         {
2480             CustomAnimationEffectPtr pEffect = (*aIter++);
2481             pSequence->append( pEffect->clone() );
2482         }
2483 
2484         preview( pSequence->getRootNode() );
2485     }
2486 }
2487 
preview(const Reference<XAnimationNode> & xAnimationNode)2488 void CustomAnimationPane::preview( const Reference< XAnimationNode >& xAnimationNode )
2489 {
2490     Reference< XTimeContainer > xRoot(::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.ParallelTimeContainer"))), UNO_QUERY);
2491     if( xRoot.is() )
2492     {
2493         Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 );
2494         aUserData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) );
2495         aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT;
2496         xRoot->setUserData( aUserData );
2497         xRoot->appendChild( xAnimationNode );
2498 
2499         Reference< XAnimationNode > xNode( xRoot, UNO_QUERY );
2500         SlideShow::StartPreview( mrBase, mxCurrentPage, xNode );
2501     }
2502 }
2503 
2504 
2505 // ICustomAnimationListController
onSelect()2506 void CustomAnimationPane::onSelect()
2507 {
2508     maListSelection = mpCustomAnimationList->getSelection();
2509     updateControls();
2510     markShapesFromSelectedEffects();
2511 }
2512 
2513 
2514 
2515 
getPresets(void)2516 const CustomAnimationPresets& CustomAnimationPane::getPresets (void)
2517 {
2518     if (mpCustomAnimationPresets == NULL)
2519         mpCustomAnimationPresets = &CustomAnimationPresets::getCustomAnimationPresets();
2520     return *mpCustomAnimationPresets;
2521 }
2522 
2523 
2524 
markShapesFromSelectedEffects()2525 void CustomAnimationPane::markShapesFromSelectedEffects()
2526 {
2527     if( !maSelectionLock.isLocked() )
2528     {
2529         ScopeLockGuard aGuard( maSelectionLock );
2530         DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >(
2531             FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get());
2532         DrawView* pView = pViewShell ? pViewShell->GetDrawView() : NULL;
2533 
2534         if( pView )
2535         {
2536             pView->UnmarkAllObj();
2537             EffectSequence::iterator aIter( maListSelection.begin() );
2538             const EffectSequence::iterator aEnd( maListSelection.end() );
2539             while( aIter != aEnd )
2540             {
2541                 CustomAnimationEffectPtr pEffect = (*aIter++);
2542 
2543                 Reference< XShape > xShape( pEffect->getTargetShape() );
2544                 SdrObject* pObj = GetSdrObjectFromXShape( xShape );
2545                 if( pObj )
2546                     pView->MarkObj(pObj, pView->GetSdrPageView(), sal_False, sal_False);
2547             }
2548         }
2549     }
2550 }
2551 
2552 
updatePathFromMotionPathTag(const rtl::Reference<MotionPathTag> & xTag)2553 void CustomAnimationPane::updatePathFromMotionPathTag( const rtl::Reference< MotionPathTag >& xTag )
2554 {
2555     MainSequenceRebuildGuard aGuard( mpMainSequence );
2556     if( xTag.is() )
2557     {
2558         SdrPathObj* pPathObj = xTag->getPathObj();
2559         CustomAnimationEffectPtr pEffect = xTag->getEffect();
2560         if( (pPathObj != 0) && pEffect.get() != 0 )
2561         {
2562             ::svl::IUndoManager* pManager = mrBase.GetDocShell()->GetUndoManager();
2563             if( pManager )
2564             {
2565                 SdPage* pPage = SdPage::getImplementation( mxCurrentPage );
2566                 if( pPage )
2567                     pManager->AddUndoAction( new UndoAnimationPath( mrBase.GetDocShell()->GetDoc(), pPage, pEffect->getNode() ) );
2568             }
2569 
2570             pEffect->updatePathFromSdrPathObj( *pPathObj );
2571         }
2572     }
2573 }
2574 
2575 // ====================================================================
2576 
createCustomAnimationPanel(::Window * pParent,ViewShellBase & rBase)2577 ::Window * createCustomAnimationPanel( ::Window* pParent, ViewShellBase& rBase )
2578 {
2579     DialogListBox* pWindow = 0;
2580 
2581     DrawDocShell* pDocSh = rBase.GetDocShell();
2582     if( pDocSh )
2583     {
2584         pWindow = new DialogListBox( pParent, WB_CLIPCHILDREN|WB_TABSTOP|WB_AUTOHSCROLL );
2585         const Size aMinSize( pWindow->LogicToPixel( Size( 80, 256 ), MAP_APPFONT ) );
2586         pWindow->SetSizePixel(aMinSize);
2587         pWindow->SetBackground(Wallpaper(Color(COL_BLUE)));
2588 
2589         ::Window* pPaneWindow = new CustomAnimationPane( pWindow, rBase, aMinSize );
2590         pWindow->SetChildWindow( pPaneWindow, aMinSize );
2591         pWindow->SetText( pPaneWindow->GetText() );
2592     }
2593 
2594     return pWindow;
2595 }
2596 
2597 
2598 
2599 
getCustomAnimationPanelMinimumHeight(::Window * pDialog)2600 sal_Int32 getCustomAnimationPanelMinimumHeight (::Window* pDialog)
2601 {
2602     if (pDialog != NULL)
2603         return pDialog->LogicToPixel(Size( 80, 256 ), MAP_APPFONT).Height();
2604     else
2605         return 0;
2606 }
2607 
2608 }
2609