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 automatically 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