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 aplied all other options 1699 // above 1700 1701 sal_Int32 nTextGrouping = 0; 1702 sal_Bool bAnimateForm = sal_True, bTextReverse = sal_False; 1703 double fTextGroupingAuto = -1.0; 1704 1705 if( bHasTextGrouping ) 1706 pResultSet->getPropertyValue(nHandleTextGrouping) >>= nTextGrouping; 1707 1708 if( bHasAnimateForm ) 1709 pResultSet->getPropertyValue(nHandleAnimateForm) >>= bAnimateForm; 1710 1711 if( bHasTextGroupingAuto ) 1712 pResultSet->getPropertyValue(nHandleTextGroupingAuto) >>= fTextGroupingAuto; 1713 1714 if( bHasTextReverse ) 1715 pResultSet->getPropertyValue(nHandleTextReverse) >>= bTextReverse; 1716 1717 EffectSequence const aSelectedEffects( maListSelection ); 1718 EffectSequence::const_iterator iter( aSelectedEffects.begin() ); 1719 const EffectSequence::const_iterator iEnd( aSelectedEffects.end() ); 1720 while( iter != iEnd ) 1721 { 1722 CustomAnimationEffectPtr const& pEffect = (*iter++); 1723 1724 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence(); 1725 if( !pEffectSequence ) 1726 pEffectSequence = mpMainSequence.get(); 1727 1728 sal_Int32 nGroupId = pEffect->getGroupId(); 1729 CustomAnimationTextGroupPtr pTextGroup; 1730 if( (nGroupId != -1) ) 1731 { 1732 // use existing group 1733 pTextGroup = pEffectSequence->findGroup( nGroupId ); 1734 } 1735 else 1736 { 1737 // somethings changed so we need a group now 1738 pTextGroup = pEffectSequence->createTextGroup( pEffect, nTextGrouping, fTextGroupingAuto, bAnimateForm, bTextReverse ); 1739 bChanged = true; 1740 } 1741 1742 //#Bug 119988# 1743 /************************************************************************/ 1744 /* 1745 Note, the setAnimateForm means set the animation from TextGroup to Object's Shape 1746 And on the UI in means "Animate attached shape" in "Effect Option" dialog 1747 The setTextGrouping means set animation to Object's Text, 1748 the nTextGrouping is Text Animation Type 1749 nTextGrouping = -1 is "As one Object", means no text animation. 1750 1751 The previous call order first do the setTextGrouping and then do the setAnimateForm, 1752 that will cause such defect: in the setTextGrouping, the effect has been removed, 1753 but in setAnimateForm still need this effect, then a NULL pointer of that effect will 1754 be gotten, and cause crash. 1755 1756 []bHasAnimateForm means the UI has changed, bAnimateForm is it value 1757 1758 So if create a new textgroup animation, the following animation will never be run! 1759 Since the ��Animate attached shape�� is default checked. 1760 And the bHasAnimateForm default is false, and if user uncheck it the value bAnimateForm will be false, 1761 it same as the TextGroup��s default value, also could not be run setAnimateForm. 1762 if( bHasAnimateForm ) 1763 { 1764 if( pTextGroup->getAnimateForm() != bAnimateForm ) 1765 { 1766 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm ); 1767 bChanged = true; 1768 } 1769 } 1770 1771 In setTextGrouping, there are three case: 1772 1. Create new text effects for empty TextGroup 1773 2. Remove all text effects of TextGroup (nTextGrouping == -1) 1774 3. Change all the text effects�� start type 1775 1776 So here is the right logic: 1777 If set the animation from text to shape and remove text animation, 1778 should do setAnimateForm first, then do setTextGrouping. 1779 Other case,do setTextGrouping first, then do setAnimateForm. 1780 1781 */ 1782 /************************************************************************/ 1783 1784 bool bDoSetAnimateFormFirst = false; 1785 bool bNeedDoSetAnimateForm = false; 1786 1787 if( bHasAnimateForm ) 1788 { 1789 if( pTextGroup->getAnimateForm() != bAnimateForm ) 1790 { 1791 if( (pTextGroup->getTextGrouping() >= 0) && (nTextGrouping == -1 ) ) 1792 { 1793 bDoSetAnimateFormFirst = true; 1794 } 1795 bNeedDoSetAnimateForm = true; 1796 } 1797 } 1798 1799 if (bDoSetAnimateFormFirst) 1800 { 1801 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm ); 1802 bChanged = true; 1803 } 1804 1805 if( bHasTextGrouping ) 1806 { 1807 if( (pTextGroup->getTextGrouping() != nTextGrouping) ) 1808 { 1809 pEffectSequence->setTextGrouping( pTextGroup, nTextGrouping ); 1810 bChanged = true; 1811 } 1812 } 1813 1814 if (!bDoSetAnimateFormFirst&&bNeedDoSetAnimateForm) 1815 { 1816 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm ); 1817 bChanged = true; 1818 } 1819 1820 if( bHasTextGroupingAuto ) 1821 { 1822 if( pTextGroup->getTextGroupingAuto() != fTextGroupingAuto ) 1823 { 1824 pEffectSequence->setTextGroupingAuto( pTextGroup, fTextGroupingAuto ); 1825 bChanged = true; 1826 } 1827 } 1828 1829 if( bHasTextReverse ) 1830 { 1831 if( pTextGroup->getTextReverse() != bTextReverse ) 1832 { 1833 pEffectSequence->setTextReverse( pTextGroup, bTextReverse ); 1834 bChanged = true; 1835 } 1836 } 1837 } 1838 } 1839 1840 if( bChanged ) 1841 { 1842 mpMainSequence->rebuild(); 1843 updateControls(); 1844 mrBase.GetDocShell()->SetModified(); 1845 } 1846 } 1847 1848 void CustomAnimationPane::showOptions( sal_uInt16 nPage /* = 0 */ ) 1849 { 1850 STLPropertySet* pSet = createSelectionSet(); 1851 1852 CustomAnimationDialog* pDlg = new CustomAnimationDialog( this, pSet, nPage ); 1853 if( pDlg->Execute() ) 1854 { 1855 addUndo(); 1856 changeSelection( pDlg->getResultSet(), pSet ); 1857 updateControls(); 1858 } 1859 1860 delete pDlg; 1861 } 1862 1863 void CustomAnimationPane::onChangeCurrentPage() 1864 { 1865 if( mxView.is() ) try 1866 { 1867 Reference< XDrawPage > xNewPage( mxView->getCurrentPage() ); 1868 if( xNewPage != mxCurrentPage ) 1869 { 1870 mxCurrentPage = xNewPage; 1871 SdPage* pPage = SdPage::getImplementation( mxCurrentPage ); 1872 if( pPage ) 1873 { 1874 mpMainSequence = pPage->getMainSequence(); 1875 mpCustomAnimationList->update( mpMainSequence ); 1876 } 1877 updateControls(); 1878 } 1879 } 1880 catch( Exception& ) 1881 { 1882 DBG_ERROR( "sd::CustomAnimationPane::onChangeCurrentPage(), exception catched!" ); 1883 } 1884 } 1885 1886 bool getTextSelection( const Any& rSelection, Reference< XShape >& xShape, std::list< sal_Int16 >& rParaList ) 1887 { 1888 Reference< XTextRange > xSelectedText; 1889 rSelection >>= xSelectedText; 1890 if( xSelectedText.is() ) try 1891 { 1892 xShape.set( xSelectedText->getText(), UNO_QUERY_THROW ); 1893 1894 Reference< XTextRangeCompare > xTextRangeCompare( xShape, UNO_QUERY_THROW ); 1895 Reference< XEnumerationAccess > xParaEnumAccess( xShape, UNO_QUERY_THROW ); 1896 Reference< XEnumeration > xParaEnum( xParaEnumAccess->createEnumeration(), UNO_QUERY_THROW ); 1897 Reference< XTextRange > xRange; 1898 Reference< XTextRange > xStart( xSelectedText->getStart() ); 1899 Reference< XTextRange > xEnd( xSelectedText->getEnd() ); 1900 1901 if( xTextRangeCompare->compareRegionEnds( xStart, xEnd ) < 0 ) 1902 { 1903 Reference< XTextRange > xTemp( xStart ); 1904 xStart = xEnd; 1905 xEnd = xTemp; 1906 } 1907 1908 sal_Int16 nPara = 0; 1909 while( xParaEnum->hasMoreElements() ) 1910 { 1911 xParaEnum->nextElement() >>= xRange; 1912 1913 // break if start of selection is prior to end of current paragraph 1914 if( xRange.is() && (xTextRangeCompare->compareRegionEnds( xStart, xRange ) >= 0 ) ) 1915 break; 1916 1917 nPara++; 1918 } 1919 1920 while( xRange.is() ) 1921 { 1922 if( xRange.is() && xRange->getString().getLength() ) 1923 rParaList.push_back( nPara ); 1924 1925 // break if end of selection is before or at end of current paragraph 1926 if( xRange.is() && xTextRangeCompare->compareRegionEnds( xEnd, xRange ) >= 0 ) 1927 break; 1928 1929 nPara++; 1930 1931 if( xParaEnum->hasMoreElements() ) 1932 xParaEnum->nextElement() >>= xRange; 1933 else 1934 xRange.clear(); 1935 } 1936 1937 return true; 1938 } 1939 catch( Exception& e ) 1940 { 1941 (void)e; 1942 DBG_ERROR( "sd::CustomAnimationPane::getTextSelection(), exception cought!" ); 1943 } 1944 1945 return false; 1946 } 1947 1948 void CustomAnimationPane::onChange( bool bCreate ) 1949 { 1950 bool bHasText = true; 1951 1952 // first create vector of targets for dialog preview 1953 std::vector< Any > aTargets; 1954 OUString sPresetId; 1955 double fDuration = 2.0f; 1956 1957 if( bCreate ) 1958 { 1959 // gather shapes from the selection 1960 Reference< XSelectionSupplier > xSel( mxView, UNO_QUERY_THROW ); 1961 maViewSelection = xSel->getSelection(); 1962 1963 if( maViewSelection.getValueType() == ::getCppuType((const Reference< XShapes >*)0) ) 1964 { 1965 Reference< XIndexAccess > xShapes; 1966 maViewSelection >>= xShapes; 1967 1968 sal_Int32 nCount = xShapes->getCount(); 1969 sal_Int32 nIndex; 1970 for( nIndex = 0; nIndex < nCount; nIndex++ ) 1971 { 1972 Any aTarget( xShapes->getByIndex( nIndex ) ); 1973 aTargets.push_back( aTarget ); 1974 if( bHasText ) 1975 { 1976 Reference< XText > xText; 1977 aTarget >>= xText; 1978 if( !xText.is() || xText->getString().getLength() == 0 ) 1979 bHasText = false; 1980 } 1981 } 1982 } 1983 else if ( maViewSelection.getValueType() == ::getCppuType((const Reference< XShape >*)0) ) 1984 { 1985 aTargets.push_back( maViewSelection ); 1986 Reference< XText > xText; 1987 maViewSelection >>= xText; 1988 if( !xText.is() || xText->getString().getLength() == 0 ) 1989 bHasText = false; 1990 } 1991 else if ( maViewSelection.getValueType() == ::getCppuType((const Reference< XTextCursor >*)0) ) 1992 { 1993 Reference< XShape > xShape; 1994 std::list< sal_Int16 > aParaList; 1995 if( getTextSelection( maViewSelection, xShape, aParaList ) ) 1996 { 1997 ParagraphTarget aParaTarget; 1998 aParaTarget.Shape = xShape; 1999 2000 std::list< sal_Int16 >::iterator aIter( aParaList.begin() ); 2001 for( ; aIter != aParaList.end(); aIter++ ) 2002 { 2003 aParaTarget.Paragraph = (*aIter); 2004 aTargets.push_back( makeAny( aParaTarget ) ); 2005 } 2006 } 2007 } 2008 else 2009 { 2010 DBG_ERROR("sd::CustomAnimationPane::onChange(), unknown view selection!" ); 2011 return; 2012 } 2013 } 2014 else 2015 { 2016 // get selected effect 2017 EffectSequence::iterator aIter( maListSelection.begin() ); 2018 const EffectSequence::iterator aEnd( maListSelection.end() ); 2019 while( aIter != aEnd ) 2020 { 2021 if( !bHasText || !(*aIter)->hasText() ) 2022 bHasText = false; 2023 2024 if( sPresetId.getLength() == 0 ) 2025 { 2026 sPresetId = (*aIter)->getPresetId(); 2027 fDuration = (*aIter)->getDuration(); 2028 } 2029 2030 aTargets.push_back( (*aIter++)->getTarget() ); 2031 } 2032 } 2033 2034 CustomAnimationCreateDialog* pDlg = new CustomAnimationCreateDialog( this, this, aTargets, bHasText, sPresetId, fDuration ); 2035 if( pDlg->Execute() ) 2036 { 2037 addUndo(); 2038 fDuration = pDlg->getSelectedDuration(); 2039 CustomAnimationPresetPtr pDescriptor = pDlg->getSelectedPreset(); 2040 if( pDescriptor.get() ) 2041 { 2042 if( bCreate ) 2043 { 2044 mpCustomAnimationList->SelectAll( sal_False ); 2045 2046 // gather shapes from the selection 2047 std::vector< Any >::iterator aIter( aTargets.begin() ); 2048 const std::vector< Any >::iterator aEnd( aTargets.end() ); 2049 bool bFirst = true; 2050 for( ; aIter != aEnd; aIter++ ) 2051 { 2052 CustomAnimationEffectPtr pCreated = mpMainSequence->append( pDescriptor, (*aIter), fDuration ); 2053 2054 // if only one shape with text and no fill or outline is selected, animate only by first level paragraphs 2055 if( bHasText && (aTargets.size() == 1) ) 2056 { 2057 Reference< XShape > xShape( (*aIter), UNO_QUERY ); 2058 if( xShape.is() && !hasVisibleShape( xShape ) ) 2059 { 2060 mpMainSequence->createTextGroup( pCreated, 1, -1.0, sal_False, sal_False ); 2061 } 2062 } 2063 2064 if( bFirst ) 2065 bFirst = false; 2066 else 2067 pCreated->setNodeType( EffectNodeType::WITH_PREVIOUS ); 2068 2069 if( pCreated.get() ) 2070 { 2071 mpCustomAnimationList->select( pCreated ); 2072 } 2073 } 2074 } 2075 else 2076 { 2077 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2078 2079 // get selected effect 2080 EffectSequence::iterator aIter( maListSelection.begin() ); 2081 const EffectSequence::iterator aEnd( maListSelection.end() ); 2082 while( aIter != aEnd ) 2083 { 2084 CustomAnimationEffectPtr pEffect = (*aIter++); 2085 2086 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence(); 2087 if( !pEffectSequence ) 2088 pEffectSequence = mpMainSequence.get(); 2089 2090 pEffectSequence->replace( pEffect, pDescriptor, fDuration ); 2091 } 2092 } 2093 } 2094 else 2095 { 2096 PathKind eKind = pDlg->getCreatePathKind(); 2097 if( eKind != NONE ) 2098 createPath( eKind, aTargets, fDuration ); 2099 } 2100 mrBase.GetDocShell()->SetModified(); 2101 } 2102 2103 delete pDlg; 2104 2105 updateControls(); 2106 2107 // stop running preview from dialog 2108 SlideShow::Stop( mrBase ); 2109 } 2110 2111 void CustomAnimationPane::createPath( PathKind eKind, std::vector< Any >& rTargets, double fDuration) 2112 { 2113 sal_uInt16 nSID = 0; 2114 2115 switch( eKind ) 2116 { 2117 case CURVE: nSID = SID_DRAW_BEZIER_NOFILL; break; 2118 case POLYGON: nSID = SID_DRAW_POLYGON_NOFILL; break; 2119 case FREEFORM: nSID = SID_DRAW_FREELINE_NOFILL; break; 2120 default: break; 2121 } 2122 2123 if( nSID ) 2124 { 2125 DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >( 2126 FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get()); 2127 2128 if( pViewShell ) 2129 { 2130 DrawView* pView = pViewShell->GetDrawView(); 2131 if( pView ) 2132 pView->UnmarkAllObj(); 2133 2134 std::vector< Any > aTargets( 1, Any( fDuration ) ); 2135 aTargets.insert( aTargets.end(), rTargets.begin(), rTargets.end() ); 2136 Sequence< Any > aTargetSequence( comphelper::containerToSequence( aTargets ) ); 2137 const SfxUnoAnyItem aItem( SID_ADD_MOTION_PATH, Any( aTargetSequence ) ); 2138 pViewShell->GetViewFrame()->GetDispatcher()->Execute( nSID, SFX_CALLMODE_ASYNCHRON, &aItem, 0 ); 2139 } 2140 } 2141 } 2142 2143 void CustomAnimationPane::onRemove() 2144 { 2145 if( !maListSelection.empty() ) 2146 { 2147 addUndo(); 2148 2149 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2150 2151 EffectSequence aList( maListSelection ); 2152 2153 EffectSequence::iterator aIter( aList.begin() ); 2154 const EffectSequence::iterator aEnd( aList.end() ); 2155 while( aIter != aEnd ) 2156 { 2157 CustomAnimationEffectPtr pEffect = (*aIter++); 2158 if( pEffect->getEffectSequence() ) 2159 pEffect->getEffectSequence()->remove( pEffect ); 2160 } 2161 2162 maListSelection.clear(); 2163 mrBase.GetDocShell()->SetModified(); 2164 } 2165 } 2166 2167 void CustomAnimationPane::remove( CustomAnimationEffectPtr& pEffect ) 2168 { 2169 if( pEffect->getEffectSequence() ) 2170 { 2171 addUndo(); 2172 pEffect->getEffectSequence()->remove( pEffect ); 2173 mrBase.GetDocShell()->SetModified(); 2174 } 2175 } 2176 2177 void CustomAnimationPane::onChangeStart() 2178 { 2179 if( mpLBStart->GetSelectEntryCount() == 1 ) 2180 { 2181 sal_Int16 nNodeType; 2182 sal_uInt16 nPos= mpLBStart->GetSelectEntryPos(); 2183 switch( nPos ) 2184 { 2185 case 0: nNodeType = EffectNodeType::ON_CLICK; break; 2186 case 1: nNodeType = EffectNodeType::WITH_PREVIOUS; break; 2187 case 2: nNodeType = EffectNodeType::AFTER_PREVIOUS; break; 2188 default: 2189 return; 2190 } 2191 2192 onChangeStart( nNodeType ); 2193 } 2194 } 2195 2196 void CustomAnimationPane::onChangeStart( sal_Int16 nNodeType ) 2197 { 2198 addUndo(); 2199 2200 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2201 2202 bool bNeedRebuild = false; 2203 2204 EffectSequence::iterator aIter( maListSelection.begin() ); 2205 const EffectSequence::iterator aEnd( maListSelection.end() ); 2206 while( aIter != aEnd ) 2207 { 2208 CustomAnimationEffectPtr pEffect = (*aIter++); 2209 if( pEffect->getNodeType() != nNodeType ) 2210 { 2211 pEffect->setNodeType( nNodeType ); 2212 bNeedRebuild = true; 2213 } 2214 } 2215 2216 if( bNeedRebuild ) 2217 { 2218 mpMainSequence->rebuild(); 2219 updateControls(); 2220 mrBase.GetDocShell()->SetModified(); 2221 } 2222 } 2223 2224 void CustomAnimationPane::onChangeProperty() 2225 { 2226 if( mpLBProperty->getSubControl() ) 2227 { 2228 addUndo(); 2229 2230 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2231 2232 const Any aValue( mpLBProperty->getSubControl()->getValue() ); 2233 2234 bool bNeedUpdate = false; 2235 2236 // change selected effect 2237 EffectSequence::iterator aIter( maListSelection.begin() ); 2238 const EffectSequence::iterator aEnd( maListSelection.end() ); 2239 while( aIter != aEnd ) 2240 { 2241 CustomAnimationEffectPtr pEffect = (*aIter++); 2242 2243 if( setProperty1Value( mnPropertyType, pEffect, aValue ) ) 2244 bNeedUpdate = true; 2245 } 2246 2247 if( bNeedUpdate ) 2248 { 2249 mpMainSequence->rebuild(); 2250 updateControls(); 2251 mrBase.GetDocShell()->SetModified(); 2252 } 2253 2254 onPreview( false ); 2255 } 2256 } 2257 2258 void CustomAnimationPane::onChangeSpeed() 2259 { 2260 if( mpCBSpeed->GetSelectEntryCount() == 1 ) 2261 { 2262 addUndo(); 2263 2264 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2265 2266 double fDuration; 2267 2268 sal_uInt16 nPos= mpCBSpeed->GetSelectEntryPos(); 2269 2270 switch( nPos ) 2271 { 2272 case 0: fDuration = 5.0; break; 2273 case 1: fDuration = 3.0; break; 2274 case 2: fDuration = 2.0; break; 2275 case 3: fDuration = 1.0; break; 2276 case 4: fDuration = 0.5; break; 2277 default: 2278 return; 2279 } 2280 2281 // change selected effect 2282 EffectSequence::iterator aIter( maListSelection.begin() ); 2283 const EffectSequence::iterator aEnd( maListSelection.end() ); 2284 while( aIter != aEnd ) 2285 { 2286 CustomAnimationEffectPtr pEffect = (*aIter++); 2287 pEffect->setDuration( fDuration ); 2288 } 2289 2290 mpMainSequence->rebuild(); 2291 updateControls(); 2292 mrBase.GetDocShell()->SetModified(); 2293 2294 onPreview( false ); 2295 } 2296 } 2297 2298 /// this link is called when the property box is modified by the user 2299 IMPL_LINK( CustomAnimationPane, implPropertyHdl, Control*, EMPTYARG ) 2300 { 2301 onChangeProperty(); 2302 return 0; 2303 } 2304 2305 /// this link is called when one of the controls is modified 2306 IMPL_LINK( CustomAnimationPane, implControlHdl, Control*, pControl ) 2307 { 2308 if( pControl == mpPBAddEffect ) 2309 onChange(true); 2310 else if( pControl == mpPBChangeEffect ) 2311 onChange(false); 2312 else if( pControl == mpPBRemoveEffect ) 2313 onRemove(); 2314 else if( pControl == mpLBStart ) 2315 onChangeStart(); 2316 else if( pControl == mpCBSpeed ) 2317 onChangeSpeed(); 2318 else if( pControl == mpPBPropertyMore ) 2319 showOptions(); 2320 else if( pControl == mpPBMoveUp ) 2321 moveSelection( true ); 2322 else if( pControl == mpPBMoveDown ) 2323 moveSelection( false ); 2324 else if( pControl == mpPBPlay ) 2325 onPreview( true ); 2326 else if( pControl == mpPBSlideShow ) 2327 { 2328 mrBase.StartPresentation(); 2329 } 2330 else if( pControl == mpCBAutoPreview ) 2331 { 2332 SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS); 2333 pOptions->SetPreviewChangedEffects( mpCBAutoPreview->IsChecked() ? sal_True : sal_False ); 2334 } 2335 2336 updateControls(); 2337 2338 return 0; 2339 } 2340 2341 IMPL_LINK(CustomAnimationPane, lateInitCallback, Timer*, EMPTYARG ) 2342 { 2343 // Call getPresets() to initiate the (expensive) construction of the 2344 // presets list. 2345 getPresets(); 2346 2347 // update selection and control states 2348 onSelectionChanged(); 2349 2350 return 0; 2351 } 2352 2353 void CustomAnimationPane::moveSelection( bool bUp ) 2354 { 2355 if( maListSelection.empty() ) 2356 return; 2357 2358 EffectSequenceHelper* pSequence = maListSelection.front()->getEffectSequence(); 2359 if( pSequence == 0 ) 2360 return; 2361 2362 addUndo(); 2363 2364 bool bChanged = false; 2365 2366 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2367 EffectSequence& rEffectSequence = pSequence->getSequence(); 2368 2369 if( bUp ) 2370 { 2371 EffectSequence::iterator aIter( maListSelection.begin() ); 2372 const EffectSequence::iterator aEnd( maListSelection.end() ); 2373 2374 while( aIter != aEnd ) 2375 { 2376 CustomAnimationEffectPtr pEffect = (*aIter++); 2377 2378 EffectSequence::iterator aEffectPos( pSequence->find( pEffect ) ); 2379 if( aEffectPos != rEffectSequence.end() ) 2380 { 2381 EffectSequence::iterator aInsertPos( rEffectSequence.erase( aEffectPos ) ); 2382 2383 if( aInsertPos != rEffectSequence.begin() ) 2384 { 2385 aInsertPos--; 2386 while( (aInsertPos != rEffectSequence.begin()) && !mpCustomAnimationList->isExpanded(*aInsertPos)) 2387 aInsertPos--; 2388 2389 rEffectSequence.insert( aInsertPos, pEffect ); 2390 } 2391 else 2392 { 2393 rEffectSequence.push_front( pEffect ); 2394 } 2395 bChanged = true; 2396 } 2397 } 2398 } 2399 else 2400 { 2401 EffectSequence::reverse_iterator aIter( maListSelection.rbegin() ); 2402 const EffectSequence::reverse_iterator aEnd( maListSelection.rend() ); 2403 2404 while( aIter != aEnd ) 2405 { 2406 CustomAnimationEffectPtr pEffect = (*aIter++); 2407 2408 EffectSequence::iterator aEffectPos( pSequence->find( pEffect ) ); 2409 if( aEffectPos != rEffectSequence.end() ) 2410 { 2411 EffectSequence::iterator aInsertPos( rEffectSequence.erase( aEffectPos ) ); 2412 2413 if( aInsertPos != rEffectSequence.end() ) 2414 { 2415 aInsertPos++; 2416 while( (aInsertPos != rEffectSequence.end()) && !mpCustomAnimationList->isExpanded(*aInsertPos)) 2417 aInsertPos++; 2418 2419 rEffectSequence.insert( aInsertPos, pEffect ); 2420 } 2421 else 2422 { 2423 rEffectSequence.push_back( pEffect ); 2424 } 2425 bChanged = true; 2426 } 2427 } 2428 } 2429 2430 if( bChanged ) 2431 { 2432 mpMainSequence->rebuild(); 2433 updateControls(); 2434 mrBase.GetDocShell()->SetModified(); 2435 } 2436 } 2437 2438 void CustomAnimationPane::onPreview( bool bForcePreview ) 2439 { 2440 if( !bForcePreview && !mpCBAutoPreview->IsChecked() ) 2441 return; 2442 2443 if( maListSelection.empty() ) 2444 { 2445 rtl::Reference< MotionPathTag > xMotionPathTag; 2446 MotionPathTagVector::iterator aIter; 2447 for( aIter = maMotionPathTags.begin(); aIter != maMotionPathTags.end(); aIter++ ) 2448 { 2449 if( (*aIter)->isSelected() ) 2450 { 2451 xMotionPathTag = (*aIter); 2452 break; 2453 } 2454 } 2455 2456 if( xMotionPathTag.is() ) 2457 { 2458 MainSequencePtr pSequence( new MainSequence() ); 2459 pSequence->append( xMotionPathTag->getEffect()->clone() ); 2460 preview( pSequence->getRootNode() ); 2461 } 2462 else 2463 { 2464 Reference< XAnimationNodeSupplier > xNodeSupplier( mxCurrentPage, UNO_QUERY ); 2465 if( !xNodeSupplier.is() ) 2466 return; 2467 2468 preview( xNodeSupplier->getAnimationNode() ); 2469 } 2470 } 2471 else 2472 { 2473 MainSequencePtr pSequence( new MainSequence() ); 2474 2475 EffectSequence::iterator aIter( maListSelection.begin() ); 2476 const EffectSequence::iterator aEnd( maListSelection.end() ); 2477 2478 while( aIter != aEnd ) 2479 { 2480 CustomAnimationEffectPtr pEffect = (*aIter++); 2481 pSequence->append( pEffect->clone() ); 2482 } 2483 2484 preview( pSequence->getRootNode() ); 2485 } 2486 } 2487 2488 void CustomAnimationPane::preview( const Reference< XAnimationNode >& xAnimationNode ) 2489 { 2490 Reference< XTimeContainer > xRoot(::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.ParallelTimeContainer"))), UNO_QUERY); 2491 if( xRoot.is() ) 2492 { 2493 Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 ); 2494 aUserData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) ); 2495 aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT; 2496 xRoot->setUserData( aUserData ); 2497 xRoot->appendChild( xAnimationNode ); 2498 2499 Reference< XAnimationNode > xNode( xRoot, UNO_QUERY ); 2500 SlideShow::StartPreview( mrBase, mxCurrentPage, xNode ); 2501 } 2502 } 2503 2504 2505 // ICustomAnimationListController 2506 void CustomAnimationPane::onSelect() 2507 { 2508 maListSelection = mpCustomAnimationList->getSelection(); 2509 updateControls(); 2510 markShapesFromSelectedEffects(); 2511 } 2512 2513 2514 2515 2516 const CustomAnimationPresets& CustomAnimationPane::getPresets (void) 2517 { 2518 if (mpCustomAnimationPresets == NULL) 2519 mpCustomAnimationPresets = &CustomAnimationPresets::getCustomAnimationPresets(); 2520 return *mpCustomAnimationPresets; 2521 } 2522 2523 2524 2525 void CustomAnimationPane::markShapesFromSelectedEffects() 2526 { 2527 if( !maSelectionLock.isLocked() ) 2528 { 2529 ScopeLockGuard aGuard( maSelectionLock ); 2530 DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >( 2531 FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get()); 2532 DrawView* pView = pViewShell ? pViewShell->GetDrawView() : NULL; 2533 2534 if( pView ) 2535 { 2536 pView->UnmarkAllObj(); 2537 EffectSequence::iterator aIter( maListSelection.begin() ); 2538 const EffectSequence::iterator aEnd( maListSelection.end() ); 2539 while( aIter != aEnd ) 2540 { 2541 CustomAnimationEffectPtr pEffect = (*aIter++); 2542 2543 Reference< XShape > xShape( pEffect->getTargetShape() ); 2544 SdrObject* pObj = GetSdrObjectFromXShape( xShape ); 2545 if( pObj ) 2546 pView->MarkObj(pObj, pView->GetSdrPageView(), sal_False, sal_False); 2547 } 2548 } 2549 } 2550 } 2551 2552 2553 void CustomAnimationPane::updatePathFromMotionPathTag( const rtl::Reference< MotionPathTag >& xTag ) 2554 { 2555 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2556 if( xTag.is() ) 2557 { 2558 SdrPathObj* pPathObj = xTag->getPathObj(); 2559 CustomAnimationEffectPtr pEffect = xTag->getEffect(); 2560 if( (pPathObj != 0) && pEffect.get() != 0 ) 2561 { 2562 ::svl::IUndoManager* pManager = mrBase.GetDocShell()->GetUndoManager(); 2563 if( pManager ) 2564 { 2565 SdPage* pPage = SdPage::getImplementation( mxCurrentPage ); 2566 if( pPage ) 2567 pManager->AddUndoAction( new UndoAnimationPath( mrBase.GetDocShell()->GetDoc(), pPage, pEffect->getNode() ) ); 2568 } 2569 2570 pEffect->updatePathFromSdrPathObj( *pPathObj ); 2571 } 2572 } 2573 } 2574 2575 // ==================================================================== 2576 2577 ::Window * createCustomAnimationPanel( ::Window* pParent, ViewShellBase& rBase ) 2578 { 2579 DialogListBox* pWindow = 0; 2580 2581 DrawDocShell* pDocSh = rBase.GetDocShell(); 2582 if( pDocSh ) 2583 { 2584 pWindow = new DialogListBox( pParent, WB_CLIPCHILDREN|WB_TABSTOP|WB_AUTOHSCROLL ); 2585 const Size aMinSize( pWindow->LogicToPixel( Size( 80, 256 ), MAP_APPFONT ) ); 2586 pWindow->SetSizePixel(aMinSize); 2587 pWindow->SetBackground(Wallpaper(Color(COL_BLUE))); 2588 2589 ::Window* pPaneWindow = new CustomAnimationPane( pWindow, rBase, aMinSize ); 2590 pWindow->SetChildWindow( pPaneWindow, aMinSize ); 2591 pWindow->SetText( pPaneWindow->GetText() ); 2592 } 2593 2594 return pWindow; 2595 } 2596 2597 2598 2599 2600 sal_Int32 getCustomAnimationPanelMinimumHeight (::Window* pDialog) 2601 { 2602 if (pDialog != NULL) 2603 return pDialog->LogicToPixel(Size( 80, 256 ), MAP_APPFONT).Height(); 2604 else 2605 return 0; 2606 } 2607 2608 } 2609