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