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