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 (mrBase.GetMainViewShell() != NULL) 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 SetBackground(::sfx2::sidebar::Theme::GetWallpaper(::sfx2::sidebar::Theme::Paint_PanelBackground)); 1094 if (mpFLModify != NULL) 1095 mpFLModify->SetBackground(Wallpaper()); 1096 if (mpFLEffect != NULL) 1097 mpFLEffect->SetBackground(Wallpaper()); 1098 if (mpFTStart != NULL) 1099 mpFTStart->SetBackground(Wallpaper()); 1100 if (mpFTProperty != NULL) 1101 mpFTProperty->SetBackground(Wallpaper()); 1102 if (mpFTSpeed != NULL) 1103 mpFTSpeed->SetBackground(Wallpaper()); 1104 if (mpFTChangeOrder != NULL) 1105 mpFTChangeOrder->SetBackground(Wallpaper()); 1106 if (mpFLSeperator1 != NULL) 1107 mpFLSeperator1->SetBackground(Wallpaper()); 1108 if (mpFLSeperator2 != NULL) 1109 mpFLSeperator2->SetBackground(Wallpaper()); 1110 } 1111 1112 1113 1114 1115 void addValue( STLPropertySet* pSet, sal_Int32 nHandle, const Any& rValue ) 1116 { 1117 switch( pSet->getPropertyState( nHandle ) ) 1118 { 1119 case STLPropertyState_AMBIGUOUS: 1120 // value is already ambiguous, do nothing 1121 break; 1122 case STLPropertyState_DIRECT: 1123 // set to ambiguous if existing value is different 1124 if( rValue != pSet->getPropertyValue( nHandle ) ) 1125 pSet->setPropertyState( nHandle, STLPropertyState_AMBIGUOUS ); 1126 break; 1127 case STLPropertyState_DEFAULT: 1128 // just set new value 1129 pSet->setPropertyValue( nHandle, rValue ); 1130 break; 1131 } 1132 } 1133 1134 static sal_Int32 calcMaxParaDepth( Reference< XShape > xTargetShape ) 1135 { 1136 sal_Int32 nMaxParaDepth = -1; 1137 1138 if( xTargetShape.is() ) 1139 { 1140 Reference< XEnumerationAccess > xText( xTargetShape, UNO_QUERY ); 1141 if( xText.is() ) 1142 { 1143 Reference< XPropertySet > xParaSet; 1144 const OUString strNumberingLevel( RTL_CONSTASCII_USTRINGPARAM("NumberingLevel") ); 1145 1146 Reference< XEnumeration > xEnumeration( xText->createEnumeration(), UNO_QUERY_THROW ); 1147 while( xEnumeration->hasMoreElements() ) 1148 { 1149 xEnumeration->nextElement() >>= xParaSet; 1150 if( xParaSet.is() ) 1151 { 1152 sal_Int32 nParaDepth = 0; 1153 xParaSet->getPropertyValue( strNumberingLevel ) >>= nParaDepth; 1154 1155 if( nParaDepth > nMaxParaDepth ) 1156 nMaxParaDepth = nParaDepth; 1157 } 1158 } 1159 } 1160 } 1161 1162 return nMaxParaDepth + 1; 1163 } 1164 1165 Any CustomAnimationPane::getProperty1Value( sal_Int32 nType, CustomAnimationEffectPtr pEffect ) 1166 { 1167 switch( nType ) 1168 { 1169 case nPropertyTypeDirection: 1170 case nPropertyTypeSpokes: 1171 case nPropertyTypeZoom: 1172 return makeAny( pEffect->getPresetSubType() ); 1173 1174 case nPropertyTypeColor: 1175 case nPropertyTypeFillColor: 1176 case nPropertyTypeFirstColor: 1177 case nPropertyTypeSecondColor: 1178 case nPropertyTypeCharColor: 1179 case nPropertyTypeLineColor: 1180 { 1181 const sal_Int32 nIndex = (nPropertyTypeFirstColor == nType) ? 0 : 1; 1182 return pEffect->getColor( nIndex ); 1183 } 1184 1185 case nPropertyTypeFont: 1186 return pEffect->getProperty( AnimationNodeType::SET, OUString( RTL_CONSTASCII_USTRINGPARAM("CharFontName") ), VALUE_TO ); 1187 1188 case nPropertyTypeCharHeight: 1189 { 1190 const OUString aAttributeName( RTL_CONSTASCII_USTRINGPARAM( "CharHeight" ) ); 1191 Any aValue( pEffect->getProperty( AnimationNodeType::SET, aAttributeName, VALUE_TO ) ); 1192 if( !aValue.hasValue() ) 1193 aValue = pEffect->getProperty( AnimationNodeType::ANIMATE, aAttributeName, VALUE_TO ); 1194 return aValue; 1195 } 1196 1197 case nPropertyTypeRotate: 1198 return pEffect->getTransformationProperty( AnimationTransformType::ROTATE, VALUE_BY); 1199 1200 case nPropertyTypeTransparency: 1201 return pEffect->getProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("Opacity")), VALUE_TO ); 1202 1203 case nPropertyTypeScale: 1204 return pEffect->getTransformationProperty( AnimationTransformType::SCALE, VALUE_BY ); 1205 1206 case nPropertyTypeCharDecoration: 1207 { 1208 Sequence< Any > aValues(3); 1209 aValues[0] = pEffect->getProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharWeight")), VALUE_TO ); 1210 aValues[1] = pEffect->getProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharPosture")), VALUE_TO ); 1211 aValues[2] = pEffect->getProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharUnderline")), VALUE_TO ); 1212 return makeAny( aValues ); 1213 } 1214 } 1215 1216 Any aAny; 1217 return aAny; 1218 } 1219 1220 bool CustomAnimationPane::setProperty1Value( sal_Int32 nType, CustomAnimationEffectPtr pEffect, const Any& rValue ) 1221 { 1222 bool bEffectChanged = false; 1223 switch( nType ) 1224 { 1225 case nPropertyTypeDirection: 1226 case nPropertyTypeSpokes: 1227 case nPropertyTypeZoom: 1228 { 1229 OUString aPresetSubType; 1230 rValue >>= aPresetSubType; 1231 if( aPresetSubType != pEffect->getPresetSubType() ) 1232 { 1233 getPresets().changePresetSubType( pEffect, aPresetSubType ); 1234 bEffectChanged = true; 1235 } 1236 } 1237 break; 1238 1239 case nPropertyTypeFillColor: 1240 case nPropertyTypeColor: 1241 case nPropertyTypeFirstColor: 1242 case nPropertyTypeSecondColor: 1243 case nPropertyTypeCharColor: 1244 case nPropertyTypeLineColor: 1245 { 1246 const sal_Int32 nIndex = (nPropertyTypeFirstColor == nType) ? 0 : 1; 1247 Any aOldColor( pEffect->getColor( nIndex ) ); 1248 if( aOldColor != rValue ) 1249 { 1250 pEffect->setColor( nIndex, rValue ); 1251 bEffectChanged = true; 1252 } 1253 } 1254 break; 1255 1256 case nPropertyTypeFont: 1257 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, OUString( RTL_CONSTASCII_USTRINGPARAM( "CharFontName" ) ), VALUE_TO, rValue ); 1258 break; 1259 1260 case nPropertyTypeCharHeight: 1261 { 1262 const OUString aAttributeName( RTL_CONSTASCII_USTRINGPARAM( "CharHeight" ) ); 1263 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, aAttributeName, VALUE_TO, rValue ); 1264 if( !bEffectChanged ) 1265 bEffectChanged = pEffect->setProperty( AnimationNodeType::ANIMATE, aAttributeName, VALUE_TO, rValue ); 1266 } 1267 break; 1268 case nPropertyTypeRotate: 1269 bEffectChanged = pEffect->setTransformationProperty( AnimationTransformType::ROTATE, VALUE_BY , rValue ); 1270 break; 1271 1272 case nPropertyTypeTransparency: 1273 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, OUString( RTL_CONSTASCII_USTRINGPARAM("Opacity") ), VALUE_TO, rValue ); 1274 break; 1275 1276 case nPropertyTypeScale: 1277 bEffectChanged = pEffect->setTransformationProperty( AnimationTransformType::SCALE, VALUE_BY, rValue ); 1278 break; 1279 1280 case nPropertyTypeCharDecoration: 1281 { 1282 Sequence< Any > aValues(3); 1283 rValue >>= aValues; 1284 bEffectChanged = pEffect->setProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharWeight")), VALUE_TO, aValues[0] ); 1285 bEffectChanged |= pEffect->setProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharPosture")), VALUE_TO, aValues[1] ); 1286 bEffectChanged |= pEffect->setProperty( AnimationNodeType::SET, OUString(RTL_CONSTASCII_USTRINGPARAM("CharUnderline")), VALUE_TO, aValues[2] ); 1287 } 1288 break; 1289 1290 } 1291 1292 return bEffectChanged; 1293 } 1294 1295 static sal_Bool hasVisibleShape( const Reference< XShape >& xShape ) 1296 { 1297 try 1298 { 1299 const OUString sShapeType( xShape->getShapeType() ); 1300 1301 if( sShapeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.presentation.TitleTextShape") ) || 1302 sShapeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.presentation.OutlinerShape") ) || 1303 sShapeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.presentation.SubtitleShape") ) || 1304 sShapeType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.drawing.TextShape") ) ) 1305 { 1306 const OUString sFillStyle( RTL_CONSTASCII_USTRINGPARAM("FillStyle" ) ); 1307 const OUString sLineStyle( RTL_CONSTASCII_USTRINGPARAM("LineStyle" ) ); 1308 Reference< XPropertySet > xSet( xShape, UNO_QUERY_THROW ); 1309 1310 FillStyle eFillStyle; 1311 xSet->getPropertyValue( sFillStyle ) >>= eFillStyle; 1312 1313 ::com::sun::star::drawing::LineStyle eLineStyle; 1314 xSet->getPropertyValue( sLineStyle ) >>= eLineStyle; 1315 1316 return eFillStyle != FillStyle_NONE || eLineStyle != ::com::sun::star::drawing::LineStyle_NONE; 1317 } 1318 } 1319 catch( Exception& e ) 1320 { 1321 (void)e; 1322 } 1323 return sal_True; 1324 } 1325 1326 STLPropertySet* CustomAnimationPane::createSelectionSet() 1327 { 1328 STLPropertySet* pSet = CustomAnimationDialog::createDefaultSet(); 1329 1330 pSet->setPropertyValue( nHandleCurrentPage, makeAny( mxCurrentPage ) ); 1331 1332 sal_Int32 nMaxParaDepth = 0; 1333 1334 // get options from selected effects 1335 EffectSequence::iterator aIter( maListSelection.begin() ); 1336 const EffectSequence::iterator aEnd( maListSelection.end() ); 1337 const CustomAnimationPresets& rPresets (getPresets()); 1338 while( aIter != aEnd ) 1339 { 1340 CustomAnimationEffectPtr pEffect = (*aIter++); 1341 1342 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence(); 1343 if( !pEffectSequence ) 1344 pEffectSequence = mpMainSequence.get(); 1345 1346 if( pEffect->hasText() ) 1347 { 1348 sal_Int32 n = calcMaxParaDepth(pEffect->getTargetShape()); 1349 if( n > nMaxParaDepth ) 1350 nMaxParaDepth = n; 1351 } 1352 1353 addValue( pSet, nHandleHasAfterEffect, makeAny( pEffect->hasAfterEffect() ) ); 1354 addValue( pSet, nHandleAfterEffectOnNextEffect, makeAny( pEffect->IsAfterEffectOnNext() ? sal_True : sal_False ) ); 1355 addValue( pSet, nHandleDimColor, pEffect->getDimColor() ); 1356 addValue( pSet, nHandleIterateType, makeAny( pEffect->getIterateType() ) ); 1357 1358 // convert absolute time to percentage value 1359 // This calculation is done in float to avoid some rounding artifacts. 1360 float fIterateInterval = (float)pEffect->getIterateInterval(); 1361 if( pEffect->getDuration() ) 1362 fIterateInterval = (float)(fIterateInterval / pEffect->getDuration() ); 1363 fIterateInterval *= 100.0; 1364 addValue( pSet, nHandleIterateInterval, makeAny( (double)fIterateInterval ) ); 1365 1366 addValue( pSet, nHandleBegin, makeAny( pEffect->getBegin() ) ); 1367 addValue( pSet, nHandleDuration, makeAny( pEffect->getDuration() ) ); 1368 addValue( pSet, nHandleStart, makeAny( pEffect->getNodeType() ) ); 1369 addValue( pSet, nHandleRepeat, makeAny( pEffect->getRepeatCount() ) ); 1370 addValue( pSet, nHandleEnd, pEffect->getEnd() ); 1371 addValue( pSet, nHandleRewind, makeAny( pEffect->getFill() ) ); 1372 1373 addValue( pSet, nHandlePresetId, makeAny( pEffect->getPresetId() ) ); 1374 1375 addValue( pSet, nHandleHasText, makeAny( (sal_Bool)pEffect->hasText() ) ); 1376 1377 addValue( pSet, nHandleHasVisibleShape, Any( hasVisibleShape( pEffect->getTargetShape() ) ) ); 1378 1379 Any aSoundSource; 1380 if( pEffect->getAudio().is() ) 1381 { 1382 aSoundSource = pEffect->getAudio()->getSource(); 1383 addValue( pSet, nHandleSoundVolumne, makeAny( pEffect->getAudio()->getVolume() ) ); 1384 // todo addValue( pSet, nHandleSoundEndAfterSlide, makeAny( pEffect->getAudio()->getEndAfterSlide() ) ); 1385 // this is now stored at the XCommand parameter sequence 1386 } 1387 else if( pEffect->getCommand() == EffectCommands::STOPAUDIO ) 1388 { 1389 aSoundSource = makeAny( (sal_Bool)sal_True ); 1390 } 1391 addValue( pSet, nHandleSoundURL, aSoundSource ); 1392 1393 sal_Int32 nGroupId = pEffect->getGroupId(); 1394 CustomAnimationTextGroupPtr pTextGroup; 1395 if( nGroupId != -1 ) 1396 pTextGroup = pEffectSequence->findGroup( nGroupId ); 1397 1398 addValue( pSet, nHandleTextGrouping, makeAny( pTextGroup.get() ? pTextGroup->getTextGrouping() : (sal_Int32)-1 ) ); 1399 addValue( pSet, nHandleAnimateForm, makeAny( pTextGroup.get() ? (sal_Bool)pTextGroup->getAnimateForm() : sal_True ) ); 1400 addValue( pSet, nHandleTextGroupingAuto, makeAny( pTextGroup.get() ? pTextGroup->getTextGroupingAuto() : (double)-1.0 ) ); 1401 addValue( pSet, nHandleTextReverse, makeAny( pTextGroup.get() ? (sal_Bool)pTextGroup->getTextReverse() : sal_False ) ); 1402 1403 if( pEffectSequence->getSequenceType() == EffectNodeType::INTERACTIVE_SEQUENCE ) 1404 { 1405 InteractiveSequence* pIS = static_cast< InteractiveSequence* >( pEffectSequence ); 1406 addValue( pSet, nHandleTrigger, makeAny( pIS->getTriggerShape() ) ); 1407 } 1408 1409 // 1410 1411 CustomAnimationPresetPtr pDescriptor = rPresets.getEffectDescriptor( pEffect->getPresetId() ); 1412 if( pDescriptor.get() ) 1413 { 1414 sal_Int32 nType = nPropertyTypeNone; 1415 1416 UStringList aProperties( pDescriptor->getProperties() ); 1417 if( aProperties.size() >= 1 ) 1418 nType = getPropertyType( aProperties.front() ); 1419 1420 if( nType != nPropertyTypeNone ) 1421 { 1422 addValue( pSet, nHandleProperty1Type, makeAny( nType ) ); 1423 addValue( pSet, nHandleProperty1Value, getProperty1Value( nType, pEffect ) ); 1424 } 1425 1426 if( pDescriptor->hasProperty( OUString( RTL_CONSTASCII_USTRINGPARAM( "Accelerate" ) ) ) ) 1427 { 1428 addValue( pSet, nHandleAccelerate, makeAny( pEffect->getAcceleration() ) ); 1429 } 1430 1431 if( pDescriptor->hasProperty( OUString( RTL_CONSTASCII_USTRINGPARAM( "Decelerate" ) ) ) ) 1432 { 1433 addValue( pSet, nHandleDecelerate, makeAny( pEffect->getDecelerate() ) ); 1434 } 1435 1436 if( pDescriptor->hasProperty( OUString( RTL_CONSTASCII_USTRINGPARAM( "AutoReverse" ) ) ) ) 1437 { 1438 addValue( pSet, nHandleAutoReverse, makeAny( pEffect->getAutoReverse() ) ); 1439 } 1440 } 1441 } 1442 1443 addValue( pSet, nHandleMaxParaDepth, makeAny( nMaxParaDepth ) ); 1444 1445 return pSet; 1446 } 1447 1448 void CustomAnimationPane::changeSelection( STLPropertySet* pResultSet, STLPropertySet* pOldSet ) 1449 { 1450 // change selected effect 1451 bool bChanged = false; 1452 1453 MainSequenceRebuildGuard aGuard( mpMainSequence ); 1454 1455 EffectSequence::iterator aIter( maListSelection.begin() ); 1456 const EffectSequence::iterator aEnd( maListSelection.end() ); 1457 while( aIter != aEnd ) 1458 { 1459 CustomAnimationEffectPtr pEffect = (*aIter++); 1460 1461 DBG_ASSERT( pEffect->getEffectSequence(), "sd::CustomAnimationPane::changeSelection(), dead effect in selection!" ); 1462 if( !pEffect->getEffectSequence() ) 1463 continue; 1464 1465 double fDuration = 0.0; // we might need this for iterate-interval 1466 if( pResultSet->getPropertyState( nHandleDuration ) == STLPropertyState_DIRECT ) 1467 { 1468 pResultSet->getPropertyValue( nHandleDuration ) >>= fDuration; 1469 } 1470 else 1471 { 1472 fDuration = pEffect->getDuration(); 1473 } 1474 1475 if( pResultSet->getPropertyState( nHandleIterateType ) == STLPropertyState_DIRECT ) 1476 { 1477 sal_Int16 nIterateType = 0; 1478 pResultSet->getPropertyValue( nHandleIterateType ) >>= nIterateType; 1479 if( pEffect->getIterateType() != nIterateType ) 1480 { 1481 pEffect->setIterateType( nIterateType ); 1482 bChanged = true; 1483 } 1484 } 1485 1486 if( pEffect->getIterateType() ) 1487 { 1488 if( pResultSet->getPropertyState( nHandleIterateInterval ) == STLPropertyState_DIRECT ) 1489 { 1490 double fIterateInterval = 0.0; 1491 pResultSet->getPropertyValue( nHandleIterateInterval ) >>= fIterateInterval; 1492 if( pEffect->getIterateInterval() != fIterateInterval ) 1493 { 1494 const double f = fIterateInterval * pEffect->getDuration() / 100; 1495 pEffect->setIterateInterval( f ); 1496 bChanged = true; 1497 } 1498 } 1499 } 1500 1501 if( pResultSet->getPropertyState( nHandleBegin ) == STLPropertyState_DIRECT ) 1502 { 1503 double fBegin = 0.0; 1504 pResultSet->getPropertyValue( nHandleBegin ) >>= fBegin; 1505 if( pEffect->getBegin() != fBegin ) 1506 { 1507 pEffect->setBegin( fBegin ); 1508 bChanged = true; 1509 } 1510 } 1511 1512 if( pResultSet->getPropertyState( nHandleDuration ) == STLPropertyState_DIRECT ) 1513 { 1514 if( pEffect->getDuration() != fDuration ) 1515 { 1516 pEffect->setDuration( fDuration ); 1517 bChanged = true; 1518 } 1519 } 1520 1521 if( pResultSet->getPropertyState( nHandleStart ) == STLPropertyState_DIRECT ) 1522 { 1523 sal_Int16 nNodeType = 0; 1524 pResultSet->getPropertyValue( nHandleStart ) >>= nNodeType; 1525 if( pEffect->getNodeType() != nNodeType ) 1526 { 1527 pEffect->setNodeType( nNodeType ); 1528 bChanged = true; 1529 } 1530 } 1531 1532 if( pResultSet->getPropertyState( nHandleRepeat ) == STLPropertyState_DIRECT ) 1533 { 1534 Any aRepeatCount( pResultSet->getPropertyValue( nHandleRepeat ) ); 1535 if( aRepeatCount != pEffect->getRepeatCount() ) 1536 { 1537 pEffect->setRepeatCount( aRepeatCount ); 1538 bChanged = true; 1539 } 1540 } 1541 1542 if( pResultSet->getPropertyState( nHandleEnd ) == STLPropertyState_DIRECT ) 1543 { 1544 Any aEndValue( pResultSet->getPropertyValue( nHandleEnd ) ); 1545 if( pEffect->getEnd() != aEndValue ) 1546 { 1547 pEffect->setEnd( aEndValue ); 1548 bChanged = true; 1549 } 1550 } 1551 1552 if( pResultSet->getPropertyState( nHandleRewind ) == STLPropertyState_DIRECT ) 1553 { 1554 sal_Int16 nFill = 0; 1555 pResultSet->getPropertyValue( nHandleRewind ) >>= nFill; 1556 if( pEffect->getFill() != nFill ) 1557 { 1558 pEffect->setFill( nFill ); 1559 bChanged = true; 1560 } 1561 } 1562 1563 if( pResultSet->getPropertyState( nHandleHasAfterEffect ) == STLPropertyState_DIRECT ) 1564 { 1565 sal_Bool bHasAfterEffect = sal_False; 1566 if( pResultSet->getPropertyValue( nHandleHasAfterEffect ) >>= bHasAfterEffect ) 1567 { 1568 if( pEffect->hasAfterEffect() != bHasAfterEffect ) 1569 { 1570 pEffect->setHasAfterEffect( bHasAfterEffect ); 1571 bChanged = true; 1572 } 1573 } 1574 } 1575 1576 if( pResultSet->getPropertyState( nHandleAfterEffectOnNextEffect ) == STLPropertyState_DIRECT ) 1577 { 1578 sal_Bool bAfterEffectOnNextEffect = sal_False; 1579 if( (pResultSet->getPropertyValue( nHandleAfterEffectOnNextEffect ) >>= bAfterEffectOnNextEffect) && ((pEffect->IsAfterEffectOnNext() ? sal_True : sal_False) != bAfterEffectOnNextEffect) ) 1580 { 1581 pEffect->setAfterEffectOnNext( bAfterEffectOnNextEffect ); 1582 bChanged = true; 1583 } 1584 } 1585 1586 if( pResultSet->getPropertyState( nHandleDimColor ) == STLPropertyState_DIRECT ) 1587 { 1588 Any aDimColor( pResultSet->getPropertyValue( nHandleDimColor ) ); 1589 if( pEffect->getDimColor() != aDimColor ) 1590 { 1591 pEffect->setDimColor( aDimColor ); 1592 bChanged = true; 1593 } 1594 } 1595 1596 if( pResultSet->getPropertyState( nHandleAccelerate ) == STLPropertyState_DIRECT ) 1597 { 1598 double fAccelerate = 0.0; 1599 pResultSet->getPropertyValue( nHandleAccelerate ) >>= fAccelerate; 1600 if( pEffect->getAcceleration() != fAccelerate ) 1601 { 1602 pEffect->setAcceleration( fAccelerate ); 1603 bChanged = true; 1604 } 1605 } 1606 1607 if( pResultSet->getPropertyState( nHandleDecelerate ) == STLPropertyState_DIRECT ) 1608 { 1609 double fDecelerate = 0.0; 1610 pResultSet->getPropertyValue( nHandleDecelerate ) >>= fDecelerate; 1611 if( pEffect->getDecelerate() != fDecelerate ) 1612 { 1613 pEffect->setDecelerate( fDecelerate ); 1614 bChanged = true; 1615 } 1616 } 1617 1618 if( pResultSet->getPropertyState( nHandleAutoReverse ) == STLPropertyState_DIRECT ) 1619 { 1620 sal_Bool bAutoReverse = sal_False; 1621 pResultSet->getPropertyValue( nHandleAutoReverse ) >>= bAutoReverse; 1622 if( pEffect->getAutoReverse() != bAutoReverse ) 1623 { 1624 pEffect->setAutoReverse( bAutoReverse ); 1625 bChanged = true; 1626 } 1627 } 1628 1629 if( pResultSet->getPropertyState( nHandleProperty1Value ) == STLPropertyState_DIRECT ) 1630 { 1631 sal_Int32 nType = 0; 1632 pOldSet->getPropertyValue( nHandleProperty1Type ) >>= nType; 1633 1634 bChanged |= setProperty1Value( nType, pEffect, pResultSet->getPropertyValue( nHandleProperty1Value ) ); 1635 } 1636 1637 if( pResultSet->getPropertyState( nHandleSoundURL ) == STLPropertyState_DIRECT ) 1638 { 1639 const Any aSoundSource( pResultSet->getPropertyValue( nHandleSoundURL ) ); 1640 1641 if( aSoundSource.getValueType() == ::getCppuType((const sal_Bool*)0) ) 1642 { 1643 pEffect->setStopAudio(); 1644 bChanged = true; 1645 } 1646 else 1647 { 1648 OUString aSoundURL; 1649 aSoundSource >>= aSoundURL; 1650 1651 if( aSoundURL.getLength() ) 1652 { 1653 if( !pEffect->getAudio().is() ) 1654 { 1655 pEffect->createAudio( aSoundSource ); 1656 bChanged = true; 1657 } 1658 else 1659 { 1660 if( pEffect->getAudio()->getSource() != aSoundSource ) 1661 { 1662 pEffect->getAudio()->setSource( aSoundSource ); 1663 bChanged = true; 1664 } 1665 } 1666 } 1667 else 1668 { 1669 if( pEffect->getAudio().is() || pEffect->getStopAudio() ) 1670 { 1671 pEffect->removeAudio(); 1672 bChanged = true; 1673 } 1674 } 1675 } 1676 } 1677 1678 if( pResultSet->getPropertyState( nHandleTrigger ) == STLPropertyState_DIRECT ) 1679 { 1680 Reference< XShape > xTriggerShape; 1681 pResultSet->getPropertyValue( nHandleTrigger ) >>= xTriggerShape; 1682 bChanged |= mpMainSequence->setTrigger( pEffect, xTriggerShape ); 1683 } 1684 } 1685 1686 const bool bHasTextGrouping = pResultSet->getPropertyState( nHandleTextGrouping ) == STLPropertyState_DIRECT; 1687 const bool bHasAnimateForm = pResultSet->getPropertyState( nHandleAnimateForm ) == STLPropertyState_DIRECT; 1688 const bool bHasTextGroupingAuto = pResultSet->getPropertyState( nHandleTextGroupingAuto ) == STLPropertyState_DIRECT; 1689 const bool bHasTextReverse = pResultSet->getPropertyState( nHandleTextReverse ) == STLPropertyState_DIRECT; 1690 1691 if( bHasTextGrouping || bHasAnimateForm || bHasTextGroupingAuto || bHasTextReverse ) 1692 { 1693 // we need to do a second pass for text grouping options 1694 // since changing them can cause effects to be removed 1695 // or replaced, we do this after we aplied all other options 1696 // above 1697 1698 sal_Int32 nTextGrouping = 0; 1699 sal_Bool bAnimateForm = sal_True, bTextReverse = sal_False; 1700 double fTextGroupingAuto = -1.0; 1701 1702 if( bHasTextGrouping ) 1703 pResultSet->getPropertyValue(nHandleTextGrouping) >>= nTextGrouping; 1704 1705 if( bHasAnimateForm ) 1706 pResultSet->getPropertyValue(nHandleAnimateForm) >>= bAnimateForm; 1707 1708 if( bHasTextGroupingAuto ) 1709 pResultSet->getPropertyValue(nHandleTextGroupingAuto) >>= fTextGroupingAuto; 1710 1711 if( bHasTextReverse ) 1712 pResultSet->getPropertyValue(nHandleTextReverse) >>= bTextReverse; 1713 1714 EffectSequence const aSelectedEffects( maListSelection ); 1715 EffectSequence::const_iterator iter( aSelectedEffects.begin() ); 1716 const EffectSequence::const_iterator iEnd( aSelectedEffects.end() ); 1717 while( iter != iEnd ) 1718 { 1719 CustomAnimationEffectPtr const& pEffect = (*iter++); 1720 1721 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence(); 1722 if( !pEffectSequence ) 1723 pEffectSequence = mpMainSequence.get(); 1724 1725 sal_Int32 nGroupId = pEffect->getGroupId(); 1726 CustomAnimationTextGroupPtr pTextGroup; 1727 if( (nGroupId != -1) ) 1728 { 1729 // use existing group 1730 pTextGroup = pEffectSequence->findGroup( nGroupId ); 1731 } 1732 else 1733 { 1734 // somethings changed so we need a group now 1735 pTextGroup = pEffectSequence->createTextGroup( pEffect, nTextGrouping, fTextGroupingAuto, bAnimateForm, bTextReverse ); 1736 bChanged = true; 1737 } 1738 1739 //#Bug 119988# 1740 /************************************************************************/ 1741 /* 1742 Note, the setAnimateForm means set the animation from TextGroup to Object's Shape 1743 And on the UI in means "Animate attached shape" in "Effect Option" dialog 1744 The setTextGrouping means set animation to Object's Text, 1745 the nTextGrouping is Text Animation Type 1746 nTextGrouping = -1 is "As one Object", means no text animation. 1747 1748 The previous call order first do the setTextGrouping and then do the setAnimateForm, 1749 that will cause such defect: in the setTextGrouping, the effect has been removed, 1750 but in setAnimateForm still need this effect, then a NULL pointer of that effect will 1751 be gotten, and cause crash. 1752 1753 []bHasAnimateForm means the UI has changed, bAnimateForm is it value 1754 1755 So if create a new textgroup animation, the following animation will never be run! 1756 Since the ��Animate attached shape�� is default checked. 1757 And the bHasAnimateForm default is false, and if user uncheck it the value bAnimateForm will be false, 1758 it same as the TextGroup��s default value, also could not be run setAnimateForm. 1759 if( bHasAnimateForm ) 1760 { 1761 if( pTextGroup->getAnimateForm() != bAnimateForm ) 1762 { 1763 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm ); 1764 bChanged = true; 1765 } 1766 } 1767 1768 In setTextGrouping, there are three case: 1769 1. Create new text effects for empty TextGroup 1770 2. Remove all text effects of TextGroup (nTextGrouping == -1) 1771 3. Change all the text effects�� start type 1772 1773 So here is the right logic: 1774 If set the animation from text to shape and remove text animation, 1775 should do setAnimateForm first, then do setTextGrouping. 1776 Other case,do setTextGrouping first, then do setAnimateForm. 1777 1778 */ 1779 /************************************************************************/ 1780 1781 bool bDoSetAnimateFormFirst = false; 1782 bool bNeedDoSetAnimateForm = false; 1783 1784 if( bHasAnimateForm ) 1785 { 1786 if( pTextGroup->getAnimateForm() != bAnimateForm ) 1787 { 1788 if( (pTextGroup->getTextGrouping() >= 0) && (nTextGrouping == -1 ) ) 1789 { 1790 bDoSetAnimateFormFirst = true; 1791 } 1792 bNeedDoSetAnimateForm = true; 1793 } 1794 } 1795 1796 if (bDoSetAnimateFormFirst) 1797 { 1798 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm ); 1799 bChanged = true; 1800 } 1801 1802 if( bHasTextGrouping ) 1803 { 1804 if( (pTextGroup->getTextGrouping() != nTextGrouping) ) 1805 { 1806 pEffectSequence->setTextGrouping( pTextGroup, nTextGrouping ); 1807 bChanged = true; 1808 } 1809 } 1810 1811 if (!bDoSetAnimateFormFirst&&bNeedDoSetAnimateForm) 1812 { 1813 pEffectSequence->setAnimateForm( pTextGroup, bAnimateForm ); 1814 bChanged = true; 1815 } 1816 1817 if( bHasTextGroupingAuto ) 1818 { 1819 if( pTextGroup->getTextGroupingAuto() != fTextGroupingAuto ) 1820 { 1821 pEffectSequence->setTextGroupingAuto( pTextGroup, fTextGroupingAuto ); 1822 bChanged = true; 1823 } 1824 } 1825 1826 if( bHasTextReverse ) 1827 { 1828 if( pTextGroup->getTextReverse() != bTextReverse ) 1829 { 1830 pEffectSequence->setTextReverse( pTextGroup, bTextReverse ); 1831 bChanged = true; 1832 } 1833 } 1834 } 1835 } 1836 1837 if( bChanged ) 1838 { 1839 mpMainSequence->rebuild(); 1840 updateControls(); 1841 mrBase.GetDocShell()->SetModified(); 1842 } 1843 } 1844 1845 void CustomAnimationPane::showOptions( sal_uInt16 nPage /* = 0 */ ) 1846 { 1847 STLPropertySet* pSet = createSelectionSet(); 1848 1849 CustomAnimationDialog* pDlg = new CustomAnimationDialog( this, pSet, nPage ); 1850 if( pDlg->Execute() ) 1851 { 1852 addUndo(); 1853 changeSelection( pDlg->getResultSet(), pSet ); 1854 updateControls(); 1855 } 1856 1857 delete pDlg; 1858 } 1859 1860 void CustomAnimationPane::onChangeCurrentPage() 1861 { 1862 if( mxView.is() ) try 1863 { 1864 Reference< XDrawPage > xNewPage( mxView->getCurrentPage() ); 1865 if( xNewPage != mxCurrentPage ) 1866 { 1867 mxCurrentPage = xNewPage; 1868 SdPage* pPage = SdPage::getImplementation( mxCurrentPage ); 1869 if( pPage ) 1870 { 1871 mpMainSequence = pPage->getMainSequence(); 1872 mpCustomAnimationList->update( mpMainSequence ); 1873 } 1874 updateControls(); 1875 } 1876 } 1877 catch( Exception& ) 1878 { 1879 DBG_ERROR( "sd::CustomAnimationPane::onChangeCurrentPage(), exception catched!" ); 1880 } 1881 } 1882 1883 bool getTextSelection( const Any& rSelection, Reference< XShape >& xShape, std::list< sal_Int16 >& rParaList ) 1884 { 1885 Reference< XTextRange > xSelectedText; 1886 rSelection >>= xSelectedText; 1887 if( xSelectedText.is() ) try 1888 { 1889 xShape.set( xSelectedText->getText(), UNO_QUERY_THROW ); 1890 1891 Reference< XTextRangeCompare > xTextRangeCompare( xShape, UNO_QUERY_THROW ); 1892 Reference< XEnumerationAccess > xParaEnumAccess( xShape, UNO_QUERY_THROW ); 1893 Reference< XEnumeration > xParaEnum( xParaEnumAccess->createEnumeration(), UNO_QUERY_THROW ); 1894 Reference< XTextRange > xRange; 1895 Reference< XTextRange > xStart( xSelectedText->getStart() ); 1896 Reference< XTextRange > xEnd( xSelectedText->getEnd() ); 1897 1898 if( xTextRangeCompare->compareRegionEnds( xStart, xEnd ) < 0 ) 1899 { 1900 Reference< XTextRange > xTemp( xStart ); 1901 xStart = xEnd; 1902 xEnd = xTemp; 1903 } 1904 1905 sal_Int16 nPara = 0; 1906 while( xParaEnum->hasMoreElements() ) 1907 { 1908 xParaEnum->nextElement() >>= xRange; 1909 1910 // break if start of selection is prior to end of current paragraph 1911 if( xRange.is() && (xTextRangeCompare->compareRegionEnds( xStart, xRange ) >= 0 ) ) 1912 break; 1913 1914 nPara++; 1915 } 1916 1917 while( xRange.is() ) 1918 { 1919 if( xRange.is() && xRange->getString().getLength() ) 1920 rParaList.push_back( nPara ); 1921 1922 // break if end of selection is before or at end of current paragraph 1923 if( xRange.is() && xTextRangeCompare->compareRegionEnds( xEnd, xRange ) >= 0 ) 1924 break; 1925 1926 nPara++; 1927 1928 if( xParaEnum->hasMoreElements() ) 1929 xParaEnum->nextElement() >>= xRange; 1930 else 1931 xRange.clear(); 1932 } 1933 1934 return true; 1935 } 1936 catch( Exception& e ) 1937 { 1938 (void)e; 1939 DBG_ERROR( "sd::CustomAnimationPane::getTextSelection(), exception cought!" ); 1940 } 1941 1942 return false; 1943 } 1944 1945 void CustomAnimationPane::onChange( bool bCreate ) 1946 { 1947 bool bHasText = true; 1948 1949 // first create vector of targets for dialog preview 1950 std::vector< Any > aTargets; 1951 OUString sPresetId; 1952 double fDuration = 2.0f; 1953 1954 if( bCreate ) 1955 { 1956 // gather shapes from the selection 1957 Reference< XSelectionSupplier > xSel( mxView, UNO_QUERY_THROW ); 1958 maViewSelection = xSel->getSelection(); 1959 1960 if( maViewSelection.getValueType() == ::getCppuType((const Reference< XShapes >*)0) ) 1961 { 1962 Reference< XIndexAccess > xShapes; 1963 maViewSelection >>= xShapes; 1964 1965 sal_Int32 nCount = xShapes->getCount(); 1966 sal_Int32 nIndex; 1967 for( nIndex = 0; nIndex < nCount; nIndex++ ) 1968 { 1969 Any aTarget( xShapes->getByIndex( nIndex ) ); 1970 aTargets.push_back( aTarget ); 1971 if( bHasText ) 1972 { 1973 Reference< XText > xText; 1974 aTarget >>= xText; 1975 if( !xText.is() || xText->getString().getLength() == 0 ) 1976 bHasText = false; 1977 } 1978 } 1979 } 1980 else if ( maViewSelection.getValueType() == ::getCppuType((const Reference< XShape >*)0) ) 1981 { 1982 aTargets.push_back( maViewSelection ); 1983 Reference< XText > xText; 1984 maViewSelection >>= xText; 1985 if( !xText.is() || xText->getString().getLength() == 0 ) 1986 bHasText = false; 1987 } 1988 else if ( maViewSelection.getValueType() == ::getCppuType((const Reference< XTextCursor >*)0) ) 1989 { 1990 Reference< XShape > xShape; 1991 std::list< sal_Int16 > aParaList; 1992 if( getTextSelection( maViewSelection, xShape, aParaList ) ) 1993 { 1994 ParagraphTarget aParaTarget; 1995 aParaTarget.Shape = xShape; 1996 1997 std::list< sal_Int16 >::iterator aIter( aParaList.begin() ); 1998 for( ; aIter != aParaList.end(); aIter++ ) 1999 { 2000 aParaTarget.Paragraph = (*aIter); 2001 aTargets.push_back( makeAny( aParaTarget ) ); 2002 } 2003 } 2004 } 2005 else 2006 { 2007 DBG_ERROR("sd::CustomAnimationPane::onChange(), unknown view selection!" ); 2008 return; 2009 } 2010 } 2011 else 2012 { 2013 // get selected effect 2014 EffectSequence::iterator aIter( maListSelection.begin() ); 2015 const EffectSequence::iterator aEnd( maListSelection.end() ); 2016 while( aIter != aEnd ) 2017 { 2018 if( !bHasText || !(*aIter)->hasText() ) 2019 bHasText = false; 2020 2021 if( sPresetId.getLength() == 0 ) 2022 { 2023 sPresetId = (*aIter)->getPresetId(); 2024 fDuration = (*aIter)->getDuration(); 2025 } 2026 2027 aTargets.push_back( (*aIter++)->getTarget() ); 2028 } 2029 } 2030 2031 CustomAnimationCreateDialog* pDlg = new CustomAnimationCreateDialog( this, this, aTargets, bHasText, sPresetId, fDuration ); 2032 if( pDlg->Execute() ) 2033 { 2034 addUndo(); 2035 fDuration = pDlg->getSelectedDuration(); 2036 CustomAnimationPresetPtr pDescriptor = pDlg->getSelectedPreset(); 2037 if( pDescriptor.get() ) 2038 { 2039 if( bCreate ) 2040 { 2041 mpCustomAnimationList->SelectAll( sal_False ); 2042 2043 // gather shapes from the selection 2044 std::vector< Any >::iterator aIter( aTargets.begin() ); 2045 const std::vector< Any >::iterator aEnd( aTargets.end() ); 2046 bool bFirst = true; 2047 for( ; aIter != aEnd; aIter++ ) 2048 { 2049 CustomAnimationEffectPtr pCreated = mpMainSequence->append( pDescriptor, (*aIter), fDuration ); 2050 2051 // if only one shape with text and no fill or outline is selected, animate only by first level paragraphs 2052 if( bHasText && (aTargets.size() == 1) ) 2053 { 2054 Reference< XShape > xShape( (*aIter), UNO_QUERY ); 2055 if( xShape.is() && !hasVisibleShape( xShape ) ) 2056 { 2057 mpMainSequence->createTextGroup( pCreated, 1, -1.0, sal_False, sal_False ); 2058 } 2059 } 2060 2061 if( bFirst ) 2062 bFirst = false; 2063 else 2064 pCreated->setNodeType( EffectNodeType::WITH_PREVIOUS ); 2065 2066 if( pCreated.get() ) 2067 { 2068 mpCustomAnimationList->select( pCreated ); 2069 } 2070 } 2071 } 2072 else 2073 { 2074 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2075 2076 // get selected effect 2077 EffectSequence::iterator aIter( maListSelection.begin() ); 2078 const EffectSequence::iterator aEnd( maListSelection.end() ); 2079 while( aIter != aEnd ) 2080 { 2081 CustomAnimationEffectPtr pEffect = (*aIter++); 2082 2083 EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence(); 2084 if( !pEffectSequence ) 2085 pEffectSequence = mpMainSequence.get(); 2086 2087 pEffectSequence->replace( pEffect, pDescriptor, fDuration ); 2088 } 2089 } 2090 } 2091 else 2092 { 2093 PathKind eKind = pDlg->getCreatePathKind(); 2094 if( eKind != NONE ) 2095 createPath( eKind, aTargets, fDuration ); 2096 } 2097 mrBase.GetDocShell()->SetModified(); 2098 } 2099 2100 delete pDlg; 2101 2102 updateControls(); 2103 2104 // stop running preview from dialog 2105 SlideShow::Stop( mrBase ); 2106 } 2107 2108 void CustomAnimationPane::createPath( PathKind eKind, std::vector< Any >& rTargets, double fDuration) 2109 { 2110 sal_uInt16 nSID = 0; 2111 2112 switch( eKind ) 2113 { 2114 case CURVE: nSID = SID_DRAW_BEZIER_NOFILL; break; 2115 case POLYGON: nSID = SID_DRAW_POLYGON_NOFILL; break; 2116 case FREEFORM: nSID = SID_DRAW_FREELINE_NOFILL; break; 2117 default: break; 2118 } 2119 2120 if( nSID ) 2121 { 2122 DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >( 2123 FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get()); 2124 2125 if( pViewShell ) 2126 { 2127 DrawView* pView = pViewShell->GetDrawView(); 2128 if( pView ) 2129 pView->UnmarkAllObj(); 2130 2131 std::vector< Any > aTargets( 1, Any( fDuration ) ); 2132 aTargets.insert( aTargets.end(), rTargets.begin(), rTargets.end() ); 2133 Sequence< Any > aTargetSequence( comphelper::containerToSequence( aTargets ) ); 2134 const SfxUnoAnyItem aItem( SID_ADD_MOTION_PATH, Any( aTargetSequence ) ); 2135 pViewShell->GetViewFrame()->GetDispatcher()->Execute( nSID, SFX_CALLMODE_ASYNCHRON, &aItem, 0 ); 2136 } 2137 } 2138 } 2139 2140 void CustomAnimationPane::onRemove() 2141 { 2142 if( !maListSelection.empty() ) 2143 { 2144 addUndo(); 2145 2146 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2147 2148 EffectSequence aList( maListSelection ); 2149 2150 EffectSequence::iterator aIter( aList.begin() ); 2151 const EffectSequence::iterator aEnd( aList.end() ); 2152 while( aIter != aEnd ) 2153 { 2154 CustomAnimationEffectPtr pEffect = (*aIter++); 2155 if( pEffect->getEffectSequence() ) 2156 pEffect->getEffectSequence()->remove( pEffect ); 2157 } 2158 2159 maListSelection.clear(); 2160 mrBase.GetDocShell()->SetModified(); 2161 } 2162 } 2163 2164 void CustomAnimationPane::remove( CustomAnimationEffectPtr& pEffect ) 2165 { 2166 if( pEffect->getEffectSequence() ) 2167 { 2168 addUndo(); 2169 pEffect->getEffectSequence()->remove( pEffect ); 2170 mrBase.GetDocShell()->SetModified(); 2171 } 2172 } 2173 2174 void CustomAnimationPane::onChangeStart() 2175 { 2176 if( mpLBStart->GetSelectEntryCount() == 1 ) 2177 { 2178 sal_Int16 nNodeType; 2179 sal_uInt16 nPos= mpLBStart->GetSelectEntryPos(); 2180 switch( nPos ) 2181 { 2182 case 0: nNodeType = EffectNodeType::ON_CLICK; break; 2183 case 1: nNodeType = EffectNodeType::WITH_PREVIOUS; break; 2184 case 2: nNodeType = EffectNodeType::AFTER_PREVIOUS; break; 2185 default: 2186 return; 2187 } 2188 2189 onChangeStart( nNodeType ); 2190 } 2191 } 2192 2193 void CustomAnimationPane::onChangeStart( sal_Int16 nNodeType ) 2194 { 2195 addUndo(); 2196 2197 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2198 2199 bool bNeedRebuild = false; 2200 2201 EffectSequence::iterator aIter( maListSelection.begin() ); 2202 const EffectSequence::iterator aEnd( maListSelection.end() ); 2203 while( aIter != aEnd ) 2204 { 2205 CustomAnimationEffectPtr pEffect = (*aIter++); 2206 if( pEffect->getNodeType() != nNodeType ) 2207 { 2208 pEffect->setNodeType( nNodeType ); 2209 bNeedRebuild = true; 2210 } 2211 } 2212 2213 if( bNeedRebuild ) 2214 { 2215 mpMainSequence->rebuild(); 2216 updateControls(); 2217 mrBase.GetDocShell()->SetModified(); 2218 } 2219 } 2220 2221 void CustomAnimationPane::onChangeProperty() 2222 { 2223 if( mpLBProperty->getSubControl() ) 2224 { 2225 addUndo(); 2226 2227 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2228 2229 const Any aValue( mpLBProperty->getSubControl()->getValue() ); 2230 2231 bool bNeedUpdate = false; 2232 2233 // change selected effect 2234 EffectSequence::iterator aIter( maListSelection.begin() ); 2235 const EffectSequence::iterator aEnd( maListSelection.end() ); 2236 while( aIter != aEnd ) 2237 { 2238 CustomAnimationEffectPtr pEffect = (*aIter++); 2239 2240 if( setProperty1Value( mnPropertyType, pEffect, aValue ) ) 2241 bNeedUpdate = true; 2242 } 2243 2244 if( bNeedUpdate ) 2245 { 2246 mpMainSequence->rebuild(); 2247 updateControls(); 2248 mrBase.GetDocShell()->SetModified(); 2249 } 2250 2251 onPreview( false ); 2252 } 2253 } 2254 2255 void CustomAnimationPane::onChangeSpeed() 2256 { 2257 if( mpCBSpeed->GetSelectEntryCount() == 1 ) 2258 { 2259 addUndo(); 2260 2261 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2262 2263 double fDuration; 2264 2265 sal_uInt16 nPos= mpCBSpeed->GetSelectEntryPos(); 2266 2267 switch( nPos ) 2268 { 2269 case 0: fDuration = 5.0; break; 2270 case 1: fDuration = 3.0; break; 2271 case 2: fDuration = 2.0; break; 2272 case 3: fDuration = 1.0; break; 2273 case 4: fDuration = 0.5; break; 2274 default: 2275 return; 2276 } 2277 2278 // change selected effect 2279 EffectSequence::iterator aIter( maListSelection.begin() ); 2280 const EffectSequence::iterator aEnd( maListSelection.end() ); 2281 while( aIter != aEnd ) 2282 { 2283 CustomAnimationEffectPtr pEffect = (*aIter++); 2284 pEffect->setDuration( fDuration ); 2285 } 2286 2287 mpMainSequence->rebuild(); 2288 updateControls(); 2289 mrBase.GetDocShell()->SetModified(); 2290 2291 onPreview( false ); 2292 } 2293 } 2294 2295 /// this link is called when the property box is modified by the user 2296 IMPL_LINK( CustomAnimationPane, implPropertyHdl, Control*, EMPTYARG ) 2297 { 2298 onChangeProperty(); 2299 return 0; 2300 } 2301 2302 /// this link is called when one of the controls is modified 2303 IMPL_LINK( CustomAnimationPane, implControlHdl, Control*, pControl ) 2304 { 2305 if( pControl == mpPBAddEffect ) 2306 onChange(true); 2307 else if( pControl == mpPBChangeEffect ) 2308 onChange(false); 2309 else if( pControl == mpPBRemoveEffect ) 2310 onRemove(); 2311 else if( pControl == mpLBStart ) 2312 onChangeStart(); 2313 else if( pControl == mpCBSpeed ) 2314 onChangeSpeed(); 2315 else if( pControl == mpPBPropertyMore ) 2316 showOptions(); 2317 else if( pControl == mpPBMoveUp ) 2318 moveSelection( true ); 2319 else if( pControl == mpPBMoveDown ) 2320 moveSelection( false ); 2321 else if( pControl == mpPBPlay ) 2322 onPreview( true ); 2323 else if( pControl == mpPBSlideShow ) 2324 { 2325 mrBase.StartPresentation(); 2326 } 2327 else if( pControl == mpCBAutoPreview ) 2328 { 2329 SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS); 2330 pOptions->SetPreviewChangedEffects( mpCBAutoPreview->IsChecked() ? sal_True : sal_False ); 2331 } 2332 2333 updateControls(); 2334 2335 return 0; 2336 } 2337 2338 IMPL_LINK(CustomAnimationPane, lateInitCallback, Timer*, EMPTYARG ) 2339 { 2340 // Call getPresets() to initiate the (expensive) construction of the 2341 // presets list. 2342 getPresets(); 2343 2344 // update selection and control states 2345 onSelectionChanged(); 2346 2347 return 0; 2348 } 2349 2350 void CustomAnimationPane::moveSelection( bool bUp ) 2351 { 2352 if( maListSelection.empty() ) 2353 return; 2354 2355 EffectSequenceHelper* pSequence = maListSelection.front()->getEffectSequence(); 2356 if( pSequence == 0 ) 2357 return; 2358 2359 addUndo(); 2360 2361 bool bChanged = false; 2362 2363 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2364 EffectSequence& rEffectSequence = pSequence->getSequence(); 2365 2366 if( bUp ) 2367 { 2368 EffectSequence::iterator aIter( maListSelection.begin() ); 2369 const EffectSequence::iterator aEnd( maListSelection.end() ); 2370 2371 while( aIter != aEnd ) 2372 { 2373 CustomAnimationEffectPtr pEffect = (*aIter++); 2374 2375 EffectSequence::iterator aEffectPos( pSequence->find( pEffect ) ); 2376 if( aEffectPos != rEffectSequence.end() ) 2377 { 2378 EffectSequence::iterator aInsertPos( rEffectSequence.erase( aEffectPos ) ); 2379 2380 if( aInsertPos != rEffectSequence.begin() ) 2381 { 2382 aInsertPos--; 2383 while( (aInsertPos != rEffectSequence.begin()) && !mpCustomAnimationList->isExpanded(*aInsertPos)) 2384 aInsertPos--; 2385 2386 rEffectSequence.insert( aInsertPos, pEffect ); 2387 } 2388 else 2389 { 2390 rEffectSequence.push_front( pEffect ); 2391 } 2392 bChanged = true; 2393 } 2394 } 2395 } 2396 else 2397 { 2398 EffectSequence::reverse_iterator aIter( maListSelection.rbegin() ); 2399 const EffectSequence::reverse_iterator aEnd( maListSelection.rend() ); 2400 2401 while( aIter != aEnd ) 2402 { 2403 CustomAnimationEffectPtr pEffect = (*aIter++); 2404 2405 EffectSequence::iterator aEffectPos( pSequence->find( pEffect ) ); 2406 if( aEffectPos != rEffectSequence.end() ) 2407 { 2408 EffectSequence::iterator aInsertPos( rEffectSequence.erase( aEffectPos ) ); 2409 2410 if( aInsertPos != rEffectSequence.end() ) 2411 { 2412 aInsertPos++; 2413 while( (aInsertPos != rEffectSequence.end()) && !mpCustomAnimationList->isExpanded(*aInsertPos)) 2414 aInsertPos++; 2415 2416 rEffectSequence.insert( aInsertPos, pEffect ); 2417 } 2418 else 2419 { 2420 rEffectSequence.push_back( pEffect ); 2421 } 2422 bChanged = true; 2423 } 2424 } 2425 } 2426 2427 if( bChanged ) 2428 { 2429 mpMainSequence->rebuild(); 2430 updateControls(); 2431 mrBase.GetDocShell()->SetModified(); 2432 } 2433 } 2434 2435 void CustomAnimationPane::onPreview( bool bForcePreview ) 2436 { 2437 if( !bForcePreview && !mpCBAutoPreview->IsChecked() ) 2438 return; 2439 2440 if( maListSelection.empty() ) 2441 { 2442 rtl::Reference< MotionPathTag > xMotionPathTag; 2443 MotionPathTagVector::iterator aIter; 2444 for( aIter = maMotionPathTags.begin(); aIter != maMotionPathTags.end(); aIter++ ) 2445 { 2446 if( (*aIter)->isSelected() ) 2447 { 2448 xMotionPathTag = (*aIter); 2449 break; 2450 } 2451 } 2452 2453 if( xMotionPathTag.is() ) 2454 { 2455 MainSequencePtr pSequence( new MainSequence() ); 2456 pSequence->append( xMotionPathTag->getEffect()->clone() ); 2457 preview( pSequence->getRootNode() ); 2458 } 2459 else 2460 { 2461 Reference< XAnimationNodeSupplier > xNodeSupplier( mxCurrentPage, UNO_QUERY ); 2462 if( !xNodeSupplier.is() ) 2463 return; 2464 2465 preview( xNodeSupplier->getAnimationNode() ); 2466 } 2467 } 2468 else 2469 { 2470 MainSequencePtr pSequence( new MainSequence() ); 2471 2472 EffectSequence::iterator aIter( maListSelection.begin() ); 2473 const EffectSequence::iterator aEnd( maListSelection.end() ); 2474 2475 while( aIter != aEnd ) 2476 { 2477 CustomAnimationEffectPtr pEffect = (*aIter++); 2478 pSequence->append( pEffect->clone() ); 2479 } 2480 2481 preview( pSequence->getRootNode() ); 2482 } 2483 } 2484 2485 void CustomAnimationPane::preview( const Reference< XAnimationNode >& xAnimationNode ) 2486 { 2487 Reference< XTimeContainer > xRoot(::comphelper::getProcessServiceFactory()->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.animations.ParallelTimeContainer"))), UNO_QUERY); 2488 if( xRoot.is() ) 2489 { 2490 Sequence< ::com::sun::star::beans::NamedValue > aUserData( 1 ); 2491 aUserData[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "node-type" ) ); 2492 aUserData[0].Value <<= ::com::sun::star::presentation::EffectNodeType::TIMING_ROOT; 2493 xRoot->setUserData( aUserData ); 2494 xRoot->appendChild( xAnimationNode ); 2495 2496 Reference< XAnimationNode > xNode( xRoot, UNO_QUERY ); 2497 SlideShow::StartPreview( mrBase, mxCurrentPage, xNode ); 2498 } 2499 } 2500 2501 2502 // ICustomAnimationListController 2503 void CustomAnimationPane::onSelect() 2504 { 2505 maListSelection = mpCustomAnimationList->getSelection(); 2506 updateControls(); 2507 markShapesFromSelectedEffects(); 2508 } 2509 2510 2511 2512 2513 const CustomAnimationPresets& CustomAnimationPane::getPresets (void) 2514 { 2515 if (mpCustomAnimationPresets == NULL) 2516 mpCustomAnimationPresets = &CustomAnimationPresets::getCustomAnimationPresets(); 2517 return *mpCustomAnimationPresets; 2518 } 2519 2520 2521 2522 void CustomAnimationPane::markShapesFromSelectedEffects() 2523 { 2524 if( !maSelectionLock.isLocked() ) 2525 { 2526 ScopeLockGuard aGuard( maSelectionLock ); 2527 DrawViewShell* pViewShell = dynamic_cast< DrawViewShell* >( 2528 FrameworkHelper::Instance(mrBase)->GetViewShell(FrameworkHelper::msCenterPaneURL).get()); 2529 DrawView* pView = pViewShell ? pViewShell->GetDrawView() : NULL; 2530 2531 if( pView ) 2532 { 2533 pView->UnmarkAllObj(); 2534 EffectSequence::iterator aIter( maListSelection.begin() ); 2535 const EffectSequence::iterator aEnd( maListSelection.end() ); 2536 while( aIter != aEnd ) 2537 { 2538 CustomAnimationEffectPtr pEffect = (*aIter++); 2539 2540 Reference< XShape > xShape( pEffect->getTargetShape() ); 2541 SdrObject* pObj = GetSdrObjectFromXShape( xShape ); 2542 if( pObj ) 2543 pView->MarkObj(pObj, pView->GetSdrPageView(), sal_False, sal_False); 2544 } 2545 } 2546 } 2547 } 2548 2549 2550 void CustomAnimationPane::updatePathFromMotionPathTag( const rtl::Reference< MotionPathTag >& xTag ) 2551 { 2552 MainSequenceRebuildGuard aGuard( mpMainSequence ); 2553 if( xTag.is() ) 2554 { 2555 SdrPathObj* pPathObj = xTag->getPathObj(); 2556 CustomAnimationEffectPtr pEffect = xTag->getEffect(); 2557 if( (pPathObj != 0) && pEffect.get() != 0 ) 2558 { 2559 ::svl::IUndoManager* pManager = mrBase.GetDocShell()->GetUndoManager(); 2560 if( pManager ) 2561 { 2562 SdPage* pPage = SdPage::getImplementation( mxCurrentPage ); 2563 if( pPage ) 2564 pManager->AddUndoAction( new UndoAnimationPath( mrBase.GetDocShell()->GetDoc(), pPage, pEffect->getNode() ) ); 2565 } 2566 2567 pEffect->updatePathFromSdrPathObj( *pPathObj ); 2568 } 2569 } 2570 } 2571 2572 // ==================================================================== 2573 2574 ::Window * createCustomAnimationPanel( ::Window* pParent, ViewShellBase& rBase ) 2575 { 2576 DialogListBox* pWindow = 0; 2577 2578 DrawDocShell* pDocSh = rBase.GetDocShell(); 2579 if( pDocSh ) 2580 { 2581 pWindow = new DialogListBox( pParent, WB_CLIPCHILDREN|WB_TABSTOP|WB_AUTOHSCROLL ); 2582 const Size aMinSize( pWindow->LogicToPixel( Size( 80, 256 ), MAP_APPFONT ) ); 2583 pWindow->SetSizePixel(aMinSize); 2584 pWindow->SetBackground(Wallpaper(Color(COL_BLUE))); 2585 2586 ::Window* pPaneWindow = new CustomAnimationPane( pWindow, rBase, aMinSize ); 2587 pWindow->SetChildWindow( pPaneWindow, aMinSize ); 2588 pWindow->SetText( pPaneWindow->GetText() ); 2589 } 2590 2591 return pWindow; 2592 } 2593 2594 2595 2596 2597 sal_Int32 getCustomAnimationPanelMinimumHeight (::Window* pDialog) 2598 { 2599 if (pDialog != NULL) 2600 return pDialog->LogicToPixel(Size( 80, 256 ), MAP_APPFONT).Height(); 2601 else 2602 return 0; 2603 } 2604 2605 } 2606