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