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