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 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 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 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 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 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 298 void CustomAnimationPane::Resize() 299 { 300 updateLayout(); 301 } 302 303 void CustomAnimationPane::StateChanged( StateChangedType nStateChange ) 304 { 305 Control::StateChanged( nStateChange ); 306 307 if( nStateChange == STATE_CHANGE_VISIBLE ) 308 updateMotionPathTags(); 309 } 310 311 void CustomAnimationPane::KeyInput( const KeyEvent& rKEvt ) 312 { 313 if( mpCustomAnimationList ) 314 mpCustomAnimationList->KeyInput( rKEvt ); 315 } 316 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 330 void CustomAnimationPane::removeListener() 331 { 332 Link aLink( LINK(this,CustomAnimationPane,EventMultiplexerListener) ); 333 mrBase.GetEventMultiplexer()->RemoveEventListener( aLink ); 334 } 335 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 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 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 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 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 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 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 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 1054 void CustomAnimationPane::onDoubleClick() 1055 { 1056 showOptions(); 1057 } 1058 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 1078 void CustomAnimationPane::DataChanged (const DataChangedEvent& rEvent) 1079 { 1080 (void)rEvent; 1081 UpdateLook(); 1082 } 1083 1084 1085 1086 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 2505 void CustomAnimationPane::onSelect() 2506 { 2507 maListSelection = mpCustomAnimationList->getSelection(); 2508 updateControls(); 2509 markShapesFromSelectedEffects(); 2510 } 2511 2512 2513 2514 2515 const CustomAnimationPresets& CustomAnimationPane::getPresets (void) 2516 { 2517 if (mpCustomAnimationPresets == NULL) 2518 mpCustomAnimationPresets = &CustomAnimationPresets::getCustomAnimationPresets(); 2519 return *mpCustomAnimationPresets; 2520 } 2521 2522 2523 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 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 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 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