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