xref: /AOO41X/main/sd/source/ui/animations/CustomAnimationList.cxx (revision 79aad27f7f29270c03e208e3d687e8e3850af11d)
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.
getShapeIndex(const Reference<XShapes> & xShapes,const Reference<XShape> & xShape,sal_Int32 & nIndex)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
getShapeIndex(const Reference<XShape> & xShape)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 
getShapeDescription(const Reference<XShape> & xShape,bool bWithText=true)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 
getDescription(const Any & rTarget,bool bWithText=true)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 
CustomAnimationListEntryItem(SvLBoxEntry * pEntry,sal_uInt16 nFlags,OUString aDescription,CustomAnimationEffectPtr pEffect,CustomAnimationList * pParent)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 
~CustomAnimationListEntryItem()238 CustomAnimationListEntryItem::~CustomAnimationListEntryItem()
239 {
240 }
241 
242 // --------------------------------------------------------------------
243 
InitViewData(SvLBox * pView,SvLBoxEntry * pEntry,SvViewDataItem * pViewData)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 
Paint(const Point & rPos,SvLBox & rDev,sal_uInt16,SvLBoxEntry * pEntry)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 
Create() const314 SvLBoxItem* CustomAnimationListEntryItem::Create() const
315 {
316     return NULL;
317 }
318 
319 // --------------------------------------------------------------------
320 
Clone(SvLBoxItem *)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 
getEffect() const334     CustomAnimationEffectPtr getEffect() const { return mpEffect; }
335 
336 private:
337     CustomAnimationEffectPtr mpEffect;
338 };
339 
340 // --------------------------------------------------------------------
341 
CustomAnimationListEntry()342 CustomAnimationListEntry::CustomAnimationListEntry()
343 {
344 }
345 
346 // --------------------------------------------------------------------
347 
CustomAnimationListEntry(CustomAnimationEffectPtr pEffect)348 CustomAnimationListEntry::CustomAnimationListEntry( CustomAnimationEffectPtr pEffect )
349 : mpEffect( pEffect )
350 {
351 }
352 
353 // --------------------------------------------------------------------
354 
~CustomAnimationListEntry()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 
CustomAnimationTriggerEntryItem(SvLBoxEntry * pEntry,sal_uInt16 nFlags,OUString aDescription,CustomAnimationList * pParent)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 
~CustomAnimationTriggerEntryItem()386 CustomAnimationTriggerEntryItem::~CustomAnimationTriggerEntryItem()
387 {
388 }
389 
390 // --------------------------------------------------------------------
391 
IsA()392 sal_uInt16 CustomAnimationTriggerEntryItem::IsA()
393 {
394     return (sal_uInt16)-1;
395 }
396 
397 // --------------------------------------------------------------------
398 
InitViewData(SvLBox * pView,SvLBoxEntry * pEntry,SvViewDataItem * pViewData)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 
Paint(const Point & rPos,SvLBox & rDev,sal_uInt16,SvLBoxEntry *)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 
Create() const457 SvLBoxItem* CustomAnimationTriggerEntryItem::Create() const
458 {
459     return NULL;
460 }
461 
462 // --------------------------------------------------------------------
463 
Clone(SvLBoxItem *)464 void CustomAnimationTriggerEntryItem::Clone( SvLBoxItem* )
465 {
466 }
467 
468 // ====================================================================
469 
CustomAnimationList(::Window * pParent,const ResId & rResId,ICustomAnimationListController * pController)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 
getImage(sal_uInt16 nId,bool bHighContrast)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 
~CustomAnimationList()504 CustomAnimationList::~CustomAnimationList()
505 {
506     if( mpMainSequence.get() )
507         mpMainSequence->removeListener( this );
508 
509     clear();
510 }
511 
512 // --------------------------------------------------------------------
513 
KeyInput(const KeyEvent & rKEvt)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 */
select(CustomAnimationEffectPtr pEffect,bool bSelect)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 
clear()560 void CustomAnimationList::clear()
561 {
562     Clear();
563 
564     mpLastParentEntry = 0;
565     mxLastTargetShape = 0;
566 }
567 
568 // --------------------------------------------------------------------
569 
update(MainSequencePtr pMainSequence)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 {
stl_append_effect_funcsd::stl_append_effect_func586     stl_append_effect_func( CustomAnimationList& rList ) : mrList( rList ) {}
587     void operator()(CustomAnimationEffectPtr pEffect);
588     CustomAnimationList& mrList;
589 };
590 
operator ()(CustomAnimationEffectPtr pEffect)591 void stl_append_effect_func::operator()(CustomAnimationEffectPtr pEffect)
592 {
593     mrList.append( pEffect );
594 }
595 // --------------------------------------------------------------------
596 
update()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 
append(CustomAnimationEffectPtr pEffect)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 
selectShape(SvTreeListBox * pTreeList,Reference<XShape> xShape)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 
onSelectionChanged(Any aSelection)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 
SelectHdl()852 void CustomAnimationList::SelectHdl()
853 {
854     SvTreeListBox::SelectHdl();
855     mpController->onSelect();
856 }
857 
858 // --------------------------------------------------------------------
859 
isExpanded(const CustomAnimationEffectPtr & pEffect) const860 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 // --------------------------------------------------------------------
getSelection() const879 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 
DoubleClickHdl()916 sal_Bool CustomAnimationList::DoubleClickHdl()
917 {
918     mpController->onDoubleClick();
919     return false;
920 }
921 
922 // --------------------------------------------------------------------
923 
CreateContextMenu()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 
ExcecuteContextMenuAction(sal_uInt16 nSelectedPopupEntry)966 void CustomAnimationList::ExcecuteContextMenuAction( sal_uInt16 nSelectedPopupEntry )
967 {
968     mpController->onContextMenu( nSelectedPopupEntry );
969 }
970 
971 // --------------------------------------------------------------------
972 
SetTabs()973 void CustomAnimationList::SetTabs()
974 {
975     SvTreeListBox::SetTabs();
976 }
977 
978 // --------------------------------------------------------------------
979 
notify_change()980 void CustomAnimationList::notify_change()
981 {
982     update();
983     mpController->onSelect();
984 }
985 
Paint(const Rectangle & rRect)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