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