1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sd.hxx"
30 #include <com/sun/star/animations/XAnimationNode.hpp>
31 
32 #include "SlideTransitionPane.hxx"
33 #include "SlideTransitionPane.hrc"
34 #include "CustomAnimation.hrc"
35 
36 #include "TransitionPreset.hxx"
37 #include "sdresid.hxx"
38 #include "ViewShellBase.hxx"
39 #include "DrawDocShell.hxx"
40 #include "SlideSorterViewShell.hxx"
41 #include "drawdoc.hxx"
42 #include "filedlg.hxx"
43 #include "strings.hrc"
44 #include "DrawController.hxx"
45 #include <com/sun/star/beans/XPropertySet.hpp>
46 
47 #ifndef _SVT_CONTROLDIMS_HRC_
48 #include <svtools/controldims.hrc>
49 #endif
50 #include <svx/gallery.hxx>
51 #include <unotools/pathoptions.hxx>
52 #include <vcl/msgbox.hxx>
53 #include <tools/urlobj.hxx>
54 #include "DrawViewShell.hxx"
55 #include "slideshow.hxx"
56 #include "drawview.hxx"
57 #include "sdundogr.hxx"
58 #include "undoanim.hxx"
59 #include "optsitem.hxx"
60 #include "sddll.hxx"
61 #include "framework/FrameworkHelper.hxx"
62 
63 #include "DialogListBox.hxx"
64 
65 #include <algorithm>
66 #include <memory>
67 
68 
69 using namespace ::com::sun::star;
70 
71 using ::com::sun::star::uno::Reference;
72 using ::com::sun::star::uno::Sequence;
73 using ::rtl::OUString;
74 using ::com::sun::star::uno::RuntimeException;
75 
76 using ::sd::framework::FrameworkHelper;
77 
78 // ____________________________
79 //
80 // ::sd::impl::TransitionEffect
81 // ____________________________
82 
83 namespace sd
84 {
85 namespace impl
86 {
87 struct TransitionEffect
88 {
89     TransitionEffect() :
90             mnType( 0 ),
91             mnSubType( 0 ),
92             mbDirection( sal_True ),
93             mnFadeColor( 0 )
94     {
95         init();
96     }
97     explicit TransitionEffect( const ::sd::TransitionPreset & rPreset ) :
98             mnType( rPreset.getTransition()),
99             mnSubType( rPreset.getSubtype()),
100             mbDirection( rPreset.getDirection()),
101             mnFadeColor( rPreset.getFadeColor())
102     {
103         init();
104     }
105     explicit TransitionEffect( sal_Int16 nType, sal_Int16 nSubType,
106                                sal_Bool  bDirection, sal_Int32 nFadeColor ) :
107             mnType( nType),
108             mnSubType( nSubType ),
109             mbDirection( bDirection ),
110             mnFadeColor( nFadeColor )
111     {
112         init();
113     }
114     explicit TransitionEffect( const SdPage & rPage ) :
115             mnType( rPage.getTransitionType() ),
116             mnSubType( rPage.getTransitionSubtype() ),
117             mbDirection( rPage.getTransitionDirection() ),
118             mnFadeColor( rPage.getTransitionFadeColor() )
119     {
120         init();
121 
122         mfDuration = rPage.getTransitionDuration();
123         mnTime = rPage.GetTime();
124         mePresChange = rPage.GetPresChange();
125         mbSoundOn = rPage.IsSoundOn();
126         maSound = rPage.GetSoundFile();
127 		mbLoopSound = rPage.IsLoopSound();
128 		mbStopSound = rPage.IsStopSound();
129     }
130 
131     void init()
132     {
133         mfDuration = 2.0;
134         mnTime = 0;
135         mePresChange = PRESCHANGE_MANUAL;
136         mbSoundOn = sal_False;
137 		mbLoopSound = sal_False;
138 		mbStopSound = sal_False;
139 
140         mbEffectAmbiguous = false;
141         mbDurationAmbiguous = false;
142         mbTimeAmbiguous = false;
143         mbPresChangeAmbiguous = false;
144         mbSoundAmbiguous = false;
145         mbLoopSoundAmbiguous = false;
146     }
147 
148     void setAllAmbiguous()
149     {
150         mbEffectAmbiguous = true;
151         mbDurationAmbiguous = true;
152         mbTimeAmbiguous = true;
153         mbPresChangeAmbiguous = true;
154         mbSoundAmbiguous = true;
155 		mbLoopSoundAmbiguous = true;
156     }
157 
158     bool operator == ( const ::sd::TransitionPreset & rPreset ) const
159     {
160         return
161             (mnType == rPreset.getTransition()) &&
162             (mnSubType == rPreset.getSubtype()) &&
163             (mbDirection == rPreset.getDirection()) &&
164             (mnFadeColor ==  rPreset.getFadeColor());
165     }
166 
167     void applyTo( SdPage & rOutPage ) const
168     {
169         if( ! mbEffectAmbiguous )
170         {
171 			rOutPage.setTransitionType( mnType );
172 			rOutPage.setTransitionSubtype( mnSubType );
173             rOutPage.setTransitionDirection( mbDirection );
174             rOutPage.setTransitionFadeColor( mnFadeColor );
175         }
176 
177         if( ! mbDurationAmbiguous )
178             rOutPage.setTransitionDuration( mfDuration );
179         if( ! mbTimeAmbiguous )
180             rOutPage.SetTime( mnTime );
181         if( ! mbPresChangeAmbiguous )
182             rOutPage.SetPresChange( mePresChange );
183         if( ! mbSoundAmbiguous )
184 		{
185 			if( mbStopSound )
186 			{
187 				rOutPage.SetStopSound( sal_True );
188 	            rOutPage.SetSound( sal_False );
189 			}
190 			else
191 			{
192 				rOutPage.SetStopSound( sal_False );
193 	            rOutPage.SetSound( mbSoundOn );
194 		        rOutPage.SetSoundFile( maSound );
195 			}
196 		}
197 		if( ! mbLoopSoundAmbiguous )
198 			rOutPage.SetLoopSound( mbLoopSound );
199     }
200 
201     void compareWith( const SdPage & rPage )
202     {
203         TransitionEffect aOtherEffect( rPage );
204         mbEffectAmbiguous = mbEffectAmbiguous || aOtherEffect.mbEffectAmbiguous
205 											  || (mnType != aOtherEffect.mnType)
206 											  || (mnSubType != aOtherEffect.mnSubType)
207 											  || (mbDirection != aOtherEffect.mbDirection)
208 											  || (mnFadeColor != aOtherEffect.mnFadeColor);
209 
210         mbDurationAmbiguous = mbDurationAmbiguous || aOtherEffect.mbDurationAmbiguous || mfDuration != aOtherEffect.mfDuration;
211         mbTimeAmbiguous = mbTimeAmbiguous || aOtherEffect.mbTimeAmbiguous || mnTime != aOtherEffect.mnTime;
212         mbPresChangeAmbiguous = mbPresChangeAmbiguous || aOtherEffect.mbPresChangeAmbiguous || mePresChange != aOtherEffect.mePresChange;
213         mbSoundAmbiguous = mbSoundAmbiguous || aOtherEffect.mbSoundAmbiguous || mbSoundOn != aOtherEffect.mbSoundOn;
214 						(!mbStopSound && !aOtherEffect.mbStopSound && maSound != aOtherEffect.maSound) || (mbStopSound != aOtherEffect.mbStopSound);
215 		mbLoopSoundAmbiguous = mbLoopSoundAmbiguous || aOtherEffect.mbLoopSoundAmbiguous || mbLoopSound != aOtherEffect.mbLoopSound;
216     }
217 
218     // effect
219     sal_Int16 mnType;
220     sal_Int16 mnSubType;
221     sal_Bool  mbDirection;
222     sal_Int32 mnFadeColor;
223 
224     // other settings
225     double		mfDuration;
226     sal_uLong       mnTime;
227     PresChange  mePresChange;
228     sal_Bool        mbSoundOn;
229     String      maSound;
230 	bool		mbLoopSound;
231 	bool		mbStopSound;
232 
233     bool mbEffectAmbiguous;
234     bool mbDurationAmbiguous;
235     bool mbTimeAmbiguous;
236     bool mbPresChangeAmbiguous;
237     bool mbSoundAmbiguous;
238     bool mbLoopSoundAmbiguous;
239 };
240 
241 } // namespace impl
242 } // namespace sd
243 
244 // ______________________
245 //
246 // Local Helper Functions
247 // ______________________
248 
249 namespace
250 {
251 
252 void lcl_ApplyToPages(
253     const ::sd::slidesorter::SharedPageSelection& rpPages,
254     const ::sd::impl::TransitionEffect & rEffect )
255 {
256     ::std::vector< SdPage * >::const_iterator aIt( rpPages->begin());
257     const ::std::vector< SdPage * >::const_iterator aEndIt( rpPages->end());
258     for( ; aIt != aEndIt; ++aIt )
259     {
260         rEffect.applyTo( *(*aIt) );
261     }
262 }
263 
264 void lcl_CreateUndoForPages(
265     const ::sd::slidesorter::SharedPageSelection& rpPages,
266     ::sd::ViewShellBase& rBase )
267 {
268 	::sd::DrawDocShell* pDocSh	    = rBase.GetDocShell();
269 	::svl::IUndoManager* pManager   = pDocSh->GetUndoManager();
270 	SdDrawDocument*	pDoc		    = pDocSh->GetDoc();
271 	if( pManager && pDocSh && pDoc )
272 	{
273 		String aComment( SdResId(STR_UNDO_SLIDE_PARAMS) );
274 		pManager->EnterListAction(aComment, aComment);
275 		SdUndoGroup* pUndoGroup = new SdUndoGroup( pDoc );
276 		pUndoGroup->SetComment( aComment );
277 
278 		::std::vector< SdPage * >::const_iterator aIt( rpPages->begin());
279 		const ::std::vector< SdPage * >::const_iterator aEndIt( rpPages->end());
280 		for( ; aIt != aEndIt; ++aIt )
281 		{
282 			pUndoGroup->AddAction( new sd::UndoTransition( pDoc, (*aIt) ) );
283 		}
284 
285 		pManager->AddUndoAction( pUndoGroup );
286 		pManager->LeaveListAction();
287 	}
288 }
289 
290 sal_uInt16 lcl_getTransitionEffectIndex(
291     SdDrawDocument * pDoc,
292     const ::sd::impl::TransitionEffect & rTransition )
293 {
294     // first entry: "<none>"
295     sal_uInt16 nResultIndex = LISTBOX_ENTRY_NOTFOUND;
296 
297     if( pDoc )
298     {
299         sal_uInt16 nCurrentIndex = 0;
300 		const ::sd::TransitionPresetList & rPresetList = ::sd::TransitionPreset::getTransitionPresetList();
301         ::sd::TransitionPresetList::const_iterator aIt( rPresetList.begin());
302         const ::sd::TransitionPresetList::const_iterator aEndIt( rPresetList.end());
303         for( ; aIt != aEndIt; ++aIt, ++nCurrentIndex )
304         {
305             if( rTransition.operator==( *(*aIt) ))
306             {
307                 nResultIndex = nCurrentIndex;
308                 break;
309             }
310         }
311     }
312 
313     return nResultIndex;
314 }
315 
316 ::sd::TransitionPresetPtr lcl_getTransitionPresetByUIName(
317     SdDrawDocument * pDoc,
318     const OUString & rUIName )
319 {
320     ::sd::TransitionPresetPtr pResult;
321     if( pDoc )
322     {
323 		const ::sd::TransitionPresetList& rPresetList = ::sd::TransitionPreset::getTransitionPresetList();
324         ::sd::TransitionPresetList::const_iterator aIter( rPresetList.begin() );
325         const ::sd::TransitionPresetList::const_iterator aEnd( rPresetList.end() );
326         for( ; aIter != aEnd; ++aIter )
327         {
328             if( (*aIter)->getUIName().equals( rUIName ))
329             {
330                 pResult = *aIter;
331                 break;
332             }
333         }
334     }
335 
336     return pResult;
337 }
338 
339 struct lcl_EqualsSoundFileName : public ::std::unary_function< String, bool >
340 {
341     explicit lcl_EqualsSoundFileName( const String & rStr ) :
342             maStr( rStr )
343     {}
344 
345     bool operator() ( const String & rStr ) const
346     {
347         // note: formerly this was a case insensitive search for all
348         // platforms. It seems more sensible to do this platform-dependent
349 #if defined( WNT )
350         return maStr.EqualsIgnoreCaseAscii( rStr );
351 #else
352         return maStr.Equals( rStr );
353 #endif
354     }
355 
356 private:
357     String maStr;
358 };
359 
360 // returns -1 if no object was found
361 bool lcl_findSoundInList( const ::std::vector< String > & rSoundList,
362                           const String & rFileName,
363                           ::std::vector< String >::size_type & rOutPosition )
364 {
365     ::std::vector< String >::const_iterator aIt =
366           ::std::find_if( rSoundList.begin(), rSoundList.end(),
367                           lcl_EqualsSoundFileName( rFileName ));
368     if( aIt != rSoundList.end())
369     {
370         rOutPosition = ::std::distance( rSoundList.begin(), aIt );
371         return true;
372     }
373 
374     return false;
375 }
376 
377 String lcl_getSoundFileURL(
378     const ::std::vector< String > & rSoundList,
379     const ListBox & rListBox )
380 {
381     String aResult;
382 
383     if( rListBox.GetSelectEntryCount() > 0 )
384     {
385         sal_uInt16 nPos = rListBox.GetSelectEntryPos();
386         // the first three entries are no actual sounds
387         if( nPos >= 3 )
388         {
389             DBG_ASSERT( (sal_uInt32)(rListBox.GetEntryCount() - 3) == rSoundList.size(),
390                         "Sound list-box is not synchronized to sound list" );
391             nPos -= 3;
392             if( rSoundList.size() > nPos )
393                 aResult = rSoundList[ nPos ];
394         }
395     }
396 
397     return aResult;
398 }
399 
400 struct lcl_AppendSoundToListBox : public ::std::unary_function< String, void >
401 {
402     lcl_AppendSoundToListBox( ListBox & rListBox ) :
403             mrListBox( rListBox )
404     {}
405 
406     void operator() ( const String & rString ) const
407     {
408         INetURLObject aURL( rString );
409         mrListBox.InsertEntry( aURL.GetBase(), LISTBOX_APPEND );
410     }
411 
412 private:
413     ListBox & mrListBox;
414 };
415 
416 void lcl_FillSoundListBox(
417     const ::std::vector< String > & rSoundList,
418     ListBox & rOutListBox )
419 {
420     sal_uInt16 nCount = rOutListBox.GetEntryCount();
421 
422     // keep first three entries
423     for( sal_uInt16 i=nCount - 1; i>=3; --i )
424         rOutListBox.RemoveEntry( i );
425 
426     ::std::for_each( rSoundList.begin(), rSoundList.end(),
427                      lcl_AppendSoundToListBox( rOutListBox ));
428 }
429 
430 } // anonymous namespace
431 
432 namespace sd
433 {
434 
435 // ___________________
436 //
437 // SlideTransitionPane
438 // ___________________
439 
440 SlideTransitionPane::SlideTransitionPane(
441     ::Window * pParent,
442     ViewShellBase & rBase,
443     const Size& rMinSize,
444     SdDrawDocument* pDoc ) :
445         Control( pParent, SdResId( DLG_SLIDE_TRANSITION_PANE ) ),
446 
447         mrBase( rBase ),
448         mpDrawDoc( pDoc ),
449         maMinSize( rMinSize ),
450         maFL_APPLY_TRANSITION( this, SdResId( FL_APPLY_TRANSITION ) ),
451         maLB_SLIDE_TRANSITIONS( this, SdResId( LB_SLIDE_TRANSITIONS ) ),
452         maFL_MODIFY_TRANSITION( this, SdResId( FL_MODIFY_TRANSITION ) ),
453         maFT_SPEED( this, SdResId( FT_SPEED ) ),
454         maLB_SPEED( this, SdResId( LB_SPEED ) ),
455         maFT_SOUND( this, SdResId( FT_SOUND ) ),
456         maLB_SOUND( this, SdResId( LB_SOUND ) ),
457         maCB_LOOP_SOUND( this, SdResId( CB_LOOP_SOUND ) ),
458         maFL_ADVANCE_SLIDE( this, SdResId( FL_ADVANCE_SLIDE ) ),
459         maRB_ADVANCE_ON_MOUSE( this, SdResId( RB_ADVANCE_ON_MOUSE ) ),
460         maRB_ADVANCE_AUTO( this, SdResId( RB_ADVANCE_AUTO ) ),
461         maMF_ADVANCE_AUTO_AFTER( this, SdResId( MF_ADVANCE_AUTO_AFTER ) ),
462         maFL_EMPTY1( this, SdResId( FL_EMPTY1 ) ),
463         maPB_APPLY_TO_ALL( this, SdResId( PB_APPLY_TO_ALL ) ),
464         maPB_PLAY( this, SdResId( PB_PLAY ) ),
465         maPB_SLIDE_SHOW( this, SdResId( PB_SLIDE_SHOW ) ),
466         maFL_EMPTY2( this, SdResId( FL_EMPTY2 ) ),
467         maCB_AUTO_PREVIEW( this, SdResId( CB_AUTO_PREVIEW ) ),
468 
469         maSTR_NO_TRANSITION( SdResId( STR_NO_TRANSITION ) ),
470         mbHasSelection( false ),
471         mbUpdatingControls( false ),
472         mbIsMainViewChangePending( false ),
473         maLateInitTimer()
474 {
475     // use no resource ids from here on
476     FreeResource();
477 
478     // use bold font for group headings (same font for all fixed lines):
479     Font font( maFL_APPLY_TRANSITION.GetFont() );
480     font.SetWeight( WEIGHT_BOLD );
481     maFL_APPLY_TRANSITION.SetFont( font );
482     maFL_MODIFY_TRANSITION.SetFont( font );
483     maFL_ADVANCE_SLIDE.SetFont( font );
484 
485     if( pDoc )
486         mxModel.set( pDoc->getUnoModel(), uno::UNO_QUERY );
487     // TODO: get correct view
488     if( mxModel.is())
489         mxView.set( mxModel->getCurrentController(), uno::UNO_QUERY );
490 
491     // fill list box of slide transitions
492     maLB_SLIDE_TRANSITIONS.InsertEntry( maSTR_NO_TRANSITION );
493 
494     // set defaults
495     maCB_AUTO_PREVIEW.Check();      // automatic preview on
496 
497     // update control states before adding handlers
498     updateLayout();
499     //    updateSoundList();
500     updateControls();
501 
502     // set handlers
503     maPB_APPLY_TO_ALL.SetClickHdl( LINK( this, SlideTransitionPane, ApplyToAllButtonClicked ));
504     maPB_PLAY.SetClickHdl( LINK( this, SlideTransitionPane, PlayButtonClicked ));
505     maPB_SLIDE_SHOW.SetClickHdl( LINK( this, SlideTransitionPane, SlideShowButtonClicked ));
506 
507     maLB_SLIDE_TRANSITIONS.SetSelectHdl( LINK( this, SlideTransitionPane, TransitionSelected ));
508 
509     maLB_SPEED.SetSelectHdl( LINK( this, SlideTransitionPane, SpeedListBoxSelected ));
510     maLB_SOUND.SetSelectHdl( LINK( this, SlideTransitionPane, SoundListBoxSelected ));
511     maCB_LOOP_SOUND.SetClickHdl( LINK( this, SlideTransitionPane, LoopSoundBoxChecked ));
512 
513     maRB_ADVANCE_ON_MOUSE.SetToggleHdl( LINK( this, SlideTransitionPane, AdvanceSlideRadioButtonToggled ));
514     maRB_ADVANCE_AUTO.SetToggleHdl( LINK( this, SlideTransitionPane, AdvanceSlideRadioButtonToggled ));
515     maMF_ADVANCE_AUTO_AFTER.SetModifyHdl( LINK( this, SlideTransitionPane, AdvanceTimeModified ));
516 	maCB_AUTO_PREVIEW.SetClickHdl( LINK( this, SlideTransitionPane, AutoPreviewClicked ));
517     addListener();
518 
519     maLateInitTimer.SetTimeout(200);
520     maLateInitTimer.SetTimeoutHdl(LINK(this, SlideTransitionPane, LateInitCallback));
521     maLateInitTimer.Start();
522 }
523 
524 SlideTransitionPane::~SlideTransitionPane()
525 {
526     maLateInitTimer.Stop();
527 	removeListener();
528 }
529 
530 void SlideTransitionPane::Resize()
531 {
532 	updateLayout();
533 }
534 
535 void SlideTransitionPane::onSelectionChanged()
536 {
537     updateControls();
538 }
539 
540 void SlideTransitionPane::onChangeCurrentPage()
541 {
542     updateControls();
543 }
544 
545 ::sd::slidesorter::SharedPageSelection SlideTransitionPane::getSelectedPages (void) const
546 {
547     ::sd::slidesorter::SlideSorterViewShell * pSlideSorterViewShell
548         = ::sd::slidesorter::SlideSorterViewShell::GetSlideSorter(mrBase);
549 //    DBG_ASSERT( pSlideSorterViewShell, "No Slide-Sorter available" );
550     ::boost::shared_ptr<sd::slidesorter::SlideSorterViewShell::PageSelection> pSelection;
551 
552     if( pSlideSorterViewShell )
553     {
554         pSelection = pSlideSorterViewShell->GetPageSelection();
555     }
556 	else
557     {
558         pSelection.reset(new sd::slidesorter::SlideSorterViewShell::PageSelection());
559         if( mxView.is() )
560         {
561             SdPage* pPage = SdPage::getImplementation( mxView->getCurrentPage() );
562             if( pPage )
563                 pSelection->push_back(pPage);
564         }
565 	}
566 
567     return pSelection;
568 }
569 
570 void SlideTransitionPane::updateLayout()
571 {
572 	::Size aPaneSize( GetSizePixel() );
573 	if( aPaneSize.Width() < maMinSize.Width() )
574 		aPaneSize.Width() = maMinSize.Width();
575 
576 	if( aPaneSize.Height() < maMinSize.Height() )
577 		aPaneSize.Height() = maMinSize.Height();
578 
579     // start layouting elements from bottom to top.  The remaining space is used
580     // for the topmost list box
581 	::Point aOffset( LogicToPixel( Point( 3, 3 ), MAP_APPFONT ) );
582     long nOffsetX = aOffset.getX();
583     long nOffsetY = aOffset.getY();
584     long nOffsetBtnX = LogicToPixel( Point( 6, 1 ), MAP_APPFONT ).getX();
585 
586     const long nMinCtrlWidth = LogicToPixel( ::Point( 32, 1 ), MAP_APPFONT ).getX();
587     const long nTextIndent = LogicToPixel( ::Point( RSC_SP_CHK_TEXTINDENT, 1 ), MAP_APPFONT ).getX();
588 
589 	::Point aUpperLeft( nOffsetX, aPaneSize.getHeight() - nOffsetY );
590     long nMaxWidth = aPaneSize.getWidth() - 2 * nOffsetX;
591 
592     // auto preview check-box
593     ::Size aCtrlSize = maCB_AUTO_PREVIEW.GetSizePixel();
594     aCtrlSize.setWidth( maCB_AUTO_PREVIEW.CalcMinimumSize( nMaxWidth ).getWidth());
595     aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight());
596     maCB_AUTO_PREVIEW.SetPosSizePixel( aUpperLeft, aCtrlSize );
597 
598     // fixed line above check-box
599     aCtrlSize = maFL_EMPTY2.GetSizePixel();
600     aCtrlSize.setWidth( nMaxWidth );
601     aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight());
602     maFL_EMPTY2.SetPosSizePixel( aUpperLeft, aCtrlSize );
603 
604     // buttons "Play" and "Slide Show"
605     long nPlayButtonWidth = maPB_PLAY.CalcMinimumSize().getWidth() + 2 * nOffsetBtnX;
606     long nSlideShowButtonWidth = maPB_SLIDE_SHOW.CalcMinimumSize().getWidth() + 2 * nOffsetBtnX;
607 
608     if( (nPlayButtonWidth + nSlideShowButtonWidth + nOffsetX) <= nMaxWidth )
609     {
610         // place buttons side by side
611         aCtrlSize = maPB_PLAY.GetSizePixel();
612         aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight());
613         aCtrlSize.setWidth( nPlayButtonWidth );
614         maPB_PLAY.SetPosSizePixel( aUpperLeft, aCtrlSize );
615 
616         aUpperLeft.setX( aUpperLeft.getX() + nPlayButtonWidth + nOffsetX );
617         aCtrlSize.setWidth( nSlideShowButtonWidth );
618         maPB_SLIDE_SHOW.SetPosSizePixel( aUpperLeft, aCtrlSize );
619         aUpperLeft.setX( nOffsetX );
620     }
621     else
622     {
623         // place buttons on top of each other
624         aCtrlSize = maPB_SLIDE_SHOW.GetSizePixel();
625         aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight());
626         aCtrlSize.setWidth( nSlideShowButtonWidth );
627         maPB_SLIDE_SHOW.SetPosSizePixel( aUpperLeft, aCtrlSize );
628 
629         aCtrlSize = maPB_PLAY.GetSizePixel();
630         aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight() - nOffsetY );
631         aCtrlSize.setWidth( nPlayButtonWidth );
632         maPB_PLAY.SetPosSizePixel( aUpperLeft, aCtrlSize );
633     }
634 
635     // "Apply to All Slides" button
636     aCtrlSize = maPB_APPLY_TO_ALL.GetSizePixel();
637     aCtrlSize.setWidth( maPB_APPLY_TO_ALL.CalcMinimumSize( nMaxWidth ).getWidth() + 2 * nOffsetBtnX );
638     aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight() - nOffsetY );
639     maPB_APPLY_TO_ALL.SetPosSizePixel( aUpperLeft, aCtrlSize );
640 
641     // fixed line above "Apply to All Slides" button
642     aCtrlSize = maFL_EMPTY1.GetSizePixel();
643     aCtrlSize.setWidth( nMaxWidth );
644     aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight());
645     maFL_EMPTY1.SetPosSizePixel( aUpperLeft, aCtrlSize );
646 
647     // advance automatically after ... seconds
648     long nItemWidth = maRB_ADVANCE_AUTO.CalcMinimumSize().getWidth();
649 
650     if( (nItemWidth + nMinCtrlWidth + nOffsetX) <= nMaxWidth )
651     {
652         long nBase = aUpperLeft.getY();
653 
654         // place controls side by side
655         aCtrlSize = maRB_ADVANCE_AUTO.GetSizePixel();
656         aUpperLeft.setY( nBase - aCtrlSize.getHeight());
657         aCtrlSize.setWidth( nItemWidth );
658         maRB_ADVANCE_AUTO.SetPosSizePixel( aUpperLeft, aCtrlSize );
659 
660         aCtrlSize = maMF_ADVANCE_AUTO_AFTER.GetSizePixel();
661         aUpperLeft.setY( nBase - aCtrlSize.getHeight() );
662         aUpperLeft.setX( aUpperLeft.getX() + nItemWidth + nOffsetX );
663         aCtrlSize.setWidth( nMinCtrlWidth );
664         maMF_ADVANCE_AUTO_AFTER.SetPosSizePixel( aUpperLeft, aCtrlSize );
665         aUpperLeft.setX( nOffsetX );
666     }
667     else
668     {
669         // place controls on top of each other
670         aCtrlSize = maMF_ADVANCE_AUTO_AFTER.GetSizePixel();
671         aUpperLeft.setX( nOffsetX + nTextIndent );
672         aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight());
673         aCtrlSize.setWidth( nMinCtrlWidth );
674         maMF_ADVANCE_AUTO_AFTER.SetPosSizePixel( aUpperLeft, aCtrlSize );
675 
676         aCtrlSize = maRB_ADVANCE_AUTO.GetSizePixel();
677         aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight() - nOffsetY );
678         aUpperLeft.setX( nOffsetX );
679         aCtrlSize.setWidth( nItemWidth );
680         maRB_ADVANCE_AUTO.SetPosSizePixel( aUpperLeft, aCtrlSize );
681         aUpperLeft.setX( nOffsetX );
682     }
683 
684     // check box "On mouse click"
685     aCtrlSize = maRB_ADVANCE_ON_MOUSE.GetSizePixel();
686     aCtrlSize.setWidth( nMaxWidth );
687     aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight() - nOffsetY );
688     maRB_ADVANCE_ON_MOUSE.SetPosSizePixel( aUpperLeft, aCtrlSize );
689 
690     // fixed line "Advance slide"
691     aCtrlSize = maFL_ADVANCE_SLIDE.GetSizePixel();
692     aCtrlSize.setWidth( nMaxWidth );
693     aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight() - nOffsetY );
694     maFL_ADVANCE_SLIDE.SetPosSizePixel( aUpperLeft, aCtrlSize );
695 
696     // check box "Loop until next sound"
697     long nFTSpeedWidth = maFT_SPEED.CalcMinimumSize().getWidth() + 2 * nOffsetX;
698     long nFTSoundWidth = maFT_SOUND.CalcMinimumSize().getWidth() + 2 * nOffsetX;
699     long nIndent = ::std::max( nFTSoundWidth, nFTSpeedWidth );
700 
701     bool bStack = ( (nIndent + nMinCtrlWidth + nOffsetX) > nMaxWidth );
702 
703     if( bStack )
704         nIndent = nTextIndent;
705 
706     aCtrlSize = maCB_LOOP_SOUND.GetSizePixel();
707     aCtrlSize.setWidth( nMaxWidth - nIndent );
708     aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight() - nOffsetY );
709     aUpperLeft.setX( nIndent );
710     maCB_LOOP_SOUND.SetPosSizePixel( aUpperLeft, aCtrlSize );
711 
712     aCtrlSize = maLB_SOUND.GetSizePixel();
713     aCtrlSize.setWidth( ::std::max( nMaxWidth - nIndent, nMinCtrlWidth ) );
714     aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight() - nOffsetY );
715     maLB_SOUND.SetPosSizePixel( aUpperLeft, aCtrlSize );
716     maLB_SOUND.SetDropDownLineCount( 8 );
717     aUpperLeft.setX( nOffsetX );
718 
719     aCtrlSize = maFT_SOUND.GetSizePixel();
720     if( bStack )
721         aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight());
722     aCtrlSize.setWidth( nFTSoundWidth );
723     maFT_SOUND.SetPosSizePixel( aUpperLeft, aCtrlSize );
724 
725     aUpperLeft.setX( nIndent );
726     aCtrlSize = maLB_SPEED.GetSizePixel();
727     aCtrlSize.setWidth( ::std::max( nMaxWidth - nIndent, nMinCtrlWidth ) );
728     aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight() - nOffsetY );
729     maLB_SPEED.SetPosSizePixel( aUpperLeft, aCtrlSize );
730     maLB_SPEED.SetDropDownLineCount( 3 );
731     aUpperLeft.setX( nOffsetX );
732 
733     aCtrlSize = maFT_SPEED.GetSizePixel();
734     if( bStack )
735         aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight());
736     aCtrlSize.setWidth( nFTSpeedWidth );
737     maFT_SPEED.SetPosSizePixel( aUpperLeft, aCtrlSize );
738 
739     // fixed line "Modify Transition"
740     aCtrlSize = maFL_MODIFY_TRANSITION.GetSizePixel();
741     aCtrlSize.setWidth( nMaxWidth );
742     aUpperLeft.setY( aUpperLeft.getY() - aCtrlSize.getHeight() - nOffsetY );
743     maFL_MODIFY_TRANSITION.SetPosSizePixel( aUpperLeft, aCtrlSize );
744 
745     // fixed line "Apply to selected slides"
746     aCtrlSize = maFL_APPLY_TRANSITION.GetSizePixel();
747     aCtrlSize.setWidth( nMaxWidth );
748     ::Point aUpperLeftCorner( nOffsetX, nOffsetY );
749     maFL_APPLY_TRANSITION.SetPosSizePixel( aUpperLeftCorner, aCtrlSize );
750     aUpperLeftCorner.setY( aUpperLeftCorner.getY() + aCtrlSize.getHeight() + nOffsetY );
751     aUpperLeft.setY( aUpperLeft.getY() - nOffsetY );
752 
753     // list box slide transitions
754     aCtrlSize.setWidth( nMaxWidth );
755     aCtrlSize.setHeight( aUpperLeft.getY() - aUpperLeftCorner.getY() );
756     maLB_SLIDE_TRANSITIONS.SetPosSizePixel( aUpperLeftCorner, aCtrlSize );
757 }
758 
759 void SlideTransitionPane::updateControls()
760 {
761     ::sd::slidesorter::SharedPageSelection pSelectedPages(getSelectedPages());
762     if( pSelectedPages->empty())
763     {
764         mbHasSelection = false;
765         return;
766     }
767     mbHasSelection = true;
768 
769     DBG_ASSERT( ! mbUpdatingControls, "Multiple Control Updates" );
770     mbUpdatingControls = true;
771 
772     // get model data for first page
773     SdPage * pFirstPage = pSelectedPages->front();
774     DBG_ASSERT( pFirstPage, "Invalid Page" );
775 
776     impl::TransitionEffect aEffect( *pFirstPage );
777 
778     // merge with other pages
779     ::sd::slidesorter::SlideSorterViewShell::PageSelection::const_iterator aIt(
780         pSelectedPages->begin());
781     ::sd::slidesorter::SlideSorterViewShell::PageSelection::const_iterator aEndIt(
782         pSelectedPages->end());
783 
784     // start with second page (note aIt != aEndIt, because ! aSelectedPages.empty())
785     for( ++aIt ;aIt != aEndIt; ++aIt )
786     {
787         if( *aIt )
788             aEffect.compareWith( *(*aIt) );
789     }
790 
791     // detect current slide effect
792     if( aEffect.mbEffectAmbiguous )
793         maLB_SLIDE_TRANSITIONS.SetNoSelection();
794     else
795     {
796         // ToDo: That 0 is "no transition" is documented nowhere except in the
797         // CTOR of sdpage
798         if( aEffect.mnType == 0 )
799             maLB_SLIDE_TRANSITIONS.SelectEntryPos( 0 );
800         else
801         {
802             sal_uInt16 nEntry = lcl_getTransitionEffectIndex( mpDrawDoc, aEffect );
803             if( nEntry == LISTBOX_ENTRY_NOTFOUND )
804                 maLB_SLIDE_TRANSITIONS.SetNoSelection();
805             else
806             {
807                 // first entry in list is "none", so add 1 after translation
808                 if( m_aPresetIndexes.find( nEntry ) != m_aPresetIndexes.end())
809                     maLB_SLIDE_TRANSITIONS.SelectEntryPos( m_aPresetIndexes[ nEntry ] + 1 );
810                 else
811                     maLB_SLIDE_TRANSITIONS.SetNoSelection();
812             }
813         }
814     }
815 
816     if( aEffect.mbDurationAmbiguous )
817         maLB_SPEED.SetNoSelection();
818     else
819         maLB_SPEED.SelectEntryPos(
820             (aEffect.mfDuration > 2.0 )
821             ? 0 : (aEffect.mfDuration < 2.0)
822             ? 2 : 1 );       // else FADE_SPEED_FAST
823 
824     if( aEffect.mbSoundAmbiguous )
825     {
826         maLB_SOUND.SetNoSelection();
827         maCurrentSoundFile.Erase();
828     }
829     else
830     {
831 		maCurrentSoundFile.Erase();
832 		if( aEffect.mbStopSound )
833 		{
834 			maLB_SOUND.SelectEntryPos( 1 );
835 		}
836 		else if( aEffect.mbSoundOn && aEffect.maSound.Len() > 0 )
837         {
838             tSoundListType::size_type nPos = 0;
839             if( lcl_findSoundInList( maSoundList, aEffect.maSound, nPos ))
840             {
841                 // skip first three entries
842                 maLB_SOUND.SelectEntryPos( (sal_uInt16)nPos + 3 );
843                 maCurrentSoundFile = aEffect.maSound;
844             }
845         }
846         else
847         {
848             maLB_SOUND.SelectEntryPos( 0 );
849         }
850     }
851 
852 	if( aEffect.mbLoopSoundAmbiguous )
853 	{
854 		maCB_LOOP_SOUND.SetState( STATE_DONTKNOW );
855 	}
856 	else
857 	{
858 		maCB_LOOP_SOUND.Check( aEffect.mbLoopSound );
859 	}
860 
861     if( aEffect.mbPresChangeAmbiguous )
862     {
863         maRB_ADVANCE_ON_MOUSE.Check( sal_False );
864         maRB_ADVANCE_AUTO.Check( sal_False );
865     }
866     else
867     {
868         maRB_ADVANCE_ON_MOUSE.Check( aEffect.mePresChange == PRESCHANGE_MANUAL );
869         maRB_ADVANCE_AUTO.Check( aEffect.mePresChange == PRESCHANGE_AUTO );
870         maMF_ADVANCE_AUTO_AFTER.SetValue( aEffect.mnTime );
871     }
872 
873 	SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
874 	maCB_AUTO_PREVIEW.Check( pOptions->IsPreviewTransitions() == sal_True );
875 
876     mbUpdatingControls = false;
877 
878     updateControlState();
879 }
880 
881 void SlideTransitionPane::updateControlState()
882 {
883     maLB_SLIDE_TRANSITIONS.Enable( mbHasSelection );
884     maLB_SPEED.Enable( mbHasSelection );
885     maLB_SOUND.Enable( mbHasSelection );
886     maCB_LOOP_SOUND.Enable( mbHasSelection && (maLB_SOUND.GetSelectEntryPos() > 2));
887     maRB_ADVANCE_ON_MOUSE.Enable( mbHasSelection );
888     maRB_ADVANCE_AUTO.Enable( mbHasSelection );
889     maMF_ADVANCE_AUTO_AFTER.Enable( mbHasSelection && maRB_ADVANCE_AUTO.IsChecked());
890 
891     maPB_APPLY_TO_ALL.Enable( mbHasSelection );
892     maPB_PLAY.Enable( mbHasSelection );
893 //     maPB_SLIDE_SHOW.Enable( sal_True );
894     maCB_AUTO_PREVIEW.Enable( mbHasSelection );
895 }
896 
897 void SlideTransitionPane::updateSoundList()
898 {
899     List aSoundList;
900 
901     GalleryExplorer::FillObjList( GALLERY_THEME_SOUNDS, aSoundList );
902     GalleryExplorer::FillObjList( GALLERY_THEME_USERSOUNDS, aSoundList );
903 
904     sal_uInt32 nCount = aSoundList.Count();
905     maSoundList.clear();
906     maSoundList.reserve( nCount );
907     for( sal_uInt32 i=0; i<nCount; ++i )
908     {
909         String * pEntry = reinterpret_cast< String * >( aSoundList.GetObject( i ));
910         if( pEntry )
911         {
912             // store copy of string in member list
913             maSoundList.push_back( *pEntry );
914             // delete pointer in temporary List
915             delete pEntry;
916         }
917     }
918 
919     lcl_FillSoundListBox( maSoundList, maLB_SOUND );
920 }
921 
922 void SlideTransitionPane::openSoundFileDialog()
923 {
924     if( ! maLB_SOUND.IsEnabled())
925         return;
926 
927     SdOpenSoundFileDialog aFileDialog;
928 
929 	String aFile;
930     DBG_ASSERT( maLB_SOUND.GetSelectEntryPos() == 2,
931                 "Dialog should only open when \"Other sound\" is selected" );
932     aFile = SvtPathOptions().GetGraphicPath();
933 
934 	aFileDialog.SetPath( aFile );
935 
936 	bool bValidSoundFile( false );
937 	bool bQuitLoop( false );
938 
939 	while( ! bQuitLoop &&
940 		   aFileDialog.Execute() == ERRCODE_NONE )
941 	{
942 		aFile = aFileDialog.GetPath();
943         tSoundListType::size_type nPos = 0;
944         bValidSoundFile = lcl_findSoundInList( maSoundList, aFile, nPos );
945 
946         if( bValidSoundFile )
947 		{
948 			bQuitLoop = true;
949 		}
950 		else // not in sound list
951 		{
952 			// try to insert into gallery
953 			if( GalleryExplorer::InsertURL( GALLERY_THEME_USERSOUNDS, aFile, SGA_FORMAT_SOUND ) )
954 			{
955                 updateSoundList();
956                 bValidSoundFile = lcl_findSoundInList( maSoundList, aFile, nPos );
957 				DBG_ASSERT( bValidSoundFile, "Adding sound to gallery failed" );
958 
959 				bQuitLoop = true;
960 			}
961 			else
962 			{
963 				String aStrWarning(SdResId(STR_WARNING_NOSOUNDFILE));
964 				String aStr( sal_Unicode( '%' ));
965 				aStrWarning.SearchAndReplace( aStr , aFile );
966 				WarningBox aWarningBox( NULL, WB_3DLOOK | WB_RETRY_CANCEL, aStrWarning );
967 				aWarningBox.SetModalInputMode (sal_True);
968 				bQuitLoop = (aWarningBox.Execute() != RET_RETRY);
969 
970 				bValidSoundFile = false;
971 			}
972 		}
973 
974 		if( bValidSoundFile )
975             // skip first three entries in list
976             maLB_SOUND.SelectEntryPos( (sal_uInt16)nPos + 3 );
977 	}
978 
979     if( ! bValidSoundFile )
980     {
981         if( maCurrentSoundFile.Len() > 0 )
982         {
983             tSoundListType::size_type nPos = 0;
984             if( lcl_findSoundInList( maSoundList, maCurrentSoundFile, nPos ))
985                 maLB_SOUND.SelectEntryPos( (sal_uInt16)nPos + 3 );
986 	        else
987 		        maLB_SOUND.SelectEntryPos( 0 );  // NONE
988         }
989         else
990             maLB_SOUND.SelectEntryPos( 0 );  // NONE
991     }
992 }
993 
994 impl::TransitionEffect SlideTransitionPane::getTransitionEffectFromControls() const
995 {
996     impl::TransitionEffect aResult;
997     aResult.setAllAmbiguous();
998 
999     // check first (aResult might be overwritten)
1000     if( maLB_SLIDE_TRANSITIONS.IsEnabled() &&
1001         maLB_SLIDE_TRANSITIONS.GetSelectEntryCount() > 0 )
1002     {
1003         TransitionPresetPtr pPreset = lcl_getTransitionPresetByUIName(
1004             mpDrawDoc, OUString( maLB_SLIDE_TRANSITIONS.GetSelectEntry()));
1005 
1006         if( pPreset.get())
1007         {
1008             aResult = impl::TransitionEffect( *pPreset );
1009 		    aResult.setAllAmbiguous();
1010         }
1011         else
1012         {
1013             aResult.mnType = 0;
1014         }
1015         aResult.mbEffectAmbiguous = false;
1016     }
1017 
1018     // speed
1019     if( maLB_SPEED.IsEnabled() &&
1020         maLB_SPEED.GetSelectEntryCount() > 0 )
1021     {
1022         sal_uInt16 nPos = maLB_SPEED.GetSelectEntryPos();
1023         aResult.mfDuration = (nPos == 0)
1024             ? 3.0
1025             : (nPos == 1)
1026             ? 2.0
1027             : 1.0;   // nPos == 2
1028         DBG_ASSERT( aResult.mfDuration != 1.0 || nPos == 2, "Invalid Listbox Entry" );
1029 
1030         aResult.mbDurationAmbiguous = false;
1031     }
1032 
1033     // slide-advance mode
1034     if( maRB_ADVANCE_ON_MOUSE.IsEnabled() && maRB_ADVANCE_AUTO.IsEnabled() &&
1035         (maRB_ADVANCE_ON_MOUSE.IsChecked() || maRB_ADVANCE_AUTO.IsChecked()))
1036     {
1037         if( maRB_ADVANCE_ON_MOUSE.IsChecked())
1038             aResult.mePresChange = PRESCHANGE_MANUAL;
1039         else
1040         {
1041             aResult.mePresChange = PRESCHANGE_AUTO;
1042             if( maMF_ADVANCE_AUTO_AFTER.IsEnabled())
1043             {
1044 //                 sal_uInt16 nDigits = maMF_ADVANCE_AUTO_AFTER.GetDecimalDigits();
1045                 aResult.mnTime = static_cast<long>(maMF_ADVANCE_AUTO_AFTER.GetValue());
1046                 // / static_cast< sal_uInt16 >( pow( 10.0, static_cast< double >( nDigits )));
1047                 aResult.mbTimeAmbiguous = false;
1048             }
1049         }
1050 
1051         aResult.mbPresChangeAmbiguous = false;
1052     }
1053 
1054     // sound
1055     if( maLB_SOUND.IsEnabled())
1056     {
1057 		maCurrentSoundFile.Erase();
1058 		if( maLB_SOUND.GetSelectEntryCount() > 0 )
1059         {
1060 			sal_uInt16 nPos = maLB_SOUND.GetSelectEntryPos();
1061 			aResult.mbStopSound = nPos == 1;
1062 			aResult.mbSoundOn = nPos > 1;
1063 			if( aResult.mbStopSound )
1064 			{
1065 				aResult.maSound = OUString();
1066 				aResult.mbSoundAmbiguous = false;
1067 			}
1068 			else
1069 			{
1070 				aResult.maSound = lcl_getSoundFileURL( maSoundList, maLB_SOUND );
1071 				aResult.mbSoundAmbiguous = false;
1072 				maCurrentSoundFile = aResult.maSound;
1073 			}
1074         }
1075     }
1076 
1077 	// sound loop
1078 	if( maCB_LOOP_SOUND.IsEnabled() )
1079 	{
1080 		aResult.mbLoopSound = maCB_LOOP_SOUND.IsChecked();
1081 		aResult.mbLoopSoundAmbiguous = false;
1082 	}
1083 
1084     return aResult;
1085 }
1086 
1087 void SlideTransitionPane::applyToSelectedPages()
1088 {
1089     if( ! mbUpdatingControls )
1090     {
1091         ::sd::slidesorter::SharedPageSelection pSelectedPages( getSelectedPages());
1092         if( ! pSelectedPages->empty())
1093         {
1094 			lcl_CreateUndoForPages( pSelectedPages, mrBase );
1095             lcl_ApplyToPages( pSelectedPages, getTransitionEffectFromControls() );
1096 			mrBase.GetDocShell()->SetModified();
1097         }
1098         if( maCB_AUTO_PREVIEW.IsEnabled() &&
1099             maCB_AUTO_PREVIEW.IsChecked())
1100         {
1101             playCurrentEffect();
1102         }
1103     }
1104 }
1105 
1106 void SlideTransitionPane::playCurrentEffect()
1107 {
1108 	if( mxView.is() )
1109 	{
1110 
1111 		Reference< ::com::sun::star::animations::XAnimationNode > xNode;
1112 		SlideShow::StartPreview( mrBase, mxView->getCurrentPage(), xNode );
1113 	}
1114 }
1115 
1116 void SlideTransitionPane::addListener()
1117 {
1118 	Link aLink( LINK(this,SlideTransitionPane,EventMultiplexerListener) );
1119     mrBase.GetEventMultiplexer()->AddEventListener (
1120         aLink,
1121         tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION
1122         | tools::EventMultiplexerEvent::EID_SLIDE_SORTER_SELECTION
1123         | tools::EventMultiplexerEvent::EID_CURRENT_PAGE
1124         | tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
1125         | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
1126         | tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED);
1127 }
1128 
1129 void SlideTransitionPane::removeListener()
1130 {
1131 	Link aLink( LINK(this,SlideTransitionPane,EventMultiplexerListener) );
1132     mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
1133 }
1134 
1135 IMPL_LINK(SlideTransitionPane,EventMultiplexerListener,
1136     tools::EventMultiplexerEvent*,pEvent)
1137 {
1138     switch (pEvent->meEventId)
1139     {
1140         case tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION:
1141             onSelectionChanged();
1142             break;
1143 
1144         case tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
1145         case tools::EventMultiplexerEvent::EID_SLIDE_SORTER_SELECTION:
1146             onChangeCurrentPage();
1147             break;
1148 
1149         case tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
1150             mxView = Reference<drawing::XDrawView>();
1151             onSelectionChanged();
1152             onChangeCurrentPage();
1153             break;
1154 
1155         case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
1156             mbIsMainViewChangePending = true;
1157             break;
1158 
1159         case tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED:
1160             if (mbIsMainViewChangePending)
1161             {
1162                 mbIsMainViewChangePending = false;
1163 
1164                 // At this moment the controller may not yet been set at
1165                 // model or ViewShellBase.  Take it from the view shell
1166                 // passed with the event.
1167                 if (mrBase.GetMainViewShell() != NULL)
1168                 {
1169                     mxView = Reference<drawing::XDrawView>::query(mrBase.GetController());
1170                     onSelectionChanged();
1171                     onChangeCurrentPage();
1172                 }
1173             }
1174             break;
1175 
1176         default:
1177             break;
1178     }
1179     return 0;
1180 }
1181 
1182 IMPL_LINK( SlideTransitionPane, ApplyToAllButtonClicked, void *, EMPTYARG )
1183 {
1184     DBG_ASSERT( mpDrawDoc, "Invalid Draw Document!" );
1185     if( !mpDrawDoc )
1186         return 0;
1187 
1188     ::sd::slidesorter::SharedPageSelection pPages (
1189         new ::sd::slidesorter::SlideSorterViewShell::PageSelection());
1190 
1191     sal_uInt16 nPageCount = mpDrawDoc->GetSdPageCount( PK_STANDARD );
1192     pPages->reserve( nPageCount );
1193     for( sal_uInt16 i=0; i<nPageCount; ++i )
1194     {
1195         SdPage * pPage = mpDrawDoc->GetSdPage( i, PK_STANDARD );
1196         if( pPage )
1197             pPages->push_back( pPage );
1198     }
1199 
1200     if( ! pPages->empty())
1201 	{
1202 		lcl_CreateUndoForPages( pPages, mrBase );
1203         lcl_ApplyToPages( pPages, getTransitionEffectFromControls() );
1204 	}
1205 
1206     return 0;
1207 }
1208 
1209 
1210 IMPL_LINK( SlideTransitionPane, PlayButtonClicked, void *, EMPTYARG )
1211 {
1212     playCurrentEffect();
1213     return 0;
1214 }
1215 
1216 IMPL_LINK( SlideTransitionPane, SlideShowButtonClicked, void *, EMPTYARG )
1217 {
1218 	mrBase.StartPresentation();
1219     return 0;
1220 }
1221 
1222 IMPL_LINK( SlideTransitionPane, TransitionSelected, void *, EMPTYARG )
1223 {
1224     applyToSelectedPages();
1225     return 0;
1226 }
1227 
1228 IMPL_LINK( SlideTransitionPane, AdvanceSlideRadioButtonToggled, void *, EMPTYARG )
1229 {
1230     updateControlState();
1231     applyToSelectedPages();
1232     return 0;
1233 }
1234 
1235 IMPL_LINK( SlideTransitionPane, AdvanceTimeModified, void *, EMPTYARG )
1236 {
1237     applyToSelectedPages();
1238     return 0;
1239 }
1240 
1241 IMPL_LINK( SlideTransitionPane, SpeedListBoxSelected, void *, EMPTYARG )
1242 {
1243     applyToSelectedPages();
1244     return 0;
1245 }
1246 
1247 IMPL_LINK( SlideTransitionPane, SoundListBoxSelected, void *, EMPTYARG )
1248 {
1249     if( maLB_SOUND.GetSelectEntryCount() )
1250     {
1251         sal_uInt16 nPos = maLB_SOUND.GetSelectEntryPos();
1252         if( nPos == 2 )
1253         {
1254             // other sound ...
1255             openSoundFileDialog();
1256         }
1257     }
1258     updateControlState();
1259     applyToSelectedPages();
1260     return 0;
1261 }
1262 
1263 IMPL_LINK( SlideTransitionPane, LoopSoundBoxChecked, void *, EMPTYARG )
1264 {
1265     applyToSelectedPages();
1266     return 0;
1267 }
1268 
1269 IMPL_LINK( SlideTransitionPane, AutoPreviewClicked, void *, EMPTYARG )
1270 {
1271 	SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
1272 	pOptions->SetPreviewTransitions( maCB_AUTO_PREVIEW.IsChecked() ? sal_True : sal_False );
1273     return 0;
1274 }
1275 
1276 IMPL_LINK( SlideTransitionPane, LateInitCallback, Timer*, EMPTYARG )
1277 {
1278 	const TransitionPresetList& rPresetList = TransitionPreset::getTransitionPresetList();
1279 	TransitionPresetList::const_iterator aIter( rPresetList.begin() );
1280 	const TransitionPresetList::const_iterator aEnd( rPresetList.end() );
1281     sal_uInt16 nIndex = 0;
1282     ::std::size_t nUIIndex = 0;
1283 	while( aIter != aEnd )
1284 	{
1285 		TransitionPresetPtr pPreset = (*aIter++);
1286 		const OUString aUIName( pPreset->getUIName() );
1287  		if( aUIName.getLength() )
1288         {
1289             maLB_SLIDE_TRANSITIONS.InsertEntry( aUIName );
1290             m_aPresetIndexes[ nIndex ] = (sal_uInt16)nUIIndex;
1291             ++nUIIndex;
1292         }
1293         ++nIndex;
1294 	}
1295 
1296     updateSoundList();
1297     updateControls();
1298 
1299     return 0;
1300 }
1301 
1302 ::Window * createSlideTransitionPanel( ::Window* pParent, ViewShellBase& rBase )
1303 {
1304 	DialogListBox* pWindow = 0;
1305 
1306 	DrawDocShell* pDocSh = rBase.GetDocShell();
1307     if( pDocSh )
1308     {
1309         pWindow = new DialogListBox( pParent, WB_CLIPCHILDREN|WB_TABSTOP|WB_AUTOHSCROLL );
1310 
1311 		Size aMinSize( pWindow->LogicToPixel( Size( 72, 216 ), MAP_APPFONT ) );
1312 		::Window* pPaneWindow = new SlideTransitionPane( pWindow, rBase, aMinSize, pDocSh->GetDoc() );
1313 		pWindow->SetChildWindow( pPaneWindow, aMinSize );
1314 		pWindow->SetText( pPaneWindow->GetText() );
1315     }
1316 
1317 	return pWindow;
1318 }
1319 
1320 
1321 } //  namespace sd
1322