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