Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <com/sun/star/animations/XAnimationNode.hpp>
21 :
22 : #include "SlideTransitionPane.hxx"
23 : #include "CustomAnimation.hrc"
24 : #include "createslidetransitionpanel.hxx"
25 :
26 : #include "TransitionPreset.hxx"
27 : #include "sdresid.hxx"
28 : #include "ViewShellBase.hxx"
29 : #include "DrawDocShell.hxx"
30 : #include "SlideSorterViewShell.hxx"
31 : #include "drawdoc.hxx"
32 : #include "filedlg.hxx"
33 : #include "strings.hrc"
34 : #include "DrawController.hxx"
35 : #include <com/sun/star/beans/XPropertySet.hpp>
36 :
37 : #include <svtools/controldims.hrc>
38 : #include <svx/gallery.hxx>
39 : #include <unotools/pathoptions.hxx>
40 : #include <vcl/msgbox.hxx>
41 : #include <tools/urlobj.hxx>
42 : #include "DrawViewShell.hxx"
43 : #include "slideshow.hxx"
44 : #include "drawview.hxx"
45 : #include "sdundogr.hxx"
46 : #include "undoanim.hxx"
47 : #include "optsitem.hxx"
48 : #include "sddll.hxx"
49 : #include "framework/FrameworkHelper.hxx"
50 :
51 : #include <sfx2/sidebar/Theme.hxx>
52 :
53 : #include <algorithm>
54 :
55 : using namespace ::com::sun::star;
56 :
57 : using ::com::sun::star::uno::Reference;
58 : using ::com::sun::star::uno::Sequence;
59 : using ::com::sun::star::uno::RuntimeException;
60 :
61 : using ::sd::framework::FrameworkHelper;
62 :
63 : // ::sd::impl::TransitionEffect
64 : namespace sd
65 : {
66 : namespace impl
67 : {
68 0 : struct TransitionEffect
69 : {
70 0 : TransitionEffect() :
71 : mnType( 0 ),
72 : mnSubType( 0 ),
73 : mbDirection( true ),
74 0 : mnFadeColor( 0 )
75 : {
76 0 : init();
77 0 : }
78 0 : explicit TransitionEffect( const ::sd::TransitionPreset & rPreset ) :
79 0 : mnType( rPreset.getTransition()),
80 0 : mnSubType( rPreset.getSubtype()),
81 0 : mbDirection( rPreset.getDirection()),
82 0 : mnFadeColor( rPreset.getFadeColor())
83 : {
84 0 : init();
85 0 : }
86 0 : explicit TransitionEffect( const SdPage & rPage ) :
87 0 : mnType( rPage.getTransitionType() ),
88 0 : mnSubType( rPage.getTransitionSubtype() ),
89 0 : mbDirection( rPage.getTransitionDirection() ),
90 0 : mnFadeColor( rPage.getTransitionFadeColor() )
91 : {
92 0 : init();
93 :
94 0 : mfDuration = rPage.getTransitionDuration();
95 0 : mfTime = rPage.GetTime();
96 0 : mePresChange = rPage.GetPresChange();
97 0 : mbSoundOn = rPage.IsSoundOn();
98 0 : maSound = rPage.GetSoundFile();
99 0 : mbLoopSound = rPage.IsLoopSound();
100 0 : mbStopSound = rPage.IsStopSound();
101 0 : }
102 :
103 0 : void init()
104 : {
105 0 : mfDuration = 2.0;
106 0 : mfTime = 0.0;
107 0 : mePresChange = PRESCHANGE_MANUAL;
108 0 : mbSoundOn = false;
109 0 : mbLoopSound = false;
110 0 : mbStopSound = false;
111 :
112 0 : mbEffectAmbiguous = false;
113 0 : mbDurationAmbiguous = false;
114 0 : mbTimeAmbiguous = false;
115 0 : mbPresChangeAmbiguous = false;
116 0 : mbSoundAmbiguous = false;
117 0 : mbLoopSoundAmbiguous = false;
118 0 : }
119 :
120 0 : void setAllAmbiguous()
121 : {
122 0 : mbEffectAmbiguous = true;
123 0 : mbDurationAmbiguous = true;
124 0 : mbTimeAmbiguous = true;
125 0 : mbPresChangeAmbiguous = true;
126 0 : mbSoundAmbiguous = true;
127 0 : mbLoopSoundAmbiguous = true;
128 0 : }
129 :
130 0 : bool operator == ( const ::sd::TransitionPreset & rPreset ) const
131 : {
132 : return
133 0 : (mnType == rPreset.getTransition()) &&
134 0 : (mnSubType == rPreset.getSubtype()) &&
135 0 : (mbDirection == rPreset.getDirection()) &&
136 0 : (mnFadeColor == rPreset.getFadeColor());
137 : }
138 :
139 0 : void applyTo( SdPage & rOutPage ) const
140 : {
141 0 : if( ! mbEffectAmbiguous )
142 : {
143 0 : rOutPage.setTransitionType( mnType );
144 0 : rOutPage.setTransitionSubtype( mnSubType );
145 0 : rOutPage.setTransitionDirection( mbDirection );
146 0 : rOutPage.setTransitionFadeColor( mnFadeColor );
147 : }
148 :
149 0 : if( ! mbDurationAmbiguous )
150 0 : rOutPage.setTransitionDuration( mfDuration );
151 0 : if( ! mbTimeAmbiguous )
152 0 : rOutPage.SetTime( mfTime );
153 0 : if( ! mbPresChangeAmbiguous )
154 0 : rOutPage.SetPresChange( mePresChange );
155 0 : if( ! mbSoundAmbiguous )
156 : {
157 0 : if( mbStopSound )
158 : {
159 0 : rOutPage.SetStopSound( true );
160 0 : rOutPage.SetSound( false );
161 : }
162 : else
163 : {
164 0 : rOutPage.SetStopSound( false );
165 0 : rOutPage.SetSound( mbSoundOn );
166 0 : rOutPage.SetSoundFile( maSound );
167 : }
168 : }
169 0 : if( ! mbLoopSoundAmbiguous )
170 0 : rOutPage.SetLoopSound( mbLoopSound );
171 0 : }
172 :
173 0 : void compareWith( const SdPage & rPage )
174 : {
175 0 : TransitionEffect aOtherEffect( rPage );
176 0 : mbEffectAmbiguous = mbEffectAmbiguous || aOtherEffect.mbEffectAmbiguous
177 0 : || (mnType != aOtherEffect.mnType)
178 0 : || (mnSubType != aOtherEffect.mnSubType)
179 0 : || (mbDirection != aOtherEffect.mbDirection)
180 0 : || (mnFadeColor != aOtherEffect.mnFadeColor);
181 :
182 0 : mbDurationAmbiguous = mbDurationAmbiguous || aOtherEffect.mbDurationAmbiguous || mfDuration != aOtherEffect.mfDuration;
183 0 : mbTimeAmbiguous = mbTimeAmbiguous || aOtherEffect.mbTimeAmbiguous || mfTime != aOtherEffect.mfTime;
184 0 : mbPresChangeAmbiguous = mbPresChangeAmbiguous || aOtherEffect.mbPresChangeAmbiguous || mePresChange != aOtherEffect.mePresChange;
185 0 : mbSoundAmbiguous = mbSoundAmbiguous || aOtherEffect.mbSoundAmbiguous || mbSoundOn != aOtherEffect.mbSoundOn;
186 : #if 0
187 : // Weird leftover isolated expression with no effect, introduced in 2007 in
188 : // CWS impress122. Ifdeffed out to avoid compiler warning, kept here in case
189 : // somebody who understands this code notices and understands what the
190 : // "right" thing to do might be.
191 : (!mbStopSound && !aOtherEffect.mbStopSound && maSound != aOtherEffect.maSound) || (mbStopSound != aOtherEffect.mbStopSound);
192 : #endif
193 0 : mbLoopSoundAmbiguous = mbLoopSoundAmbiguous || aOtherEffect.mbLoopSoundAmbiguous || mbLoopSound != aOtherEffect.mbLoopSound;
194 0 : }
195 :
196 : // effect
197 : sal_Int16 mnType;
198 : sal_Int16 mnSubType;
199 : bool mbDirection;
200 : sal_Int32 mnFadeColor;
201 :
202 : // other settings
203 : double mfDuration;
204 : double mfTime;
205 : PresChange mePresChange;
206 : bool mbSoundOn;
207 : OUString maSound;
208 : bool mbLoopSound;
209 : bool mbStopSound;
210 :
211 : bool mbEffectAmbiguous;
212 : bool mbDurationAmbiguous;
213 : bool mbTimeAmbiguous;
214 : bool mbPresChangeAmbiguous;
215 : bool mbSoundAmbiguous;
216 : bool mbLoopSoundAmbiguous;
217 : };
218 :
219 : } // namespace impl
220 : } // namespace sd
221 :
222 : // Local Helper Functions
223 : namespace
224 : {
225 :
226 0 : void lcl_ApplyToPages(
227 : const ::sd::slidesorter::SharedPageSelection& rpPages,
228 : const ::sd::impl::TransitionEffect & rEffect )
229 : {
230 0 : ::std::vector< SdPage * >::const_iterator aIt( rpPages->begin());
231 0 : const ::std::vector< SdPage * >::const_iterator aEndIt( rpPages->end());
232 0 : for( ; aIt != aEndIt; ++aIt )
233 : {
234 0 : rEffect.applyTo( *(*aIt) );
235 : }
236 0 : }
237 :
238 0 : void lcl_CreateUndoForPages(
239 : const ::sd::slidesorter::SharedPageSelection& rpPages,
240 : ::sd::ViewShellBase& rBase )
241 : {
242 0 : ::sd::DrawDocShell* pDocSh = rBase.GetDocShell();
243 0 : if (!pDocSh)
244 0 : return;
245 0 : ::svl::IUndoManager* pManager = pDocSh->GetUndoManager();
246 0 : if (!pManager)
247 0 : return;
248 0 : SdDrawDocument* pDoc = pDocSh->GetDoc();
249 0 : if (!pDoc)
250 0 : return;
251 :
252 0 : OUString aComment( SdResId(STR_UNDO_SLIDE_PARAMS) );
253 0 : pManager->EnterListAction(aComment, aComment);
254 0 : SdUndoGroup* pUndoGroup = new SdUndoGroup( pDoc );
255 0 : pUndoGroup->SetComment( aComment );
256 :
257 0 : ::std::vector< SdPage * >::const_iterator aIt( rpPages->begin());
258 0 : const ::std::vector< SdPage * >::const_iterator aEndIt( rpPages->end());
259 0 : for( ; aIt != aEndIt; ++aIt )
260 : {
261 0 : pUndoGroup->AddAction( new sd::UndoTransition( pDoc, (*aIt) ) );
262 : }
263 :
264 0 : pManager->AddUndoAction( pUndoGroup );
265 0 : pManager->LeaveListAction();
266 : }
267 :
268 0 : sal_Int32 lcl_getTransitionEffectIndex(
269 : SdDrawDocument * pDoc,
270 : const ::sd::impl::TransitionEffect & rTransition )
271 : {
272 : // first entry: "<none>"
273 0 : sal_Int32 nResultIndex = LISTBOX_ENTRY_NOTFOUND;
274 :
275 0 : if( pDoc )
276 : {
277 0 : sal_Int32 nCurrentIndex = 0;
278 0 : const ::sd::TransitionPresetList & rPresetList = ::sd::TransitionPreset::getTransitionPresetList();
279 0 : ::sd::TransitionPresetList::const_iterator aIt( rPresetList.begin());
280 0 : const ::sd::TransitionPresetList::const_iterator aEndIt( rPresetList.end());
281 0 : for( ; aIt != aEndIt; ++aIt, ++nCurrentIndex )
282 : {
283 0 : if( rTransition.operator==( *(*aIt) ))
284 : {
285 0 : nResultIndex = nCurrentIndex;
286 0 : break;
287 : }
288 : }
289 : }
290 :
291 0 : return nResultIndex;
292 : }
293 :
294 0 : ::sd::TransitionPresetPtr lcl_getTransitionPresetByUIName(
295 : SdDrawDocument * pDoc,
296 : const OUString & rUIName )
297 : {
298 0 : ::sd::TransitionPresetPtr pResult;
299 0 : if( pDoc )
300 : {
301 0 : const ::sd::TransitionPresetList& rPresetList = ::sd::TransitionPreset::getTransitionPresetList();
302 0 : ::sd::TransitionPresetList::const_iterator aIter( rPresetList.begin() );
303 0 : const ::sd::TransitionPresetList::const_iterator aEnd( rPresetList.end() );
304 0 : for( ; aIter != aEnd; ++aIter )
305 : {
306 0 : if( (*aIter)->getUIName().equals( rUIName ))
307 : {
308 0 : pResult = *aIter;
309 0 : break;
310 : }
311 : }
312 : }
313 :
314 0 : return pResult;
315 : }
316 :
317 0 : struct lcl_EqualsSoundFileName : public ::std::unary_function< OUString, bool >
318 : {
319 0 : explicit lcl_EqualsSoundFileName( const OUString & rStr ) :
320 0 : maStr( rStr )
321 0 : {}
322 :
323 0 : bool operator() ( const OUString & rStr ) const
324 : {
325 : // note: formerly this was a case insensitive search for all
326 : // platforms. It seems more sensible to do this platform-dependent
327 : #if defined( WNT )
328 : return maStr.equalsIgnoreAsciiCase( rStr );
329 : #else
330 0 : return maStr == rStr;
331 : #endif
332 : }
333 :
334 : private:
335 : OUString maStr;
336 : };
337 :
338 : // returns -1 if no object was found
339 0 : bool lcl_findSoundInList( const ::std::vector< OUString > & rSoundList,
340 : const OUString & rFileName,
341 : ::std::vector< OUString >::size_type & rOutPosition )
342 : {
343 : ::std::vector< OUString >::const_iterator aIt =
344 : ::std::find_if( rSoundList.begin(), rSoundList.end(),
345 0 : lcl_EqualsSoundFileName( rFileName ));
346 0 : if( aIt != rSoundList.end())
347 : {
348 0 : rOutPosition = ::std::distance( rSoundList.begin(), aIt );
349 0 : return true;
350 : }
351 :
352 0 : return false;
353 : }
354 :
355 0 : OUString lcl_getSoundFileURL(
356 : const ::std::vector< OUString > & rSoundList,
357 : const ListBox* rListBox )
358 : {
359 0 : if( rListBox->GetSelectEntryCount() > 0 )
360 : {
361 0 : sal_Int32 nPos = rListBox->GetSelectEntryPos();
362 : // the first three entries are no actual sounds
363 0 : if( nPos >= 3 )
364 : {
365 : DBG_ASSERT( (sal_uInt32)(rListBox->GetEntryCount() - 3) == rSoundList.size(),
366 : "Sound list-box is not synchronized to sound list" );
367 0 : nPos -= 3;
368 0 : if( rSoundList.size() > static_cast<size_t>(nPos) )
369 0 : return rSoundList[ nPos ];
370 : }
371 : }
372 :
373 0 : return OUString();
374 : }
375 :
376 0 : struct lcl_AppendSoundToListBox : public ::std::unary_function< OUString, void >
377 : {
378 0 : lcl_AppendSoundToListBox( ListBox* rListBox ) :
379 0 : mrListBox( rListBox )
380 0 : {}
381 :
382 0 : void operator() ( const OUString & rString ) const
383 : {
384 0 : INetURLObject aURL( rString );
385 0 : mrListBox->InsertEntry( aURL.GetBase(), LISTBOX_APPEND );
386 0 : }
387 :
388 : private:
389 : VclPtr<ListBox> mrListBox;
390 : };
391 :
392 0 : void lcl_FillSoundListBox(
393 : const ::std::vector< OUString > & rSoundList,
394 : ListBox* rOutListBox )
395 : {
396 0 : sal_Int32 nCount = rOutListBox->GetEntryCount();
397 :
398 : // keep first three entries
399 0 : for( sal_Int32 i=nCount - 1; i>=3; --i )
400 0 : rOutListBox->RemoveEntry( i );
401 :
402 : ::std::for_each( rSoundList.begin(), rSoundList.end(),
403 0 : lcl_AppendSoundToListBox( rOutListBox ));
404 0 : }
405 :
406 : } // anonymous namespace
407 :
408 : namespace sd
409 : {
410 :
411 : // SlideTransitionPane
412 0 : SlideTransitionPane::SlideTransitionPane(
413 : Window * pParent,
414 : ViewShellBase & rBase,
415 : const Size& rMinSize,
416 : SdDrawDocument* pDoc,
417 : const css::uno::Reference<css::frame::XFrame>& rxFrame ) :
418 : PanelLayout( pParent, "SlideTransitionsPanel", "modules/simpress/ui/slidetransitionspanel.ui", rxFrame ),
419 :
420 : mrBase( rBase ),
421 : mpDrawDoc( pDoc ),
422 : maMinSize( rMinSize ),
423 : mbHasSelection( false ),
424 : mbUpdatingControls( false ),
425 : mbIsMainViewChangePending( false ),
426 0 : maLateInitTimer()
427 : {
428 0 : get(mpLB_SLIDE_TRANSITIONS, "transitions_list");
429 0 : get(mpFT_SPEED, "speed_label");
430 0 : get(mpLB_SPEED, "speed_list");
431 0 : get(mpFT_SOUND, "sound_label");
432 0 : get(mpLB_SOUND, "sound_list");
433 0 : get(mpCB_LOOP_SOUND, "loop_sound" );
434 0 : get(mpRB_ADVANCE_ON_MOUSE, "rb_mouse_click");
435 0 : get(mpRB_ADVANCE_AUTO, "rb_auto_after");
436 0 : get(mpMF_ADVANCE_AUTO_AFTER, "auto_after_value");
437 0 : get(mpPB_APPLY_TO_ALL, "apply_to_all");
438 0 : get(mpPB_PLAY, "play");
439 0 : get(mpCB_AUTO_PREVIEW, "auto_preview");
440 :
441 0 : mpLB_SLIDE_TRANSITIONS->set_width_request(mpLB_SLIDE_TRANSITIONS->approximate_char_width() * 16);
442 0 : mpLB_SLIDE_TRANSITIONS->SetDropDownLineCount(4);
443 :
444 0 : if( pDoc )
445 0 : mxModel.set( pDoc->getUnoModel(), uno::UNO_QUERY );
446 : // TODO: get correct view
447 0 : if( mxModel.is())
448 0 : mxView.set( mxModel->getCurrentController(), uno::UNO_QUERY );
449 :
450 : // fill list box of slide transitions
451 0 : mpLB_SLIDE_TRANSITIONS->InsertEntry( SD_RESSTR( STR_SLIDETRANSITION_NONE ) );
452 :
453 : // set defaults
454 0 : mpCB_AUTO_PREVIEW->Check(); // automatic preview on
455 :
456 : // update control states before adding handlers
457 0 : updateControls();
458 :
459 : // set handlers
460 0 : mpPB_APPLY_TO_ALL->SetClickHdl( LINK( this, SlideTransitionPane, ApplyToAllButtonClicked ));
461 0 : mpPB_PLAY->SetClickHdl( LINK( this, SlideTransitionPane, PlayButtonClicked ));
462 :
463 0 : mpLB_SLIDE_TRANSITIONS->SetSelectHdl( LINK( this, SlideTransitionPane, TransitionSelected ));
464 :
465 0 : mpLB_SPEED->SetSelectHdl( LINK( this, SlideTransitionPane, SpeedListBoxSelected ));
466 0 : mpLB_SOUND->SetSelectHdl( LINK( this, SlideTransitionPane, SoundListBoxSelected ));
467 0 : mpCB_LOOP_SOUND->SetClickHdl( LINK( this, SlideTransitionPane, LoopSoundBoxChecked ));
468 :
469 0 : mpRB_ADVANCE_ON_MOUSE->SetToggleHdl( LINK( this, SlideTransitionPane, AdvanceSlideRadioButtonToggled ));
470 0 : mpRB_ADVANCE_AUTO->SetToggleHdl( LINK( this, SlideTransitionPane, AdvanceSlideRadioButtonToggled ));
471 0 : mpMF_ADVANCE_AUTO_AFTER->SetModifyHdl( LINK( this, SlideTransitionPane, AdvanceTimeModified ));
472 0 : mpCB_AUTO_PREVIEW->SetClickHdl( LINK( this, SlideTransitionPane, AutoPreviewClicked ));
473 0 : addListener();
474 :
475 0 : maLateInitTimer.SetTimeout(200);
476 0 : maLateInitTimer.SetTimeoutHdl(LINK(this, SlideTransitionPane, LateInitCallback));
477 0 : maLateInitTimer.Start();
478 :
479 0 : UpdateLook();
480 0 : }
481 :
482 0 : SlideTransitionPane::~SlideTransitionPane()
483 : {
484 0 : disposeOnce();
485 0 : }
486 :
487 0 : void SlideTransitionPane::dispose()
488 : {
489 0 : maLateInitTimer.Stop();
490 0 : removeListener();
491 0 : mpLB_SLIDE_TRANSITIONS.clear();
492 0 : mpFT_SPEED.clear();
493 0 : mpLB_SPEED.clear();
494 0 : mpFT_SOUND.clear();
495 0 : mpLB_SOUND.clear();
496 0 : mpCB_LOOP_SOUND.clear();
497 0 : mpRB_ADVANCE_ON_MOUSE.clear();
498 0 : mpRB_ADVANCE_AUTO.clear();
499 0 : mpMF_ADVANCE_AUTO_AFTER.clear();
500 0 : mpPB_APPLY_TO_ALL.clear();
501 0 : mpPB_PLAY.clear();
502 0 : mpCB_AUTO_PREVIEW.clear();
503 0 : PanelLayout::dispose();
504 0 : }
505 :
506 0 : void SlideTransitionPane::DataChanged (const DataChangedEvent& rEvent)
507 : {
508 : (void)rEvent;
509 0 : UpdateLook();
510 0 : }
511 :
512 0 : void SlideTransitionPane::UpdateLook()
513 : {
514 0 : SetBackground(::sfx2::sidebar::Theme::GetWallpaper(::sfx2::sidebar::Theme::Paint_PanelBackground));
515 0 : mpFT_SPEED->SetBackground(Wallpaper());
516 0 : mpFT_SOUND->SetBackground(Wallpaper());
517 0 : }
518 :
519 0 : void SlideTransitionPane::onSelectionChanged()
520 : {
521 0 : updateControls();
522 0 : }
523 :
524 0 : void SlideTransitionPane::onChangeCurrentPage()
525 : {
526 0 : updateControls();
527 0 : }
528 :
529 0 : ::sd::slidesorter::SharedPageSelection SlideTransitionPane::getSelectedPages() const
530 : {
531 : ::sd::slidesorter::SlideSorterViewShell * pSlideSorterViewShell
532 0 : = ::sd::slidesorter::SlideSorterViewShell::GetSlideSorter(mrBase);
533 0 : ::boost::shared_ptr<sd::slidesorter::SlideSorterViewShell::PageSelection> pSelection;
534 :
535 0 : if( pSlideSorterViewShell )
536 : {
537 0 : pSelection = pSlideSorterViewShell->GetPageSelection();
538 : }
539 : else
540 : {
541 0 : pSelection.reset(new sd::slidesorter::SlideSorterViewShell::PageSelection());
542 0 : if( mxView.is() )
543 : {
544 0 : SdPage* pPage = SdPage::getImplementation( mxView->getCurrentPage() );
545 0 : if( pPage )
546 0 : pSelection->push_back(pPage);
547 : }
548 : }
549 :
550 0 : return pSelection;
551 : }
552 :
553 0 : void SlideTransitionPane::updateControls()
554 : {
555 0 : ::sd::slidesorter::SharedPageSelection pSelectedPages(getSelectedPages());
556 0 : if( pSelectedPages->empty())
557 : {
558 0 : mbHasSelection = false;
559 0 : return;
560 : }
561 0 : mbHasSelection = true;
562 :
563 : DBG_ASSERT( ! mbUpdatingControls, "Multiple Control Updates" );
564 0 : mbUpdatingControls = true;
565 :
566 : // get model data for first page
567 0 : SdPage * pFirstPage = pSelectedPages->front();
568 : DBG_ASSERT( pFirstPage, "Invalid Page" );
569 :
570 0 : impl::TransitionEffect aEffect( *pFirstPage );
571 :
572 : // merge with other pages
573 : ::sd::slidesorter::SlideSorterViewShell::PageSelection::const_iterator aIt(
574 0 : pSelectedPages->begin());
575 : ::sd::slidesorter::SlideSorterViewShell::PageSelection::const_iterator aEndIt(
576 0 : pSelectedPages->end());
577 :
578 : // start with second page (note aIt != aEndIt, because ! aSelectedPages.empty())
579 0 : for( ++aIt ;aIt != aEndIt; ++aIt )
580 : {
581 0 : if( *aIt )
582 0 : aEffect.compareWith( *(*aIt) );
583 : }
584 :
585 : // detect current slide effect
586 0 : if( aEffect.mbEffectAmbiguous )
587 0 : mpLB_SLIDE_TRANSITIONS->SetNoSelection();
588 : else
589 : {
590 : // ToDo: That 0 is "no transition" is documented nowhere except in the
591 : // CTOR of sdpage
592 0 : if( aEffect.mnType == 0 )
593 0 : mpLB_SLIDE_TRANSITIONS->SelectEntryPos( 0 );
594 : else
595 : {
596 0 : sal_Int32 nEntry = lcl_getTransitionEffectIndex( mpDrawDoc, aEffect );
597 0 : if( nEntry == LISTBOX_ENTRY_NOTFOUND )
598 0 : mpLB_SLIDE_TRANSITIONS->SetNoSelection();
599 : else
600 : {
601 : // first entry in list is "none", so add 1 after translation
602 0 : if( m_aPresetIndexes.find( nEntry ) != m_aPresetIndexes.end())
603 0 : mpLB_SLIDE_TRANSITIONS->SelectEntryPos( m_aPresetIndexes[ nEntry ] + 1 );
604 : else
605 0 : mpLB_SLIDE_TRANSITIONS->SetNoSelection();
606 : }
607 : }
608 : }
609 :
610 0 : if( aEffect.mbDurationAmbiguous )
611 0 : mpLB_SPEED->SetNoSelection();
612 : else
613 : mpLB_SPEED->SelectEntryPos(
614 0 : (aEffect.mfDuration > 2.0 )
615 0 : ? 0 : (aEffect.mfDuration < 2.0)
616 0 : ? 2 : 1 ); // else FADE_SPEED_FAST
617 :
618 0 : if( aEffect.mbSoundAmbiguous )
619 : {
620 0 : mpLB_SOUND->SetNoSelection();
621 0 : maCurrentSoundFile.clear();
622 : }
623 : else
624 : {
625 0 : maCurrentSoundFile.clear();
626 0 : if( aEffect.mbStopSound )
627 : {
628 0 : mpLB_SOUND->SelectEntryPos( 1 );
629 : }
630 0 : else if( aEffect.mbSoundOn && !aEffect.maSound.isEmpty() )
631 : {
632 0 : tSoundListType::size_type nPos = 0;
633 0 : if( lcl_findSoundInList( maSoundList, aEffect.maSound, nPos ))
634 : {
635 : // skip first three entries
636 0 : mpLB_SOUND->SelectEntryPos( nPos + 3 );
637 0 : maCurrentSoundFile = aEffect.maSound;
638 : }
639 : }
640 : else
641 : {
642 0 : mpLB_SOUND->SelectEntryPos( 0 );
643 : }
644 : }
645 :
646 0 : if( aEffect.mbLoopSoundAmbiguous )
647 : {
648 0 : mpCB_LOOP_SOUND->SetState( TRISTATE_INDET );
649 : }
650 : else
651 : {
652 0 : mpCB_LOOP_SOUND->Check( aEffect.mbLoopSound );
653 : }
654 :
655 0 : if( aEffect.mbPresChangeAmbiguous )
656 : {
657 0 : mpRB_ADVANCE_ON_MOUSE->Check( false );
658 0 : mpRB_ADVANCE_AUTO->Check( false );
659 : }
660 : else
661 : {
662 0 : mpRB_ADVANCE_ON_MOUSE->Check( aEffect.mePresChange == PRESCHANGE_MANUAL );
663 0 : mpRB_ADVANCE_AUTO->Check( aEffect.mePresChange == PRESCHANGE_AUTO );
664 0 : mpMF_ADVANCE_AUTO_AFTER->SetValue( aEffect.mfTime * 100.0);
665 : }
666 :
667 0 : SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
668 0 : mpCB_AUTO_PREVIEW->Check( pOptions->IsPreviewTransitions() );
669 :
670 0 : mbUpdatingControls = false;
671 :
672 0 : updateControlState();
673 : }
674 :
675 0 : void SlideTransitionPane::updateControlState()
676 : {
677 0 : mpLB_SLIDE_TRANSITIONS->Enable( mbHasSelection );
678 0 : mpLB_SPEED->Enable( mbHasSelection );
679 0 : mpLB_SOUND->Enable( mbHasSelection );
680 0 : mpCB_LOOP_SOUND->Enable( mbHasSelection && (mpLB_SOUND->GetSelectEntryPos() > 2));
681 0 : mpRB_ADVANCE_ON_MOUSE->Enable( mbHasSelection );
682 0 : mpRB_ADVANCE_AUTO->Enable( mbHasSelection );
683 0 : mpMF_ADVANCE_AUTO_AFTER->Enable( mbHasSelection && mpRB_ADVANCE_AUTO->IsChecked());
684 :
685 0 : mpPB_APPLY_TO_ALL->Enable( mbHasSelection );
686 0 : mpPB_PLAY->Enable( mbHasSelection );
687 0 : mpCB_AUTO_PREVIEW->Enable( mbHasSelection );
688 0 : }
689 :
690 0 : void SlideTransitionPane::updateSoundList()
691 : {
692 0 : maSoundList.clear();
693 :
694 0 : GalleryExplorer::FillObjList( GALLERY_THEME_SOUNDS, maSoundList );
695 0 : GalleryExplorer::FillObjList( GALLERY_THEME_USERSOUNDS, maSoundList );
696 :
697 0 : lcl_FillSoundListBox( maSoundList, mpLB_SOUND );
698 0 : }
699 :
700 0 : void SlideTransitionPane::openSoundFileDialog()
701 : {
702 0 : if( ! mpLB_SOUND->IsEnabled())
703 0 : return;
704 :
705 0 : SdOpenSoundFileDialog aFileDialog;
706 :
707 0 : OUString aFile;
708 : DBG_ASSERT( mpLB_SOUND->GetSelectEntryPos() == 2,
709 : "Dialog should only open when \"Other sound\" is selected" );
710 0 : aFile = SvtPathOptions().GetGraphicPath();
711 :
712 0 : aFileDialog.SetPath( aFile );
713 :
714 0 : bool bValidSoundFile( false );
715 0 : bool bQuitLoop( false );
716 :
717 0 : while( ! bQuitLoop &&
718 0 : aFileDialog.Execute() == ERRCODE_NONE )
719 : {
720 0 : aFile = aFileDialog.GetPath();
721 0 : tSoundListType::size_type nPos = 0;
722 0 : bValidSoundFile = lcl_findSoundInList( maSoundList, aFile, nPos );
723 :
724 0 : if( bValidSoundFile )
725 : {
726 0 : bQuitLoop = true;
727 : }
728 : else // not in sound list
729 : {
730 : // try to insert into gallery
731 0 : if( GalleryExplorer::InsertURL( GALLERY_THEME_USERSOUNDS, aFile ) )
732 : {
733 0 : updateSoundList();
734 0 : bValidSoundFile = lcl_findSoundInList( maSoundList, aFile, nPos );
735 : DBG_ASSERT( bValidSoundFile, "Adding sound to gallery failed" );
736 :
737 0 : bQuitLoop = true;
738 : }
739 : else
740 : {
741 0 : OUString aStrWarning(SD_RESSTR(STR_WARNING_NOSOUNDFILE));
742 0 : aStrWarning = aStrWarning.replaceFirst("%", aFile);
743 0 : ScopedVclPtrInstance< WarningBox > aWarningBox( nullptr, WB_3DLOOK | WB_RETRY_CANCEL, aStrWarning );
744 0 : aWarningBox->SetModalInputMode (true);
745 0 : bQuitLoop = (aWarningBox->Execute() != RET_RETRY);
746 :
747 0 : bValidSoundFile = false;
748 : }
749 : }
750 :
751 0 : if( bValidSoundFile )
752 : // skip first three entries in list
753 0 : mpLB_SOUND->SelectEntryPos( nPos + 3 );
754 : }
755 :
756 0 : if( ! bValidSoundFile )
757 : {
758 0 : if( !maCurrentSoundFile.isEmpty() )
759 : {
760 0 : tSoundListType::size_type nPos = 0;
761 0 : if( lcl_findSoundInList( maSoundList, maCurrentSoundFile, nPos ))
762 0 : mpLB_SOUND->SelectEntryPos( nPos + 3 );
763 : else
764 0 : mpLB_SOUND->SelectEntryPos( 0 ); // NONE
765 : }
766 : else
767 0 : mpLB_SOUND->SelectEntryPos( 0 ); // NONE
768 0 : }
769 : }
770 :
771 0 : impl::TransitionEffect SlideTransitionPane::getTransitionEffectFromControls() const
772 : {
773 0 : impl::TransitionEffect aResult;
774 0 : aResult.setAllAmbiguous();
775 :
776 : // check first (aResult might be overwritten)
777 0 : if( mpLB_SLIDE_TRANSITIONS->IsEnabled() &&
778 0 : mpLB_SLIDE_TRANSITIONS->GetSelectEntryCount() > 0 )
779 : {
780 : TransitionPresetPtr pPreset = lcl_getTransitionPresetByUIName(
781 0 : mpDrawDoc, OUString( mpLB_SLIDE_TRANSITIONS->GetSelectEntry()));
782 :
783 0 : if( pPreset.get())
784 : {
785 0 : aResult = impl::TransitionEffect( *pPreset );
786 0 : aResult.setAllAmbiguous();
787 : }
788 : else
789 : {
790 0 : aResult.mnType = 0;
791 : }
792 0 : aResult.mbEffectAmbiguous = false;
793 : }
794 :
795 : // speed
796 0 : if( mpLB_SPEED->IsEnabled() &&
797 0 : mpLB_SPEED->GetSelectEntryCount() > 0 )
798 : {
799 0 : sal_Int32 nPos = mpLB_SPEED->GetSelectEntryPos();
800 : aResult.mfDuration = (nPos == 0)
801 : ? 3.0
802 : : (nPos == 1)
803 : ? 2.0
804 0 : : 1.0; // nPos == 2
805 : DBG_ASSERT( aResult.mfDuration != 1.0 || nPos == 2, "Invalid Listbox Entry" );
806 :
807 0 : aResult.mbDurationAmbiguous = false;
808 : }
809 :
810 : // slide-advance mode
811 0 : if( mpRB_ADVANCE_ON_MOUSE->IsEnabled() && mpRB_ADVANCE_AUTO->IsEnabled() &&
812 0 : (mpRB_ADVANCE_ON_MOUSE->IsChecked() || mpRB_ADVANCE_AUTO->IsChecked()))
813 : {
814 0 : if( mpRB_ADVANCE_ON_MOUSE->IsChecked())
815 0 : aResult.mePresChange = PRESCHANGE_MANUAL;
816 : else
817 : {
818 0 : aResult.mePresChange = PRESCHANGE_AUTO;
819 0 : if( mpMF_ADVANCE_AUTO_AFTER->IsEnabled())
820 : {
821 0 : aResult.mfTime = static_cast<double>(mpMF_ADVANCE_AUTO_AFTER->GetValue() ) / 100.0 ;
822 0 : aResult.mbTimeAmbiguous = false;
823 : }
824 : }
825 :
826 0 : aResult.mbPresChangeAmbiguous = false;
827 : }
828 :
829 : // sound
830 0 : if( mpLB_SOUND->IsEnabled())
831 : {
832 0 : maCurrentSoundFile.clear();
833 0 : if( mpLB_SOUND->GetSelectEntryCount() > 0 )
834 : {
835 0 : sal_Int32 nPos = mpLB_SOUND->GetSelectEntryPos();
836 0 : aResult.mbStopSound = nPos == 1;
837 0 : aResult.mbSoundOn = nPos > 1;
838 0 : if( aResult.mbStopSound )
839 : {
840 0 : aResult.maSound.clear();
841 0 : aResult.mbSoundAmbiguous = false;
842 : }
843 : else
844 : {
845 0 : aResult.maSound = lcl_getSoundFileURL( maSoundList, mpLB_SOUND );
846 0 : aResult.mbSoundAmbiguous = false;
847 0 : maCurrentSoundFile = aResult.maSound;
848 : }
849 : }
850 : }
851 :
852 : // sound loop
853 0 : if( mpCB_LOOP_SOUND->IsEnabled() )
854 : {
855 0 : aResult.mbLoopSound = mpCB_LOOP_SOUND->IsChecked();
856 0 : aResult.mbLoopSoundAmbiguous = false;
857 : }
858 :
859 0 : return aResult;
860 : }
861 :
862 0 : void SlideTransitionPane::applyToSelectedPages()
863 : {
864 0 : if( ! mbUpdatingControls )
865 : {
866 0 : Window *pFocusWindow = Application::GetFocusWindow();
867 :
868 0 : ::sd::slidesorter::SharedPageSelection pSelectedPages( getSelectedPages());
869 0 : impl::TransitionEffect aEffect = getTransitionEffectFromControls();
870 0 : if( ! pSelectedPages->empty())
871 : {
872 0 : lcl_CreateUndoForPages( pSelectedPages, mrBase );
873 0 : lcl_ApplyToPages( pSelectedPages, aEffect );
874 0 : mrBase.GetDocShell()->SetModified();
875 : }
876 0 : if( mpCB_AUTO_PREVIEW->IsEnabled() &&
877 0 : mpCB_AUTO_PREVIEW->IsChecked())
878 : {
879 0 : if (aEffect.mnType) // mnType = 0 denotes no transition
880 0 : playCurrentEffect();
881 : else
882 0 : stopEffects();
883 : }
884 :
885 0 : if (pFocusWindow)
886 0 : pFocusWindow->GrabFocus();
887 : }
888 0 : }
889 :
890 0 : void SlideTransitionPane::playCurrentEffect()
891 : {
892 0 : if( mxView.is() )
893 : {
894 :
895 0 : Reference< ::com::sun::star::animations::XAnimationNode > xNode;
896 0 : SlideShow::StartPreview( mrBase, mxView->getCurrentPage(), xNode );
897 : }
898 0 : }
899 :
900 0 : void SlideTransitionPane::stopEffects()
901 : {
902 0 : if( mxView.is() )
903 : {
904 0 : SlideShow::Stop( mrBase );
905 : }
906 0 : }
907 :
908 0 : void SlideTransitionPane::addListener()
909 : {
910 0 : Link<> aLink( LINK(this,SlideTransitionPane,EventMultiplexerListener) );
911 : mrBase.GetEventMultiplexer()->AddEventListener (
912 : aLink,
913 : tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION
914 : | tools::EventMultiplexerEvent::EID_SLIDE_SORTER_SELECTION
915 : | tools::EventMultiplexerEvent::EID_CURRENT_PAGE
916 : | tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED
917 : | tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED
918 0 : | tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED);
919 0 : }
920 :
921 0 : void SlideTransitionPane::removeListener()
922 : {
923 0 : Link<> aLink( LINK(this,SlideTransitionPane,EventMultiplexerListener) );
924 0 : mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
925 0 : }
926 :
927 0 : IMPL_LINK(SlideTransitionPane,EventMultiplexerListener,
928 : tools::EventMultiplexerEvent*,pEvent)
929 : {
930 0 : switch (pEvent->meEventId)
931 : {
932 : case tools::EventMultiplexerEvent::EID_EDIT_VIEW_SELECTION:
933 0 : onSelectionChanged();
934 0 : break;
935 :
936 : case tools::EventMultiplexerEvent::EID_CURRENT_PAGE:
937 : case tools::EventMultiplexerEvent::EID_SLIDE_SORTER_SELECTION:
938 0 : onChangeCurrentPage();
939 0 : break;
940 :
941 : case tools::EventMultiplexerEvent::EID_MAIN_VIEW_REMOVED:
942 0 : mxView = Reference<drawing::XDrawView>();
943 0 : onSelectionChanged();
944 0 : onChangeCurrentPage();
945 0 : break;
946 :
947 : case tools::EventMultiplexerEvent::EID_MAIN_VIEW_ADDED:
948 0 : mbIsMainViewChangePending = true;
949 0 : break;
950 :
951 : case tools::EventMultiplexerEvent::EID_CONFIGURATION_UPDATED:
952 0 : if (mbIsMainViewChangePending)
953 : {
954 0 : mbIsMainViewChangePending = false;
955 :
956 : // At this moment the controller may not yet been set at
957 : // model or ViewShellBase. Take it from the view shell
958 : // passed with the event.
959 0 : if (mrBase.GetMainViewShell() != 0)
960 : {
961 0 : mxView = Reference<drawing::XDrawView>::query(mrBase.GetController());
962 0 : onSelectionChanged();
963 0 : onChangeCurrentPage();
964 : }
965 : }
966 0 : break;
967 :
968 : default:
969 0 : break;
970 : }
971 0 : return 0;
972 : }
973 :
974 0 : IMPL_LINK_NOARG(SlideTransitionPane, ApplyToAllButtonClicked)
975 : {
976 : DBG_ASSERT( mpDrawDoc, "Invalid Draw Document!" );
977 0 : if( !mpDrawDoc )
978 0 : return 0;
979 :
980 : ::sd::slidesorter::SharedPageSelection pPages (
981 0 : new ::sd::slidesorter::SlideSorterViewShell::PageSelection());
982 :
983 0 : sal_uInt16 nPageCount = mpDrawDoc->GetSdPageCount( PK_STANDARD );
984 0 : pPages->reserve( nPageCount );
985 0 : for( sal_uInt16 i=0; i<nPageCount; ++i )
986 : {
987 0 : SdPage * pPage = mpDrawDoc->GetSdPage( i, PK_STANDARD );
988 0 : if( pPage )
989 0 : pPages->push_back( pPage );
990 : }
991 :
992 0 : if( ! pPages->empty())
993 : {
994 0 : lcl_CreateUndoForPages( pPages, mrBase );
995 0 : lcl_ApplyToPages( pPages, getTransitionEffectFromControls() );
996 : }
997 :
998 0 : return 0;
999 : }
1000 :
1001 0 : IMPL_LINK_NOARG(SlideTransitionPane, PlayButtonClicked)
1002 : {
1003 0 : playCurrentEffect();
1004 0 : return 0;
1005 : }
1006 :
1007 0 : IMPL_LINK_NOARG(SlideTransitionPane, TransitionSelected)
1008 : {
1009 0 : applyToSelectedPages();
1010 0 : return 0;
1011 : }
1012 :
1013 0 : IMPL_LINK_NOARG(SlideTransitionPane, AdvanceSlideRadioButtonToggled)
1014 : {
1015 0 : updateControlState();
1016 0 : applyToSelectedPages();
1017 0 : return 0;
1018 : }
1019 :
1020 0 : IMPL_LINK_NOARG(SlideTransitionPane, AdvanceTimeModified)
1021 : {
1022 0 : applyToSelectedPages();
1023 0 : return 0;
1024 : }
1025 :
1026 0 : IMPL_LINK_NOARG(SlideTransitionPane, SpeedListBoxSelected)
1027 : {
1028 0 : applyToSelectedPages();
1029 0 : return 0;
1030 : }
1031 :
1032 0 : IMPL_LINK_NOARG(SlideTransitionPane, SoundListBoxSelected)
1033 : {
1034 0 : if( mpLB_SOUND->GetSelectEntryCount() )
1035 : {
1036 0 : sal_Int32 nPos = mpLB_SOUND->GetSelectEntryPos();
1037 0 : if( nPos == 2 )
1038 : {
1039 : // other sound...
1040 0 : openSoundFileDialog();
1041 : }
1042 : }
1043 0 : updateControlState();
1044 0 : applyToSelectedPages();
1045 0 : return 0;
1046 : }
1047 :
1048 0 : IMPL_LINK_NOARG(SlideTransitionPane, LoopSoundBoxChecked)
1049 : {
1050 0 : applyToSelectedPages();
1051 0 : return 0;
1052 : }
1053 :
1054 0 : IMPL_LINK_NOARG(SlideTransitionPane, AutoPreviewClicked)
1055 : {
1056 0 : SdOptions* pOptions = SD_MOD()->GetSdOptions(DOCUMENT_TYPE_IMPRESS);
1057 0 : pOptions->SetPreviewTransitions( mpCB_AUTO_PREVIEW->IsChecked() );
1058 0 : return 0;
1059 : }
1060 :
1061 0 : IMPL_LINK_NOARG_TYPED(SlideTransitionPane, LateInitCallback, Timer *, void)
1062 : {
1063 0 : const TransitionPresetList& rPresetList = TransitionPreset::getTransitionPresetList();
1064 0 : TransitionPresetList::const_iterator aIter( rPresetList.begin() );
1065 0 : const TransitionPresetList::const_iterator aEnd( rPresetList.end() );
1066 0 : sal_uInt16 nIndex = 0;
1067 0 : ::std::size_t nUIIndex = 0;
1068 0 : while( aIter != aEnd )
1069 : {
1070 0 : TransitionPresetPtr pPreset = (*aIter++);
1071 0 : const OUString aUIName( pPreset->getUIName() );
1072 0 : if( !aUIName.isEmpty() )
1073 : {
1074 0 : mpLB_SLIDE_TRANSITIONS->InsertEntry( aUIName );
1075 0 : m_aPresetIndexes[ nIndex ] = (sal_uInt16)nUIIndex;
1076 0 : ++nUIIndex;
1077 : }
1078 0 : ++nIndex;
1079 0 : }
1080 :
1081 0 : updateSoundList();
1082 0 : updateControls();
1083 0 : }
1084 :
1085 0 : vcl::Window * createSlideTransitionPanel( vcl::Window* pParent, ViewShellBase& rBase, const css::uno::Reference<css::frame::XFrame>& rxFrame )
1086 : {
1087 0 : vcl::Window* pWindow = 0;
1088 :
1089 0 : DrawDocShell* pDocSh = rBase.GetDocShell();
1090 0 : if( pDocSh )
1091 : {
1092 0 : Size aMinSize( pParent->LogicToPixel( Size( 72, 216 ), MAP_APPFONT ) );
1093 0 : pWindow = VclPtr<SlideTransitionPane>::Create( pParent, rBase, aMinSize, pDocSh->GetDoc(), rxFrame );
1094 : }
1095 :
1096 0 : return pWindow;
1097 : }
1098 :
1099 66 : } // namespace sd
1100 :
1101 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|