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