1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sd.hxx" 30 #include <com/sun/star/drawing/XShapes.hpp> 31 #include <com/sun/star/presentation/ShapeAnimationSubType.hpp> 32 #include <com/sun/star/presentation/EffectNodeType.hpp> 33 #include <com/sun/star/presentation/ParagraphTarget.hpp> 34 #include <com/sun/star/container/XEnumerationAccess.hpp> 35 #include <com/sun/star/animations/XIterateContainer.hpp> 36 #include <com/sun/star/presentation/EffectPresetClass.hpp> 37 #include <com/sun/star/presentation/EffectCommands.hpp> 38 #include <com/sun/star/text/XTextRange.hpp> 39 #include <com/sun/star/beans/XPropertySet.hpp> 40 #include <com/sun/star/drawing/XDrawPage.hpp> 41 #include <svx/ShapeTypeHandler.hxx> 42 #include "CustomAnimationList.hxx" 43 #ifndef _SD_CUSTOMANIMATIONPANE_HRC 44 #include "CustomAnimationPane.hrc" 45 #endif 46 #ifndef _SD_CUSTOMANIMATION_HRC 47 #include "CustomAnimation.hrc" 48 #endif 49 #include "CustomAnimationPreset.hxx" 50 #include <svtools/treelist.hxx> 51 #include <vcl/svapp.hxx> 52 #include "sdresid.hxx" 53 54 #include "res_bmp.hrc" 55 #include "glob.hrc" 56 57 #include <algorithm> 58 59 using namespace ::com::sun::star; 60 using namespace ::com::sun::star::animations; 61 using namespace ::com::sun::star::presentation; 62 63 using ::rtl::OUString; 64 using ::com::sun::star::uno::UNO_QUERY; 65 using ::com::sun::star::uno::UNO_QUERY_THROW; 66 using ::com::sun::star::uno::Any; 67 using ::com::sun::star::uno::Sequence; 68 using ::com::sun::star::uno::Reference; 69 using ::com::sun::star::uno::Exception; 70 using ::com::sun::star::uno::XInterface; 71 using ::com::sun::star::text::XTextRange; 72 using ::com::sun::star::drawing::XShape; 73 using ::com::sun::star::drawing::XShapes; 74 using ::com::sun::star::drawing::XDrawPage; 75 using ::com::sun::star::container::XChild; 76 using ::com::sun::star::container::XIndexAccess; 77 using ::com::sun::star::container::XEnumerationAccess; 78 using ::com::sun::star::container::XEnumeration; 79 using ::com::sun::star::beans::XPropertySet; 80 using ::com::sun::star::beans::XPropertySetInfo; 81 using ::accessibility::ShapeTypeHandler; 82 83 namespace sd { 84 85 // go recursivly through all shapes in the given XShapes collection and return true as soon as the 86 // given shape is found. nIndex is incremented for each shape with the same shape type as the given 87 // shape is found until the given shape is found. 88 static bool getShapeIndex( const Reference< XShapes >& xShapes, const Reference< XShape >& xShape, sal_Int32& nIndex ) 89 { 90 const sal_Int32 nCount = xShapes->getCount(); 91 sal_Int32 n; 92 for( n = 0; n < nCount; n++ ) 93 { 94 Reference< XShape > xChild; 95 xShapes->getByIndex( n ) >>= xChild; 96 if( xChild == xShape ) 97 return true; 98 99 if( xChild->getShapeType() == xShape->getShapeType() ) 100 nIndex++; 101 102 Reference< XShapes > xChildContainer( xChild, UNO_QUERY ); 103 if( xChildContainer.is() ) 104 { 105 if( getShapeIndex( xChildContainer, xShape, nIndex ) ) 106 return true; 107 } 108 } 109 110 return false; 111 } 112 113 // returns the index of the shape type from the given shape 114 static sal_Int32 getShapeIndex( const Reference< XShape >& xShape ) 115 { 116 Reference< XChild > xChild( xShape, UNO_QUERY ); 117 Reference< XShapes > xPage; 118 119 while( xChild.is() && !xPage.is() ) 120 { 121 Reference< XInterface > x( xChild->getParent() ); 122 xChild = Reference< XChild >::query( x ); 123 Reference< XDrawPage > xTestPage( x, UNO_QUERY ); 124 if( xTestPage.is() ) 125 xPage = Reference< XShapes >::query( x ); 126 } 127 128 sal_Int32 nIndex = 1; 129 130 if( xPage.is() && getShapeIndex( xPage, xShape, nIndex ) ) 131 return nIndex; 132 else 133 return -1; 134 } 135 136 OUString getShapeDescription( const Reference< XShape >& xShape, bool bWithText = true ) 137 { 138 OUString aDescription; 139 Reference< XPropertySet > xSet( xShape, UNO_QUERY ); 140 if( xSet.is() ) 141 { 142 Reference< XPropertySetInfo > xInfo( xSet->getPropertySetInfo() ); 143 const OUString aPropName( RTL_CONSTASCII_USTRINGPARAM("UINameSingular") ); 144 if( xInfo->hasPropertyByName( aPropName ) ) 145 xSet->getPropertyValue( aPropName ) >>= aDescription; 146 } 147 148 aDescription += OUString( RTL_CONSTASCII_USTRINGPARAM(" ")); 149 aDescription += OUString::valueOf( getShapeIndex( xShape ) ); 150 151 if( bWithText ) 152 { 153 Reference< XTextRange > xText( xShape, UNO_QUERY ); 154 if( xText.is() ) 155 { 156 OUString aText( xText->getString() ); 157 if( aText.getLength() ) 158 { 159 aDescription += OUString(RTL_CONSTASCII_USTRINGPARAM(": ")); 160 161 aText = aText.replace( (sal_Unicode)'\n', (sal_Unicode)' ' ); 162 aText = aText.replace( (sal_Unicode)'\r', (sal_Unicode)' ' ); 163 164 aDescription += aText; 165 } 166 } 167 } 168 return aDescription; 169 } 170 171 static OUString getDescription( const Any& rTarget, bool bWithText = true ) 172 { 173 OUString aDescription; 174 175 if( rTarget.getValueType() == ::getCppuType((const ParagraphTarget*)0) ) 176 { 177 ParagraphTarget aParaTarget; 178 rTarget >>= aParaTarget; 179 180 Reference< XEnumerationAccess > xText( aParaTarget.Shape, UNO_QUERY_THROW ); 181 Reference< XEnumeration > xEnumeration( xText->createEnumeration(), UNO_QUERY_THROW ); 182 sal_Int32 nPara = aParaTarget.Paragraph; 183 184 while( xEnumeration->hasMoreElements() && nPara ) 185 { 186 xEnumeration->nextElement(); 187 nPara--; 188 } 189 190 DBG_ASSERT( xEnumeration->hasMoreElements(), "sd::CustomAnimationEffect::prepareText(), paragraph out of range!" ); 191 192 if( xEnumeration->hasMoreElements() ) 193 { 194 Reference< XTextRange > xParagraph; 195 xEnumeration->nextElement() >>= xParagraph; 196 197 if( xParagraph.is() ) 198 aDescription = xParagraph->getString(); 199 } 200 } 201 else 202 { 203 Reference< XShape > xShape; 204 rTarget >>= xShape; 205 if( xShape.is() ) 206 aDescription = getShapeDescription( xShape, bWithText ); 207 } 208 209 return aDescription; 210 } 211 212 // ==================================================================== 213 214 class CustomAnimationListEntryItem : public SvLBoxString 215 { 216 public: 217 CustomAnimationListEntryItem( SvLBoxEntry*,sal_uInt16 nFlags, OUString aDescription, CustomAnimationEffectPtr pEffect, CustomAnimationList* pParent ); 218 virtual ~CustomAnimationListEntryItem(); 219 void InitViewData( SvLBox*,SvLBoxEntry*,SvViewDataItem* ); 220 void Paint( const Point&, SvLBox& rDev, sal_uInt16 nFlags,SvLBoxEntry* ); 221 SvLBoxItem* Create() const; 222 void Clone( SvLBoxItem* pSource ); 223 224 private: 225 CustomAnimationList* mpParent; 226 OUString maDescription; 227 CustomAnimationEffectPtr mpEffect; 228 }; 229 230 // -------------------------------------------------------------------- 231 232 CustomAnimationListEntryItem::CustomAnimationListEntryItem( SvLBoxEntry* pEntry, sal_uInt16 nFlags, OUString aDescription, CustomAnimationEffectPtr pEffect, CustomAnimationList* pParent ) 233 : SvLBoxString( pEntry, nFlags, aDescription ) 234 , mpParent( pParent ) 235 , maDescription( aDescription ) 236 , mpEffect(pEffect) 237 { 238 } 239 240 // -------------------------------------------------------------------- 241 242 CustomAnimationListEntryItem::~CustomAnimationListEntryItem() 243 { 244 } 245 246 // -------------------------------------------------------------------- 247 248 void CustomAnimationListEntryItem::InitViewData( SvLBox* pView, SvLBoxEntry* pEntry, SvViewDataItem* pViewData ) 249 { 250 if( !pViewData ) 251 pViewData = pView->GetViewDataItem( pEntry, this ); 252 253 Size aSize(pView->GetTextWidth( maDescription ) + 2 * 19, pView->GetTextHeight() ); 254 if( aSize.Height() < 19 ) 255 aSize.Height() = 19; 256 pViewData->aSize = aSize; 257 } 258 259 // -------------------------------------------------------------------- 260 261 void CustomAnimationListEntryItem::Paint( const Point& rPos, SvLBox& rDev, sal_uInt16, SvLBoxEntry* pEntry ) 262 { 263 const bool bHighContrast = Application::GetSettings().GetStyleSettings().GetHighContrastMode(); 264 265 SvViewDataItem* pViewData = mpParent->GetViewDataItem( pEntry, this ); 266 267 Point aPos( rPos ); 268 Size aSize( pViewData->aSize ); 269 270 sal_Int16 nNodeType = mpEffect->getNodeType(); 271 if( nNodeType == EffectNodeType::ON_CLICK ) 272 { 273 rDev.DrawImage( aPos, mpParent->getImage( IMG_CUSTOMANIMATION_ON_CLICK, bHighContrast ) ); 274 } 275 else if( nNodeType == EffectNodeType::AFTER_PREVIOUS ) 276 { 277 rDev.DrawImage( aPos, mpParent->getImage( IMG_CUSTOMANIMATION_AFTER_PREVIOUS, bHighContrast ) ); 278 } 279 280 aPos.X() += 19; 281 282 sal_uInt16 nImage; 283 switch( mpEffect->getPresetClass() ) 284 { 285 case EffectPresetClass::ENTRANCE: nImage = IMG_CUSTOMANIMATION_ENTRANCE_EFFECT; break; 286 case EffectPresetClass::EXIT: nImage = IMG_CUSTOMANIMATION_EXIT_EFFECT; break; 287 case EffectPresetClass::EMPHASIS: nImage = IMG_CUSTOMANIMATION_EMPHASIS_EFFECT; break; 288 case EffectPresetClass::MOTIONPATH: nImage = IMG_CUSTOMANIMATION_MOTION_PATH; break; 289 case EffectPresetClass::OLEACTION: nImage = IMG_CUSTOMANIMATION_OLE; break; 290 case EffectPresetClass::MEDIACALL: 291 switch( mpEffect->getCommand() ) 292 { 293 case EffectCommands::TOGGLEPAUSE: nImage = IMG_CUSTOMANIMATION_MEDIA_PAUSE; break; 294 case EffectCommands::STOP: nImage = IMG_CUSTOMANIMATION_MEDIA_STOP; break; 295 case EffectCommands::PLAY: 296 default: nImage = IMG_CUSTOMANIMATION_MEDIA_PLAY; break; 297 } 298 break; 299 default: nImage = 0xffff; 300 } 301 302 if( nImage != 0xffff ) 303 { 304 const Image& rImage = mpParent->getImage( nImage, bHighContrast ); 305 Point aImagePos( aPos ); 306 aImagePos.Y() += ( aSize.Height() - rImage.GetSizePixel().Height() ) >> 1; 307 rDev.DrawImage( aImagePos, rImage ); 308 } 309 310 aPos.X() += 19; 311 aPos.Y() += ( aSize.Height() - rDev.GetTextHeight()) >> 1; 312 313 rDev.DrawText( aPos, rDev.GetEllipsisString( maDescription, rDev.GetOutputSizePixel().Width() - aPos.X() ) ); 314 } 315 316 // -------------------------------------------------------------------- 317 318 SvLBoxItem* CustomAnimationListEntryItem::Create() const 319 { 320 return NULL; 321 } 322 323 // -------------------------------------------------------------------- 324 325 void CustomAnimationListEntryItem::Clone( SvLBoxItem* ) 326 { 327 } 328 329 // ==================================================================== 330 331 class CustomAnimationListEntry : public SvLBoxEntry 332 { 333 public: 334 CustomAnimationListEntry(); 335 CustomAnimationListEntry( CustomAnimationEffectPtr pEffect ); 336 virtual ~CustomAnimationListEntry(); 337 338 CustomAnimationEffectPtr getEffect() const { return mpEffect; } 339 340 private: 341 CustomAnimationEffectPtr mpEffect; 342 }; 343 344 // -------------------------------------------------------------------- 345 346 CustomAnimationListEntry::CustomAnimationListEntry() 347 { 348 } 349 350 // -------------------------------------------------------------------- 351 352 CustomAnimationListEntry::CustomAnimationListEntry( CustomAnimationEffectPtr pEffect ) 353 : mpEffect( pEffect ) 354 { 355 } 356 357 // -------------------------------------------------------------------- 358 359 CustomAnimationListEntry::~CustomAnimationListEntry() 360 { 361 } 362 363 // ==================================================================== 364 365 class CustomAnimationTriggerEntryItem : public SvLBoxString 366 { 367 public: 368 CustomAnimationTriggerEntryItem( SvLBoxEntry*,sal_uInt16 nFlags, OUString aDescription, CustomAnimationList* pParent ); 369 virtual ~CustomAnimationTriggerEntryItem(); 370 virtual sal_uInt16 IsA(); 371 void InitViewData( SvLBox*,SvLBoxEntry*,SvViewDataItem* ); 372 void Paint( const Point&, SvLBox& rDev, sal_uInt16 nFlags,SvLBoxEntry* ); 373 SvLBoxItem* Create() const; 374 void Clone( SvLBoxItem* pSource ); 375 376 private: 377 CustomAnimationList* mpParent; 378 OUString maDescription; 379 }; 380 381 // -------------------------------------------------------------------- 382 383 CustomAnimationTriggerEntryItem::CustomAnimationTriggerEntryItem( SvLBoxEntry* pEntry, sal_uInt16 nFlags, OUString aDescription, CustomAnimationList* pParent ) 384 : SvLBoxString( pEntry, nFlags, aDescription ), mpParent( pParent ), maDescription( aDescription ) 385 { 386 } 387 388 // -------------------------------------------------------------------- 389 390 CustomAnimationTriggerEntryItem::~CustomAnimationTriggerEntryItem() 391 { 392 } 393 394 // -------------------------------------------------------------------- 395 396 sal_uInt16 CustomAnimationTriggerEntryItem::IsA() 397 { 398 return (sal_uInt16)-1; 399 } 400 401 // -------------------------------------------------------------------- 402 403 void CustomAnimationTriggerEntryItem::InitViewData( SvLBox* pView, SvLBoxEntry* pEntry, SvViewDataItem* pViewData ) 404 { 405 if( !pViewData ) 406 pViewData = pView->GetViewDataItem( pEntry, this ); 407 408 Size aSize(pView->GetTextWidth( maDescription ) + 2 * 19, pView->GetTextHeight() ); 409 if( aSize.Height() < 19 ) 410 aSize.Height() = 19; 411 pViewData->aSize = aSize; 412 413 /* 414 SvViewData* pViewData = pView->GetViewData( pEntry ); 415 if( pViewData ) 416 pViewData->SetSelectable(false); 417 */ 418 } 419 420 // -------------------------------------------------------------------- 421 422 void CustomAnimationTriggerEntryItem::Paint( const Point& rPos, SvLBox& rDev, sal_uInt16, SvLBoxEntry* ) 423 { 424 Size aSize( rDev.GetOutputSizePixel().Width(), static_cast< SvTreeListBox* >(&rDev)->GetEntryHeight() ); 425 426 Point aPos( 0, rPos.Y() ); 427 428 Rectangle aOutRect( aPos, aSize ); 429 430 // fill the background 431 Color aColor (rDev.GetSettings().GetStyleSettings().GetDialogColor()); 432 433 rDev.Push(); 434 rDev.SetFillColor (aColor); 435 rDev.SetLineColor (); 436 rDev.DrawRect(aOutRect); 437 438 // Erase the four corner pixels to make the rectangle appear rounded. 439 rDev.SetLineColor( rDev.GetSettings().GetStyleSettings().GetWindowColor()); 440 rDev.DrawPixel( aOutRect.TopLeft()); 441 rDev.DrawPixel( Point(aOutRect.Right(), aOutRect.Top())); 442 rDev.DrawPixel( Point(aOutRect.Left(), aOutRect.Bottom())); 443 rDev.DrawPixel( Point(aOutRect.Right(), aOutRect.Bottom())); 444 445 // draw the category title 446 447 int nVertBorder = (( aSize.Height() - rDev.GetTextHeight()) >> 1); 448 int nHorzBorder = rDev.LogicToPixel( Size( 3, 3 ), MAP_APPFONT ).Width(); 449 450 aOutRect.nLeft += nHorzBorder; 451 aOutRect.nRight -= nHorzBorder; 452 aOutRect.nTop += nVertBorder; 453 aOutRect.nBottom -= nVertBorder; 454 455 rDev.DrawText (aOutRect, rDev.GetEllipsisString( maDescription, aOutRect.GetWidth() ) ); 456 rDev.Pop(); 457 } 458 459 // -------------------------------------------------------------------- 460 461 SvLBoxItem* CustomAnimationTriggerEntryItem::Create() const 462 { 463 return NULL; 464 } 465 466 // -------------------------------------------------------------------- 467 468 void CustomAnimationTriggerEntryItem::Clone( SvLBoxItem* ) 469 { 470 } 471 472 // ==================================================================== 473 474 CustomAnimationList::CustomAnimationList( ::Window* pParent, const ResId& rResId, ICustomAnimationListController* pController ) 475 : SvTreeListBox( pParent, rResId ) 476 , mbIgnorePaint( false ) 477 , mpController( pController ) 478 , mpLastParentEntry(0) 479 { 480 SetStyle( GetStyle() | WB_TABSTOP | WB_BORDER | WB_HASLINES | WB_HASBUTTONS | WB_HASBUTTONSATROOT ); 481 482 EnableContextMenuHandling(); 483 SetSelectionMode( MULTIPLE_SELECTION ); 484 SetIndent(16); 485 SetNodeDefaultImages(); 486 } 487 488 // -------------------------------------------------------------------- 489 490 const Image& CustomAnimationList::getImage( sal_uInt16 nId, bool bHighContrast ) 491 { 492 DBG_ASSERT( (nId >= IMG_CUSTOMANIMATION_ON_CLICK) && (nId <= IMG_CUSTOMANIMATION_MEDIA_STOP), "sd::CustomAnimationList::getImage(), illegal index!" ); 493 494 if( bHighContrast ) 495 nId += 1; 496 497 Image& rImage = maImages[nId - IMG_CUSTOMANIMATION_ON_CLICK]; 498 499 // load on demand 500 if( rImage.GetSizePixel().Width() == 0 ) 501 rImage = Image(SdResId( nId ) ); 502 503 return rImage; 504 } 505 506 // -------------------------------------------------------------------- 507 508 CustomAnimationList::~CustomAnimationList() 509 { 510 if( mpMainSequence.get() ) 511 mpMainSequence->removeListener( this ); 512 513 clear(); 514 } 515 516 // -------------------------------------------------------------------- 517 518 void CustomAnimationList::KeyInput( const KeyEvent& rKEvt ) 519 { 520 const int nKeyCode = rKEvt.GetKeyCode().GetCode(); 521 switch( nKeyCode ) 522 { 523 case KEY_DELETE: mpController->onContextMenu( CM_REMOVE ); return; 524 case KEY_INSERT: mpController->onContextMenu( CM_CREATE ); return; 525 case KEY_SPACE: 526 { 527 const Point aPos; 528 const CommandEvent aCEvt( aPos, COMMAND_CONTEXTMENU ); 529 Command( aCEvt ); 530 return; 531 } 532 533 } 534 535 ::SvTreeListBox::KeyInput( rKEvt ); 536 } 537 538 // -------------------------------------------------------------------- 539 540 /** selects or deselects the given effect. 541 Selections of other effects are not changed */ 542 void CustomAnimationList::select( CustomAnimationEffectPtr pEffect, bool bSelect /* = true */ ) 543 { 544 CustomAnimationListEntry* pEntry = static_cast< CustomAnimationListEntry* >(First()); 545 while( pEntry ) 546 { 547 if( pEntry->getEffect() == pEffect ) 548 { 549 Select( pEntry, bSelect ); 550 break; 551 } 552 pEntry = static_cast< CustomAnimationListEntry* >(Next( pEntry )); 553 } 554 555 if( !pEntry && bSelect ) 556 { 557 append( pEffect ); 558 select( pEffect ); 559 } 560 } 561 562 // -------------------------------------------------------------------- 563 564 void CustomAnimationList::clear() 565 { 566 Clear(); 567 568 mpLastParentEntry = 0; 569 mxLastTargetShape = 0; 570 } 571 572 // -------------------------------------------------------------------- 573 574 void CustomAnimationList::update( MainSequencePtr pMainSequence ) 575 { 576 if( mpMainSequence.get() ) 577 mpMainSequence->removeListener( this ); 578 579 mpMainSequence = pMainSequence; 580 update(); 581 582 if( mpMainSequence.get() ) 583 mpMainSequence->addListener( this ); 584 } 585 586 // -------------------------------------------------------------------- 587 588 struct stl_append_effect_func : public std::unary_function<CustomAnimationEffectPtr, void> 589 { 590 stl_append_effect_func( CustomAnimationList& rList ) : mrList( rList ) {} 591 void operator()(CustomAnimationEffectPtr pEffect); 592 CustomAnimationList& mrList; 593 }; 594 595 void stl_append_effect_func::operator()(CustomAnimationEffectPtr pEffect) 596 { 597 mrList.append( pEffect ); 598 } 599 // -------------------------------------------------------------------- 600 601 void CustomAnimationList::update() 602 { 603 mbIgnorePaint = true; 604 605 CustomAnimationListEntry* pEntry = 0; 606 607 std::list< CustomAnimationEffectPtr > aExpanded; 608 std::list< CustomAnimationEffectPtr > aSelected; 609 610 CustomAnimationEffectPtr pFirstVisibleEffect; 611 612 if( mpMainSequence.get() ) 613 { 614 // save selection and expand states 615 pEntry = static_cast<CustomAnimationListEntry*>(FirstVisible()); 616 if( pEntry ) 617 pFirstVisibleEffect = pEntry->getEffect(); 618 619 pEntry = static_cast<CustomAnimationListEntry*>(First()); 620 621 while( pEntry ) 622 { 623 CustomAnimationEffectPtr pEffect( pEntry->getEffect() ); 624 if( pEffect.get() ) 625 { 626 if( IsExpanded( pEntry ) ) 627 aExpanded.push_back( pEffect ); 628 629 if( IsSelected( pEntry ) ) 630 aSelected.push_back( pEffect ); 631 } 632 633 pEntry = static_cast<CustomAnimationListEntry*>(Next( pEntry )); 634 } 635 } 636 637 // rebuild list 638 clear(); 639 if( mpMainSequence.get() ) 640 { 641 std::for_each( mpMainSequence->getBegin(), mpMainSequence->getEnd(), stl_append_effect_func( *this ) ); 642 mpLastParentEntry = 0; 643 644 const InteractiveSequenceList& rISL = mpMainSequence->getInteractiveSequenceList(); 645 646 InteractiveSequenceList::const_iterator aIter( rISL.begin() ); 647 const InteractiveSequenceList::const_iterator aEnd( rISL.end() ); 648 while( aIter != aEnd ) 649 { 650 InteractiveSequencePtr pIS( (*aIter++) ); 651 652 Reference< XShape > xShape( pIS->getTriggerShape() ); 653 if( xShape.is() ) 654 { 655 SvLBoxEntry* pLBoxEntry = new CustomAnimationListEntry; 656 pLBoxEntry->AddItem( new SvLBoxContextBmp( pLBoxEntry, 0, Image(), Image(), 0)); 657 OUString aDescription = String( SdResId( STR_CUSTOMANIMATION_TRIGGER ) ); 658 aDescription += OUString( RTL_CONSTASCII_USTRINGPARAM(": ") ); 659 aDescription += getShapeDescription( xShape, false ); 660 pLBoxEntry->AddItem( new CustomAnimationTriggerEntryItem( pLBoxEntry, 0, aDescription, this ) ); 661 Insert( pLBoxEntry ); 662 SvViewData* pViewData = GetViewData( pLBoxEntry ); 663 if( pViewData ) 664 pViewData->SetSelectable(false); 665 666 std::for_each( pIS->getBegin(), pIS->getEnd(), stl_append_effect_func( *this ) ); 667 mpLastParentEntry = 0; 668 } 669 } 670 671 // restore selection and expand states 672 pEntry = static_cast<CustomAnimationListEntry*>(First()); 673 674 while( pEntry ) 675 { 676 CustomAnimationEffectPtr pEffect( pEntry->getEffect() ); 677 if( pEffect.get() ) 678 { 679 if( std::find( aExpanded.begin(), aExpanded.end(), pEffect ) != aExpanded.end() ) 680 Expand( pEntry ); 681 682 if( std::find( aSelected.begin(), aSelected.end(), pEffect ) != aSelected.end() ) 683 Select( pEntry ); 684 685 if( pFirstVisibleEffect == pEffect ) 686 MakeVisible( pEntry ); 687 } 688 689 pEntry = static_cast<CustomAnimationListEntry*>(Next( pEntry )); 690 } 691 } 692 693 mbIgnorePaint = false; 694 Invalidate(); 695 } 696 697 // -------------------------------------------------------------------- 698 699 /* 700 void CustomAnimationList::update( CustomAnimationEffectPtr pEffect ) 701 { 702 SvLBoxEntry* pEntry = First(); 703 while( pEntry ) 704 { 705 if( static_cast< CustomAnimationEffectPtr * >( pEntry->GetUserData() )->get() == pEffect.get() ) 706 { 707 CustomAnimationPresetsPtr pPresets = mpController->getPresets(); 708 const CustomAnimationPresetPtr pPreset = pPresets->getEffectDescriptor( pEffect->getPresetId() ); 709 if( pPreset.get() ) 710 pEffect->setName( pPresets->getUINameForPresetId( pPreset->getPresetId() ) ); 711 else 712 pEffect->setName( pEffect->getPresetId() ); 713 break; 714 } 715 pEntry = Next( pEntry ); 716 } 717 718 Invalidate(); 719 } 720 */ 721 722 // -------------------------------------------------------------------- 723 724 void CustomAnimationList::append( CustomAnimationEffectPtr pEffect ) 725 { 726 // create a ui description 727 OUString aDescription; 728 729 Any aTarget( pEffect->getTarget() ); 730 if( aTarget.hasValue() ) try 731 { 732 aDescription = getDescription( aTarget, pEffect->getTargetSubItem() != ShapeAnimationSubType::ONLY_BACKGROUND ); 733 734 SvLBoxEntry* pParentEntry = 0; 735 736 Reference< XShape > xTargetShape( pEffect->getTargetShape() ); 737 sal_Int32 nGroupId = pEffect->getGroupId(); 738 739 // if this effect has the same target and group-id as the last root effect, 740 // the last root effect is also this effects parent 741 if( mpLastParentEntry && (nGroupId != -1) && (mxLastTargetShape == xTargetShape) && (mnLastGroupId == nGroupId) ) 742 pParentEntry = mpLastParentEntry; 743 744 // create an entry for the effect 745 SvLBoxEntry* pEntry = new CustomAnimationListEntry( pEffect ); 746 747 pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), 0)); 748 pEntry->AddItem( new CustomAnimationListEntryItem( pEntry, 0, aDescription, pEffect, this ) ); 749 750 if( pParentEntry ) 751 { 752 // add a subentry 753 Insert( pEntry, pParentEntry ); 754 } 755 else 756 { 757 // add a root entry 758 Insert( pEntry ); 759 760 // and the new root entry becomes the possible next group header 761 mxLastTargetShape = xTargetShape; 762 mnLastGroupId = nGroupId; 763 mpLastParentEntry = pEntry; 764 } 765 } 766 catch( Exception& e ) 767 { 768 (void)e; 769 DBG_ERROR("sd::CustomAnimationList::append(), exception catched!" ); 770 } 771 } 772 773 // -------------------------------------------------------------------- 774 775 /* 776 void CustomAnimationList::remove( CustomAnimationEffectPtr pEffect ) 777 { 778 SvLBoxEntry* pEntry = First(); 779 while( pEntry ) 780 { 781 if( static_cast< CustomAnimationEffectPtr * >( pEntry->GetUserData() )->get() == pEffect.get() ) 782 { 783 GetModel()->Remove( pEntry ); 784 if( pEntry == mpLastParentEntry ) 785 { 786 mpLastParentEntry = 0; 787 mxLastTargetShape = 0; 788 } 789 break; 790 } 791 pEntry = Next( pEntry ); 792 } 793 794 Invalidate(); 795 } 796 */ 797 798 // -------------------------------------------------------------------- 799 800 void selectShape( SvTreeListBox* pTreeList, Reference< XShape > xShape ) 801 { 802 CustomAnimationListEntry* pEntry = static_cast< CustomAnimationListEntry* >(pTreeList->First()); 803 while( pEntry ) 804 { 805 CustomAnimationEffectPtr pEffect( pEntry->getEffect() ); 806 if( pEffect.get() ) 807 { 808 if( pEffect->getTarget() == xShape ) 809 pTreeList->Select( pEntry ); 810 } 811 812 pEntry = static_cast< CustomAnimationListEntry* >(pTreeList->Next( pEntry )); 813 } 814 } 815 816 // -------------------------------------------------------------------- 817 818 void CustomAnimationList::onSelectionChanged( Any aSelection ) 819 { 820 try 821 { 822 SelectAll(sal_False); 823 824 if( aSelection.hasValue() ) 825 { 826 Reference< XIndexAccess > xShapes( aSelection, UNO_QUERY ); 827 if( xShapes.is() ) 828 { 829 sal_Int32 nCount = xShapes->getCount(); 830 sal_Int32 nIndex; 831 for( nIndex = 0; nIndex < nCount; nIndex++ ) 832 { 833 Reference< XShape > xShape( xShapes->getByIndex( nIndex ), UNO_QUERY ); 834 if( xShape.is() ) 835 selectShape( this, xShape ); 836 } 837 } 838 else 839 { 840 Reference< XShape > xShape( aSelection, UNO_QUERY ); 841 if( xShape.is() ) 842 selectShape( this, xShape ); 843 } 844 } 845 846 SelectHdl(); 847 } 848 catch( Exception& ) 849 { 850 DBG_ERROR( "sd::CustomAnimationList::onSelectionChanged(), Exception catched!" ); 851 } 852 } 853 854 // -------------------------------------------------------------------- 855 856 void CustomAnimationList::SelectHdl() 857 { 858 SvTreeListBox::SelectHdl(); 859 mpController->onSelect(); 860 } 861 862 // -------------------------------------------------------------------- 863 864 bool CustomAnimationList::isExpanded( const CustomAnimationEffectPtr& pEffect ) const 865 { 866 CustomAnimationListEntry* pEntry = static_cast<CustomAnimationListEntry*>(First()); 867 868 while( pEntry ) 869 { 870 if( pEntry->getEffect() == pEffect ) 871 break; 872 873 pEntry = static_cast<CustomAnimationListEntry*>(Next( pEntry )); 874 } 875 876 if( pEntry ) 877 pEntry = static_cast<CustomAnimationListEntry*>(GetParent( pEntry )); 878 879 return (pEntry == 0) || IsExpanded( pEntry ); 880 } 881 882 // -------------------------------------------------------------------- 883 EffectSequence CustomAnimationList::getSelection() const 884 { 885 EffectSequence aSelection; 886 887 CustomAnimationListEntry* pEntry = dynamic_cast< CustomAnimationListEntry* >(FirstSelected()); 888 while( pEntry ) 889 { 890 CustomAnimationEffectPtr pEffect( pEntry->getEffect() ); 891 if( pEffect.get() ) 892 aSelection.push_back( pEffect ); 893 894 // if the selected effect is not expanded and has children 895 // we say that the children are automaticly selected 896 if( !IsExpanded( pEntry ) ) 897 { 898 CustomAnimationListEntry* pChild = dynamic_cast< CustomAnimationListEntry* >( FirstChild( pEntry ) ); 899 while( pChild ) 900 { 901 if( !IsSelected( pChild ) ) 902 { 903 CustomAnimationEffectPtr pChildEffect( pChild->getEffect() ); 904 if( pChildEffect.get() ) 905 aSelection.push_back( pChildEffect ); 906 } 907 908 pChild = dynamic_cast< CustomAnimationListEntry* >( NextSibling( pChild ) ); 909 } 910 } 911 912 pEntry = static_cast< CustomAnimationListEntry* >(NextSelected( pEntry )); 913 } 914 915 return aSelection; 916 } 917 918 // -------------------------------------------------------------------- 919 920 sal_Bool CustomAnimationList::DoubleClickHdl() 921 { 922 mpController->onDoubleClick(); 923 return false; 924 } 925 926 // -------------------------------------------------------------------- 927 928 PopupMenu* CustomAnimationList::CreateContextMenu() 929 { 930 PopupMenu* pMenu = new PopupMenu(SdResId( RID_EFFECT_CONTEXTMENU )); 931 932 sal_Int16 nNodeType = -1; 933 sal_Int16 nEntries = 0; 934 935 CustomAnimationListEntry* pEntry = static_cast< CustomAnimationListEntry* >(FirstSelected()); 936 while( pEntry ) 937 { 938 nEntries++; 939 CustomAnimationEffectPtr pEffect( pEntry->getEffect() ); 940 if( pEffect.get() ) 941 { 942 if( nNodeType == -1 ) 943 { 944 nNodeType = pEffect->getNodeType(); 945 } 946 else 947 { 948 if( nNodeType != pEffect->getNodeType() ) 949 { 950 nNodeType = -1; 951 break; 952 } 953 } 954 } 955 956 pEntry = static_cast< CustomAnimationListEntry* >(NextSelected( pEntry )); 957 } 958 959 pMenu->CheckItem( CM_WITH_CLICK, nNodeType == EffectNodeType::ON_CLICK ); 960 pMenu->CheckItem( CM_WITH_PREVIOUS, nNodeType == EffectNodeType::WITH_PREVIOUS ); 961 pMenu->CheckItem( CM_AFTER_PREVIOUS, nNodeType == EffectNodeType::AFTER_PREVIOUS ); 962 pMenu->EnableItem( CM_OPTIONS, nEntries == 1 ); 963 pMenu->EnableItem( CM_DURATION, nEntries == 1 ); 964 965 return pMenu; 966 } 967 968 // -------------------------------------------------------------------- 969 970 void CustomAnimationList::ExcecuteContextMenuAction( sal_uInt16 nSelectedPopupEntry ) 971 { 972 mpController->onContextMenu( nSelectedPopupEntry ); 973 } 974 975 // -------------------------------------------------------------------- 976 977 void CustomAnimationList::SetTabs() 978 { 979 SvTreeListBox::SetTabs(); 980 } 981 982 // -------------------------------------------------------------------- 983 984 void CustomAnimationList::notify_change() 985 { 986 update(); 987 mpController->onSelect(); 988 } 989 990 void CustomAnimationList::Paint( const Rectangle& rRect ) 991 { 992 if( mbIgnorePaint ) 993 return; 994 995 SvTreeListBox::Paint( rRect ); 996 997 // draw help text if list box is still empty 998 if( First() == 0 ) 999 { 1000 Color aOldColor( GetTextColor() ); 1001 SetTextColor( GetSettings().GetStyleSettings().GetDisableColor() ); 1002 ::Point aOffset( LogicToPixel( Point( 6, 6 ), MAP_APPFONT ) ); 1003 1004 Rectangle aRect( Point( 0,0 ), GetOutputSizePixel() ); 1005 1006 aRect.Left() += aOffset.X(); 1007 aRect.Top() += aOffset.Y(); 1008 aRect.Right() -= aOffset.X(); 1009 aRect.Bottom() -= aOffset.Y(); 1010 1011 DrawText( aRect, String( SdResId( STR_CUSTOMANIMATION_LIST_HELPTEXT ) ), 1012 TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK | TEXT_DRAW_CENTER | TEXT_DRAW_VCENTER ); 1013 1014 SetTextColor( aOldColor ); 1015 } 1016 } 1017 1018 } 1019