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