1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/drawing/XDrawView.hpp>
21 #include <SlideTransitionPane.hxx>
23 #include <TransitionPreset.hxx>
24 #include <sdresid.hxx>
25 #include <ViewShellBase.hxx>
26 #include <DrawDocShell.hxx>
27 #include <SlideSorterViewShell.hxx>
28 #include <unomodel.hxx>
29 #include <drawdoc.hxx>
32 #include <filedlg.hxx>
33 #include <strings.hrc>
34 #include <EventMultiplexer.hxx>
36 #include <comphelper/lok.hxx>
37 #include <sal/log.hxx>
38 #include <tools/debug.hxx>
39 #include <svx/gallery.hxx>
41 #include <vcl/stdtext.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/weld.hxx>
44 #include <tools/urlobj.hxx>
45 #include <slideshow.hxx>
46 #include <sdundogr.hxx>
47 #include <undoanim.hxx>
48 #include <optsitem.hxx>
50 #include <o3tl/safeint.hxx>
54 using namespace ::com::sun::star
;
56 using ::com::sun::star::uno::Reference
;
61 struct TransitionEffect
71 explicit TransitionEffect( const ::sd::TransitionPreset
& rPreset
) :
72 mnType( rPreset
.getTransition()),
73 mnSubType( rPreset
.getSubtype()),
74 mbDirection( rPreset
.getDirection()),
75 mnFadeColor( rPreset
.getFadeColor())
79 explicit TransitionEffect( const SdPage
& rPage
) :
80 mnType( rPage
.getTransitionType() ),
81 mnSubType( rPage
.getTransitionSubtype() ),
82 mbDirection( rPage
.getTransitionDirection() ),
83 mnFadeColor( rPage
.getTransitionFadeColor() )
87 mfDuration
= rPage
.getTransitionDuration();
88 mfTime
= rPage
.GetTime();
89 mePresChange
= rPage
.GetPresChange();
90 mbSoundOn
= rPage
.IsSoundOn();
91 maSound
= rPage
.GetSoundFile();
92 mbLoopSound
= rPage
.IsLoopSound();
93 mbStopSound
= rPage
.IsStopSound();
100 mePresChange
= PresChange::Manual
;
105 mbEffectAmbiguous
= false;
106 mbDurationAmbiguous
= false;
107 mbTimeAmbiguous
= false;
108 mbPresChangeAmbiguous
= false;
109 mbSoundAmbiguous
= false;
110 mbLoopSoundAmbiguous
= false;
113 void setAllAmbiguous()
115 mbEffectAmbiguous
= true;
116 mbDurationAmbiguous
= true;
117 mbTimeAmbiguous
= true;
118 mbPresChangeAmbiguous
= true;
119 mbSoundAmbiguous
= true;
120 mbLoopSoundAmbiguous
= true;
123 bool operator == ( const ::sd::TransitionPreset
& rPreset
) const
126 (mnType
== rPreset
.getTransition()) &&
127 (mnSubType
== rPreset
.getSubtype()) &&
128 (mbDirection
== rPreset
.getDirection()) &&
129 (mnFadeColor
== rPreset
.getFadeColor());
132 void applyTo( SdPage
& rOutPage
) const
134 if( ! mbEffectAmbiguous
)
136 rOutPage
.setTransitionType( mnType
);
137 rOutPage
.setTransitionSubtype( mnSubType
);
138 rOutPage
.setTransitionDirection( mbDirection
);
139 rOutPage
.setTransitionFadeColor( mnFadeColor
);
142 if( ! mbDurationAmbiguous
)
143 rOutPage
.setTransitionDuration( mfDuration
);
144 if( ! mbTimeAmbiguous
)
145 rOutPage
.SetTime( mfTime
);
146 if( ! mbPresChangeAmbiguous
)
147 rOutPage
.SetPresChange( mePresChange
);
148 if( ! mbSoundAmbiguous
)
152 rOutPage
.SetStopSound( true );
153 rOutPage
.SetSound( false );
157 rOutPage
.SetStopSound( false );
158 rOutPage
.SetSound( mbSoundOn
);
159 rOutPage
.SetSoundFile( maSound
);
162 if( ! mbLoopSoundAmbiguous
)
163 rOutPage
.SetLoopSound( mbLoopSound
);
166 void compareWith( const SdPage
& rPage
)
168 TransitionEffect
aOtherEffect( rPage
);
169 mbEffectAmbiguous
= mbEffectAmbiguous
|| aOtherEffect
.mbEffectAmbiguous
170 || (mnType
!= aOtherEffect
.mnType
)
171 || (mnSubType
!= aOtherEffect
.mnSubType
)
172 || (mbDirection
!= aOtherEffect
.mbDirection
)
173 || (mnFadeColor
!= aOtherEffect
.mnFadeColor
);
175 mbDurationAmbiguous
= mbDurationAmbiguous
|| aOtherEffect
.mbDurationAmbiguous
|| mfDuration
!= aOtherEffect
.mfDuration
;
176 mbTimeAmbiguous
= mbTimeAmbiguous
|| aOtherEffect
.mbTimeAmbiguous
|| mfTime
!= aOtherEffect
.mfTime
;
177 mbPresChangeAmbiguous
= mbPresChangeAmbiguous
|| aOtherEffect
.mbPresChangeAmbiguous
|| mePresChange
!= aOtherEffect
.mePresChange
;
178 mbSoundAmbiguous
= mbSoundAmbiguous
|| aOtherEffect
.mbSoundAmbiguous
|| mbSoundOn
!= aOtherEffect
.mbSoundOn
;
180 // Weird leftover isolated expression with no effect, introduced in 2007 in
181 // CWS impress122. Ifdeffed out to avoid compiler warning, kept here in case
182 // somebody who understands this code notices and understands what the
183 // "right" thing to do might be.
184 (!mbStopSound
&& !aOtherEffect
.mbStopSound
&& maSound
!= aOtherEffect
.maSound
) || (mbStopSound
!= aOtherEffect
.mbStopSound
);
186 mbLoopSoundAmbiguous
= mbLoopSoundAmbiguous
|| aOtherEffect
.mbLoopSoundAmbiguous
|| mbLoopSound
!= aOtherEffect
.mbLoopSound
;
193 sal_Int32 mnFadeColor
;
198 PresChange mePresChange
;
204 bool mbEffectAmbiguous
;
205 bool mbDurationAmbiguous
;
206 bool mbTimeAmbiguous
;
207 bool mbPresChangeAmbiguous
;
208 bool mbSoundAmbiguous
;
209 bool mbLoopSoundAmbiguous
;
212 } // namespace sd::impl
217 // Local Helper Functions
221 void lcl_ApplyToPages(
222 const ::sd::slidesorter::SharedPageSelection
& rpPages
,
223 const ::sd::impl::TransitionEffect
& rEffect
)
225 for( const auto& rpPage
: *rpPages
)
227 rEffect
.applyTo( *rpPage
);
231 void lcl_CreateUndoForPages(
232 const ::sd::slidesorter::SharedPageSelection
& rpPages
,
233 ::sd::ViewShellBase
const & rBase
)
235 ::sd::DrawDocShell
* pDocSh
= rBase
.GetDocShell();
238 SfxUndoManager
* pManager
= pDocSh
->GetUndoManager();
241 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
245 OUString
aComment( SdResId(STR_UNDO_SLIDE_PARAMS
) );
246 pManager
->EnterListAction(aComment
, aComment
, 0, rBase
.GetViewShellId());
247 std::unique_ptr
<SdUndoGroup
> pUndoGroup(new SdUndoGroup( pDoc
));
248 pUndoGroup
->SetComment( aComment
);
250 for( const auto& rpPage
: *rpPages
)
252 pUndoGroup
->AddAction( new sd::UndoTransition( pDoc
, rpPage
) );
255 pManager
->AddUndoAction( std::move(pUndoGroup
) );
256 pManager
->LeaveListAction();
259 struct lcl_EqualsSoundFileName
261 explicit lcl_EqualsSoundFileName( OUString aStr
) :
262 maStr(std::move( aStr
))
265 bool operator() ( const OUString
& rStr
) const
267 // note: formerly this was a case insensitive search for all
268 // platforms. It seems more sensible to do this platform-dependent
269 INetURLObject
aURL(rStr
);
271 return maStr
.equalsIgnoreAsciiCase( aURL
.GetBase() );
273 return maStr
== aURL
.GetBase();
281 // returns -1 if no object was found
282 bool lcl_findSoundInList( const ::std::vector
< OUString
> & rSoundList
,
283 std::u16string_view rFileName
,
284 ::std::vector
< OUString
>::size_type
& rOutPosition
)
286 INetURLObject
aURL(rFileName
);
287 ::std::vector
< OUString
>::const_iterator aIt
=
288 ::std::find_if( rSoundList
.begin(), rSoundList
.end(),
289 lcl_EqualsSoundFileName( aURL
.GetBase()));
290 if( aIt
!= rSoundList
.end())
292 rOutPosition
= ::std::distance( rSoundList
.begin(), aIt
);
299 OUString
lcl_getSoundFileURL(
300 const ::std::vector
< OUString
> & rSoundList
,
301 const weld::ComboBox
& rListBox
)
303 sal_Int32 nPos
= rListBox
.get_active();
304 // the first three entries are no actual sounds
307 DBG_ASSERT( static_cast<sal_uInt32
>(rListBox
.get_count() - 3) == rSoundList
.size(),
308 "Sound list-box is not synchronized to sound list" );
310 if( rSoundList
.size() > o3tl::make_unsigned(nPos
) )
311 return rSoundList
[ nPos
];
317 struct lcl_AppendSoundToListBox
319 explicit lcl_AppendSoundToListBox(weld::ComboBox
& rListBox
)
320 : mrListBox( rListBox
)
323 void operator() ( std::u16string_view rString
) const
325 INetURLObject
aURL( rString
);
326 mrListBox
.append_text( aURL
.GetBase() );
330 weld::ComboBox
& mrListBox
;
333 void lcl_FillSoundListBox(
334 const ::std::vector
< OUString
> & rSoundList
,
335 weld::ComboBox
& rOutListBox
)
337 sal_Int32 nCount
= rOutListBox
.get_count();
339 // keep first three entries
340 for( sal_Int32 i
=nCount
- 1; i
>=3; --i
)
341 rOutListBox
.remove( i
);
343 ::std::for_each( rSoundList
.begin(), rSoundList
.end(),
344 lcl_AppendSoundToListBox( rOutListBox
));
347 /// Returns an offset into the list of transition presets
348 sd::TransitionPresetPtr
getPreset(const sd::impl::TransitionEffect
&rEffect
)
350 const sd::TransitionPresetList
& rPresetList
= sd::TransitionPreset::getTransitionPresetList();
352 for (const auto& pPreset
: rPresetList
)
354 if (rEffect
.operator==(*pPreset
))
357 return sd::TransitionPresetPtr();
360 } // anonymous namespace
362 // SlideTransitionPane
363 SlideTransitionPane::SlideTransitionPane(
364 weld::Widget
* pParent
,
365 ViewShellBase
& rBase
) :
366 PanelLayout( pParent
, u
"SlideTransitionsPanel"_ustr
, u
"modules/simpress/ui/slidetransitionspanel.ui"_ustr
),
368 mpDrawDoc( rBase
.GetDocShell() ? rBase
.GetDocShell()->GetDoc() : nullptr ),
369 mxTransitionsIconView(m_xBuilder
->weld_icon_view("transitions_icons")),
370 mxTransitionsScrollWindow(m_xBuilder
->weld_scrolled_window("transitions_icons_scrolled_window")),
371 mxRepeatAutoFrame(m_xBuilder
->weld_frame("repeat_after_frame")),
372 mbHasSelection( false ),
373 mbUpdatingControls( false ),
374 mbIsMainViewChangePending( false ),
375 maLateInitTimer("sd SlideTransitionPane maLateInitTimer")
377 Initialize(mpDrawDoc
);
380 css::ui::LayoutSize
SlideTransitionPane::GetHeightForWidth(const sal_Int32
/*nWidth*/)
382 sal_Int32 nMinimumHeight
= get_preferred_size().Height();
383 return css::ui::LayoutSize(nMinimumHeight
, -1, nMinimumHeight
);
386 void SlideTransitionPane::Initialize(SdDrawDocument
* pDoc
)
388 mxLB_VARIANT
= m_xBuilder
->weld_combo_box(u
"variant_list"_ustr
);
389 mxCBX_duration
= m_xBuilder
->weld_metric_spin_button(u
"transition_duration"_ustr
, FieldUnit::SECOND
);
390 mxFT_SOUND
= m_xBuilder
->weld_label(u
"sound_label"_ustr
);
391 mxLB_SOUND
= m_xBuilder
->weld_combo_box(u
"sound_list"_ustr
);
392 mxCB_LOOP_SOUND
= m_xBuilder
->weld_check_button(u
"loop_sound"_ustr
);
393 mxRB_ADVANCE_ON_MOUSE
= m_xBuilder
->weld_radio_button(u
"rb_mouse_click"_ustr
);
394 mxRB_ADVANCE_AUTO
= m_xBuilder
->weld_radio_button(u
"rb_auto_after"_ustr
);
395 mxMF_ADVANCE_AUTO_AFTER
= m_xBuilder
->weld_metric_spin_button(u
"auto_after_value"_ustr
, FieldUnit::SECOND
);
396 mxRB_REPEAT_DISABLED
= m_xBuilder
->weld_radio_button(u
"rb_disabled"_ustr
);
397 mxRB_REPEAT_AUTO
= m_xBuilder
->weld_radio_button(u
"rb_auto_repeat"_ustr
);
398 mxMF_REPEAT_AUTO_AFTER
= m_xBuilder
->weld_metric_spin_button(u
"rb_auto_repeat_value"_ustr
, FieldUnit::SECOND
);
399 mxPB_APPLY_TO_ALL
= m_xBuilder
->weld_button(u
"apply_to_all"_ustr
);
400 mxPB_PLAY
= m_xBuilder
->weld_button(u
"play"_ustr
);
401 mxCB_AUTO_PREVIEW
= m_xBuilder
->weld_check_button(u
"auto_preview"_ustr
);
403 auto nMax
= mxMF_ADVANCE_AUTO_AFTER
->get_max(FieldUnit::SECOND
);
404 mxMF_ADVANCE_AUTO_AFTER
->set_max(99, FieldUnit::SECOND
);
405 int nWidthChars
= mxMF_ADVANCE_AUTO_AFTER
->get_width_chars();
406 mxMF_ADVANCE_AUTO_AFTER
->set_max(nMax
, FieldUnit::SECOND
);
407 mxMF_ADVANCE_AUTO_AFTER
->set_width_chars(nWidthChars
);
408 mxMF_REPEAT_AUTO_AFTER
->set_max(nMax
, FieldUnit::SECOND
);
409 mxMF_REPEAT_AUTO_AFTER
->set_width_chars(nWidthChars
);
410 mxCBX_duration
->set_width_chars(nWidthChars
);
413 mxModel
= pDoc
->getUnoModel();
414 // TODO: get correct view
416 mxView
.set( mxModel
->getCurrentController(), uno::UNO_QUERY
);
419 mxCB_AUTO_PREVIEW
->set_active(true); // automatic preview on
421 // update control states before adding handlers
425 mxPB_APPLY_TO_ALL
->connect_clicked( LINK( this, SlideTransitionPane
, ApplyToAllButtonClicked
));
426 mxPB_PLAY
->connect_clicked( LINK( this, SlideTransitionPane
, PlayButtonClicked
));
428 mxTransitionsIconView
->connect_item_activated(LINK(this, SlideTransitionPane
, TransitionSelected
));
430 mxLB_VARIANT
->connect_changed( LINK( this, SlideTransitionPane
, VariantListBoxSelected
));
431 mxCBX_duration
->connect_value_changed(LINK( this, SlideTransitionPane
, DurationModifiedHdl
));
432 mxCBX_duration
->connect_focus_out(LINK( this, SlideTransitionPane
, DurationLoseFocusHdl
));
433 mxLB_SOUND
->connect_changed( LINK( this, SlideTransitionPane
, SoundListBoxSelected
));
434 mxCB_LOOP_SOUND
->connect_toggled( LINK( this, SlideTransitionPane
, LoopSoundBoxChecked
));
436 mxRB_ADVANCE_ON_MOUSE
->connect_toggled( LINK( this, SlideTransitionPane
, AdvanceSlideRadioButtonToggled
));
437 mxRB_ADVANCE_AUTO
->connect_toggled( LINK( this, SlideTransitionPane
, AdvanceSlideRadioButtonToggled
));
438 mxMF_ADVANCE_AUTO_AFTER
->connect_value_changed( LINK( this, SlideTransitionPane
, AdvanceTimeModified
));
439 mxRB_REPEAT_DISABLED
->connect_toggled( LINK( this, SlideTransitionPane
, RepeatAfterRadioButtonToggled
));
440 mxRB_REPEAT_AUTO
->connect_toggled( LINK( this, SlideTransitionPane
, RepeatAfterRadioButtonToggled
));
441 mxMF_REPEAT_AUTO_AFTER
->connect_value_changed( LINK( this, SlideTransitionPane
, RepeatAfterTimeModified
));
442 mxCB_AUTO_PREVIEW
->connect_toggled( LINK( this, SlideTransitionPane
, AutoPreviewClicked
));
445 mxRB_REPEAT_DISABLED
->set_active( true );
447 maLateInitTimer
.SetTimeout(200);
448 maLateInitTimer
.SetInvokeHandler(LINK(this, SlideTransitionPane
, LateInitCallback
));
449 maLateInitTimer
.Start();
452 SlideTransitionPane::~SlideTransitionPane()
454 maLateInitTimer
.Stop();
456 mxTransitionsScrollWindow
.reset();
457 mxTransitionsIconView
.reset();
458 mxRepeatAutoFrame
.reset();
459 mxLB_VARIANT
.reset();
460 mxCBX_duration
.reset();
463 mxCB_LOOP_SOUND
.reset();
464 mxRB_ADVANCE_ON_MOUSE
.reset();
465 mxRB_ADVANCE_AUTO
.reset();
466 mxMF_ADVANCE_AUTO_AFTER
.reset();
467 mxRB_REPEAT_DISABLED
.reset();
468 mxRB_REPEAT_AUTO
.reset();
469 mxMF_REPEAT_AUTO_AFTER
.reset();
470 mxPB_APPLY_TO_ALL
.reset();
472 mxCB_AUTO_PREVIEW
.reset();
475 void SlideTransitionPane::onSelectionChanged()
480 void SlideTransitionPane::onChangeCurrentPage()
485 ::sd::slidesorter::SharedPageSelection
SlideTransitionPane::getSelectedPages() const
487 ::sd::slidesorter::SlideSorterViewShell
* pSlideSorterViewShell
488 = ::sd::slidesorter::SlideSorterViewShell::GetSlideSorter(mrBase
);
489 std::shared_ptr
<sd::slidesorter::SlideSorterViewShell::PageSelection
> pSelection
;
491 if( pSlideSorterViewShell
)
493 pSelection
= pSlideSorterViewShell
->GetPageSelection();
497 pSelection
= std::make_shared
<sd::slidesorter::SlideSorterViewShell::PageSelection
>();
500 SdPage
* pPage
= SdPage::getImplementation( mxView
->getCurrentPage() );
502 pSelection
->push_back(pPage
);
509 void SlideTransitionPane::updateControls()
511 ::sd::slidesorter::SharedPageSelection
pSelectedPages(getSelectedPages());
512 if( pSelectedPages
->empty())
514 mbHasSelection
= false;
517 mbHasSelection
= true;
519 DBG_ASSERT( ! mbUpdatingControls
, "Multiple Control Updates" );
520 mbUpdatingControls
= true;
522 // get model data for first page
523 SdPage
* pFirstPage
= pSelectedPages
->front();
524 DBG_ASSERT( pFirstPage
, "Invalid Page" );
526 impl::TransitionEffect
aEffect( *pFirstPage
);
528 // merge with other pages
530 // start with second page (note aIt != aEndIt, because ! aSelectedPages.empty())
531 for( const auto& rpPage
: *pSelectedPages
)
534 aEffect
.compareWith( *rpPage
);
537 // detect current slide effect
538 if( aEffect
.mbEffectAmbiguous
)
540 SAL_WARN( "sd.transitions", "Unusual, ambiguous transition effect" );
541 mxTransitionsIconView
->select(0);
545 // ToDo: That 0 is "no transition" is documented nowhere except in the
547 if( aEffect
.mnType
== 0 )
548 mxTransitionsIconView
->select(0);
550 updateVariants(getPreset(aEffect
));
553 if( aEffect
.mbDurationAmbiguous
)
555 mxCBX_duration
->set_text(u
""_ustr
);
556 //TODO mxCBX_duration->SetNoSelection();
560 mxCBX_duration
->set_value( (aEffect
.mfDuration
)*100.0, FieldUnit::SECOND
);
563 if( aEffect
.mbSoundAmbiguous
)
565 mxLB_SOUND
->set_active(-1);
566 maCurrentSoundFile
.clear();
570 maCurrentSoundFile
.clear();
571 if( aEffect
.mbStopSound
)
573 mxLB_SOUND
->set_active( 1 );
575 else if( aEffect
.mbSoundOn
&& !aEffect
.maSound
.isEmpty() )
577 std::vector
<OUString
>::size_type nPos
= 0;
578 if( lcl_findSoundInList( maSoundList
, aEffect
.maSound
, nPos
))
580 mxLB_SOUND
->set_active( nPos
+ 3 );
581 maCurrentSoundFile
= aEffect
.maSound
;
586 mxLB_SOUND
->set_active( 0 );
590 if( aEffect
.mbLoopSoundAmbiguous
)
592 mxCB_LOOP_SOUND
->set_state(TRISTATE_INDET
);
596 mxCB_LOOP_SOUND
->set_active(aEffect
.mbLoopSound
);
599 if( aEffect
.mbPresChangeAmbiguous
)
601 mxRB_ADVANCE_ON_MOUSE
->set_active( false );
602 mxRB_ADVANCE_AUTO
->set_active( false );
606 mxRB_ADVANCE_ON_MOUSE
->set_active( aEffect
.mePresChange
== PresChange::Manual
);
607 mxRB_ADVANCE_AUTO
->set_active( aEffect
.mePresChange
== PresChange::Auto
);
608 mxMF_ADVANCE_AUTO_AFTER
->set_value(aEffect
.mfTime
* 100.0, FieldUnit::SECOND
);
611 sd::PresentationSettings
& rSettings
= mpDrawDoc
->getPresentationSettings();
613 if ( !rSettings
.mbEndless
)
615 mxRB_REPEAT_DISABLED
->set_active( true );
616 mxRB_REPEAT_AUTO
->set_active( false );
620 mxRB_REPEAT_DISABLED
->set_active( false );
621 mxRB_REPEAT_AUTO
->set_active( true );
622 mxMF_REPEAT_AUTO_AFTER
->set_value(rSettings
.mnPauseTimeout
* 100.0, FieldUnit::SECOND
);
625 if (comphelper::LibreOfficeKit::isActive())
628 mxCB_AUTO_PREVIEW
->set_active(false);
629 mxCB_AUTO_PREVIEW
->hide();
632 mxCB_LOOP_SOUND
->hide();
636 mxRepeatAutoFrame
->hide();
637 SdOptions
* pOptions
= SdModule::get()->GetSdOptions(DocumentType::Impress
);
638 mxCB_AUTO_PREVIEW
->set_active( pOptions
->IsPreviewTransitions() );
641 mbUpdatingControls
= false;
643 updateControlState();
646 void SlideTransitionPane::updateControlState()
648 if (mxTransitionsScrollWindow
)
649 mxTransitionsScrollWindow
->set_sensitive(mbHasSelection
);
650 mxLB_VARIANT
->set_sensitive( mbHasSelection
&& mxLB_VARIANT
->get_count() > 0 );
651 mxCBX_duration
->set_sensitive( mbHasSelection
);
652 mxLB_SOUND
->set_sensitive( mbHasSelection
);
653 mxCB_LOOP_SOUND
->set_sensitive( mbHasSelection
&& (mxLB_SOUND
->get_active() > 2));
654 mxRB_ADVANCE_ON_MOUSE
->set_sensitive( mbHasSelection
);
655 mxRB_ADVANCE_AUTO
->set_sensitive( mbHasSelection
);
656 mxMF_ADVANCE_AUTO_AFTER
->set_sensitive( mbHasSelection
&& mxRB_ADVANCE_AUTO
->get_active());
657 mxRB_REPEAT_DISABLED
->set_sensitive( mbHasSelection
);
658 mxRB_REPEAT_AUTO
->set_sensitive( mbHasSelection
);
659 mxMF_REPEAT_AUTO_AFTER
->set_sensitive( mbHasSelection
&& mxRB_REPEAT_AUTO
->get_active());
661 mxPB_APPLY_TO_ALL
->set_sensitive( mbHasSelection
);
662 mxPB_PLAY
->set_sensitive( mbHasSelection
);
663 mxCB_AUTO_PREVIEW
->set_sensitive( mbHasSelection
);
666 void SlideTransitionPane::updateSoundList()
670 GalleryExplorer::FillObjList( GALLERY_THEME_SOUNDS
, maSoundList
);
671 GalleryExplorer::FillObjList( GALLERY_THEME_USERSOUNDS
, maSoundList
);
673 lcl_FillSoundListBox( maSoundList
, *mxLB_SOUND
);
676 void SlideTransitionPane::openSoundFileDialog()
678 if( ! mxLB_SOUND
->get_sensitive())
681 weld::Window
* pDialogParent(GetFrameWeld());
682 SdOpenSoundFileDialog
aFileDialog(pDialogParent
);
684 DBG_ASSERT( mxLB_SOUND
->get_active() == 2,
685 "Dialog should only open when \"Other sound\" is selected" );
687 bool bValidSoundFile( false );
688 bool bQuitLoop( false );
690 while( ! bQuitLoop
&&
691 aFileDialog
.Execute() == ERRCODE_NONE
)
693 OUString aFile
= aFileDialog
.GetPath();
694 std::vector
<OUString
>::size_type nPos
= 0;
695 bValidSoundFile
= lcl_findSoundInList( maSoundList
, aFile
, nPos
);
697 if( bValidSoundFile
)
701 else // not in sound list
703 // try to insert into gallery
704 if( GalleryExplorer::InsertURL( GALLERY_THEME_USERSOUNDS
, aFile
) )
707 bValidSoundFile
= lcl_findSoundInList( maSoundList
, aFile
, nPos
);
708 DBG_ASSERT( bValidSoundFile
, "Adding sound to gallery failed" );
714 OUString
aStrWarning(SdResId(STR_WARNING_NOSOUNDFILE
));
715 aStrWarning
= aStrWarning
.replaceFirst("%", aFile
);
716 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(pDialogParent
,
717 VclMessageType::Warning
, VclButtonsType::NONE
,
719 xWarn
->add_button(GetStandardText(StandardButtonType::Retry
), RET_RETRY
);
720 xWarn
->add_button(GetStandardText(StandardButtonType::Cancel
), RET_CANCEL
);
721 bQuitLoop
= (xWarn
->run() != RET_RETRY
);
723 bValidSoundFile
= false;
727 if( bValidSoundFile
)
728 // skip first three entries in list
729 mxLB_SOUND
->set_active( nPos
+ 3 );
732 if( bValidSoundFile
)
735 if( !maCurrentSoundFile
.isEmpty() )
737 std::vector
<OUString
>::size_type nPos
= 0;
738 if( lcl_findSoundInList( maSoundList
, maCurrentSoundFile
, nPos
))
739 mxLB_SOUND
->set_active( nPos
+ 3 );
741 mxLB_SOUND
->set_active( 0 ); // NONE
744 mxLB_SOUND
->set_active( 0 ); // NONE
747 impl::TransitionEffect
SlideTransitionPane::getTransitionEffectFromControls() const
749 impl::TransitionEffect aResult
;
750 aResult
.setAllAmbiguous();
752 OUString sSelectedId
= mxTransitionsIconView
->get_selected_id();
753 auto* pTransitionEntry
= weld::fromId
<TransitionEntry
*>(sSelectedId
);
754 if (!pTransitionEntry
)
757 const sd::TransitionPresetList
& rPresetList
= sd::TransitionPreset::getTransitionPresetList();
759 if (pTransitionEntry
->mpPreset
)
761 auto pSelectedPreset
= pTransitionEntry
->mpPreset
;
763 if (mxLB_VARIANT
->get_active() == -1)
765 // Transition with just one effect.
766 aResult
= impl::TransitionEffect(*pSelectedPreset
);
767 aResult
.setAllAmbiguous();
773 for(const auto& rPreset
: rPresetList
)
775 if (rPreset
->getSetId() == pSelectedPreset
->getSetId() )
777 if( mxLB_VARIANT
->get_active() == nVariant
)
779 aResult
= impl::TransitionEffect(*rPreset
);
780 aResult
.setAllAmbiguous();
795 aResult
.mbEffectAmbiguous
= false;
799 aResult
.mbEffectAmbiguous
= false;
804 if( mxCBX_duration
->get_sensitive() && (!(mxCBX_duration
->get_text()).isEmpty()) )
806 aResult
.mfDuration
= static_cast<double>(mxCBX_duration
->get_value(FieldUnit::SECOND
))/100.0;
807 aResult
.mbDurationAmbiguous
= false;
810 // slide-advance mode
811 if( mxRB_ADVANCE_ON_MOUSE
->get_sensitive() && mxRB_ADVANCE_AUTO
->get_sensitive() &&
812 (mxRB_ADVANCE_ON_MOUSE
->get_active() || mxRB_ADVANCE_AUTO
->get_active()))
814 if( mxRB_ADVANCE_ON_MOUSE
->get_active())
815 aResult
.mePresChange
= PresChange::Manual
;
818 aResult
.mePresChange
= PresChange::Auto
;
819 if( mxMF_ADVANCE_AUTO_AFTER
->get_sensitive())
821 aResult
.mfTime
= static_cast<double>(mxMF_ADVANCE_AUTO_AFTER
->get_value(FieldUnit::SECOND
) ) / 100.0 ;
822 aResult
.mbTimeAmbiguous
= false;
826 aResult
.mbPresChangeAmbiguous
= false;
829 // transition repeat after
830 if (mxRB_REPEAT_DISABLED
->get_sensitive() && mxRB_REPEAT_AUTO
->get_sensitive()
831 && (mxRB_REPEAT_DISABLED
->get_active() || mxRB_REPEAT_AUTO
->get_active()))
833 sd::PresentationSettings
& rSettings
= mpDrawDoc
->getPresentationSettings();
835 if ( mxRB_REPEAT_DISABLED
->get_active() )
837 rSettings
.mbEndless
= false;
838 rSettings
.mnPauseTimeout
= 0;
842 if ( mxMF_REPEAT_AUTO_AFTER
->get_sensitive() )
844 rSettings
.mbEndless
= true;
845 rSettings
.mnPauseTimeout
= static_cast<sal_uInt32
>(mxMF_REPEAT_AUTO_AFTER
->get_value(FieldUnit::SECOND
) / 100.0) ;
851 if( mxLB_SOUND
->get_sensitive())
853 maCurrentSoundFile
.clear();
854 sal_Int32 nPos
= mxLB_SOUND
->get_active();
857 aResult
.mbStopSound
= nPos
== 1;
858 aResult
.mbSoundOn
= nPos
> 1;
859 if( aResult
.mbStopSound
)
861 aResult
.maSound
.clear();
862 aResult
.mbSoundAmbiguous
= false;
866 aResult
.maSound
= lcl_getSoundFileURL(maSoundList
, *mxLB_SOUND
);
867 aResult
.mbSoundAmbiguous
= false;
868 maCurrentSoundFile
= aResult
.maSound
;
874 if( mxCB_LOOP_SOUND
->get_sensitive() )
876 aResult
.mbLoopSound
= mxCB_LOOP_SOUND
->get_active();
877 aResult
.mbLoopSoundAmbiguous
= false;
883 void SlideTransitionPane::applyToSelectedPages(bool bPreview
= true)
885 if( mbUpdatingControls
)
888 vcl::Window
*pFocusWindow
= Application::GetFocusWindow();
890 ::sd::slidesorter::SharedPageSelection
pSelectedPages( getSelectedPages());
891 impl::TransitionEffect aEffect
= getTransitionEffectFromControls();
892 if( ! pSelectedPages
->empty())
894 lcl_CreateUndoForPages( pSelectedPages
, mrBase
);
895 lcl_ApplyToPages( pSelectedPages
, aEffect
);
896 mrBase
.GetDocShell()->SetModified();
898 if( mxCB_AUTO_PREVIEW
->get_sensitive() &&
899 mxCB_AUTO_PREVIEW
->get_active() && bPreview
)
901 if (aEffect
.mnType
) // mnType = 0 denotes no transition
903 else if( mxView
.is() && !SlideShow::IsInteractiveSlideshow(&mrBase
)) // IASS
904 SlideShow::Stop( mrBase
);
908 pFocusWindow
->GrabFocus();
911 void SlideTransitionPane::playCurrentEffect()
916 Reference
< css::animations::XAnimationNode
> xNode
;
917 SlideShow::StartPreview( mrBase
, mxView
->getCurrentPage(), xNode
);
921 void SlideTransitionPane::addListener()
923 Link
<tools::EventMultiplexerEvent
&,void> aLink( LINK(this,SlideTransitionPane
,EventMultiplexerListener
) );
924 mrBase
.GetEventMultiplexer()->AddEventListener( aLink
);
927 void SlideTransitionPane::removeListener()
929 Link
<tools::EventMultiplexerEvent
&,void> aLink( LINK(this,SlideTransitionPane
,EventMultiplexerListener
) );
930 mrBase
.GetEventMultiplexer()->RemoveEventListener( aLink
);
933 IMPL_LINK(SlideTransitionPane
,EventMultiplexerListener
,
934 tools::EventMultiplexerEvent
&, rEvent
, void)
936 switch (rEvent
.meEventId
)
938 case EventMultiplexerEventId::EditViewSelection
:
939 onSelectionChanged();
942 case EventMultiplexerEventId::CurrentPageChanged
:
943 case EventMultiplexerEventId::SlideSortedSelection
:
944 onChangeCurrentPage();
947 case EventMultiplexerEventId::MainViewRemoved
:
949 onSelectionChanged();
950 onChangeCurrentPage();
953 case EventMultiplexerEventId::MainViewAdded
:
954 mbIsMainViewChangePending
= true;
957 case EventMultiplexerEventId::ConfigurationUpdated
:
958 if (mbIsMainViewChangePending
)
960 mbIsMainViewChangePending
= false;
962 // At this moment the controller may not yet been set at
963 // model or ViewShellBase. Take it from the view shell
964 // passed with the event.
965 if (mrBase
.GetMainViewShell() != nullptr)
967 mxView
.set(mrBase
.GetController(), css::uno::UNO_QUERY
);
968 onSelectionChanged();
969 onChangeCurrentPage();
975 if (rEvent
.meEventId
!= EventMultiplexerEventId::Disposing
)
977 onSelectionChanged();
978 onChangeCurrentPage();
984 IMPL_LINK_NOARG(SlideTransitionPane
, ApplyToAllButtonClicked
, weld::Button
&, void)
986 DBG_ASSERT( mpDrawDoc
, "Invalid Draw Document!" );
990 ::sd::slidesorter::SharedPageSelection pPages
=
991 std::make_shared
<::sd::slidesorter::SlideSorterViewShell::PageSelection
>();
993 sal_uInt16 nPageCount
= mpDrawDoc
->GetSdPageCount( PageKind::Standard
);
994 pPages
->reserve( nPageCount
);
995 for( sal_uInt16 i
=0; i
<nPageCount
; ++i
)
997 SdPage
* pPage
= mpDrawDoc
->GetSdPage( i
, PageKind::Standard
);
999 pPages
->push_back( pPage
);
1002 if( ! pPages
->empty())
1004 lcl_CreateUndoForPages( pPages
, mrBase
);
1005 lcl_ApplyToPages( pPages
, getTransitionEffectFromControls() );
1009 IMPL_LINK_NOARG(SlideTransitionPane
, PlayButtonClicked
, weld::Button
&, void)
1011 playCurrentEffect();
1014 IMPL_LINK_NOARG(SlideTransitionPane
, TransitionSelected
, weld::IconView
&, bool)
1016 OUString sSelectedId
= mxTransitionsIconView
->get_selected_id();
1017 auto* pTransitionEntry
= weld::fromId
<TransitionEntry
*>(sSelectedId
);
1018 updateVariants(pTransitionEntry
->mpPreset
);
1019 applyToSelectedPages();
1023 /// we use an integer offset into the list of transition presets
1024 void SlideTransitionPane::updateVariants(TransitionPresetPtr
const& pPreset
)
1026 mxLB_VARIANT
->clear();
1027 mxLB_VARIANT
->set_sensitive(false);
1028 mxLB_VARIANT
->set_active(0);
1032 mxTransitionsIconView
->select(0);
1036 auto iterator
= maTranstionMap
.find(pPreset
->getSetId());
1037 if (iterator
!= maTranstionMap
.end())
1039 auto& pTransitionEntry
= iterator
->second
;
1040 if (!pTransitionEntry
->mnVariants
.empty())
1042 for (OUString
const& rCurrentVariant
: pTransitionEntry
->mnVariants
)
1044 mxLB_VARIANT
->append_text(rCurrentVariant
);
1045 if (pPreset
->getVariantLabel() == rCurrentVariant
)
1046 mxLB_VARIANT
->set_active(mxLB_VARIANT
->get_count() - 1);
1048 mxLB_VARIANT
->set_sensitive(true);
1051 mxTransitionsIconView
->select(pTransitionEntry
->mnIndex
);
1056 IMPL_LINK_NOARG(SlideTransitionPane
, AdvanceSlideRadioButtonToggled
, weld::Toggleable
&, void)
1058 updateControlState();
1059 applyToSelectedPages(false);
1062 IMPL_LINK_NOARG(SlideTransitionPane
, RepeatAfterRadioButtonToggled
, weld::Toggleable
&, void)
1064 updateControlState();
1065 applyToSelectedPages(false);
1068 IMPL_LINK_NOARG(SlideTransitionPane
, AdvanceTimeModified
, weld::MetricSpinButton
&, void)
1070 applyToSelectedPages(false);
1073 IMPL_LINK_NOARG(SlideTransitionPane
, RepeatAfterTimeModified
, weld::MetricSpinButton
&, void)
1075 applyToSelectedPages(false);
1078 IMPL_LINK_NOARG(SlideTransitionPane
, VariantListBoxSelected
, weld::ComboBox
&, void)
1080 applyToSelectedPages();
1083 IMPL_LINK_NOARG(SlideTransitionPane
, DurationModifiedHdl
, weld::MetricSpinButton
&, void)
1085 double duration_value
= static_cast<double>(mxCBX_duration
->get_value(FieldUnit::SECOND
));
1086 if (duration_value
<= 0.0)
1087 mxCBX_duration
->set_value(0, FieldUnit::SECOND
);
1089 mxCBX_duration
->set_value(duration_value
, FieldUnit::SECOND
);
1091 applyToSelectedPages();
1094 IMPL_LINK_NOARG(SlideTransitionPane
, DurationLoseFocusHdl
, weld::Widget
&, void)
1096 applyToSelectedPages();
1099 IMPL_LINK_NOARG(SlideTransitionPane
, SoundListBoxSelected
, weld::ComboBox
&, void)
1101 sal_Int32 nPos
= mxLB_SOUND
->get_active();
1105 openSoundFileDialog();
1107 updateControlState();
1108 applyToSelectedPages();
1111 IMPL_LINK_NOARG(SlideTransitionPane
, LoopSoundBoxChecked
, weld::Toggleable
&, void)
1113 applyToSelectedPages();
1116 IMPL_LINK_NOARG(SlideTransitionPane
, AutoPreviewClicked
, weld::Toggleable
&, void)
1118 SdOptions
* pOptions
= SdModule::get()->GetSdOptions(DocumentType::Impress
);
1119 pOptions
->SetPreviewTransitions( mxCB_AUTO_PREVIEW
->get_active() );
1122 IMPL_LINK_NOARG(SlideTransitionPane
, LateInitCallback
, Timer
*, void)
1124 mxTransitionsIconView
->freeze();
1127 auto pTransition
= std::make_unique
<TransitionEntry
>();
1128 const OUString aId
= weld::toId(pTransition
.get());
1129 pTransition
->msIcon
= u
"sd/cmd/transition-none.png"_ustr
;
1130 pTransition
->msLabel
= SdResId(STR_SLIDETRANSITION_NONE
);
1131 pTransition
->mnIndex
= 0;
1132 mxTransitionsIconView
->append(aId
, pTransition
->msLabel
, pTransition
->msIcon
);
1133 maTranstionMap
.emplace(u
"None"_ustr
, std::move(pTransition
));
1136 const TransitionPresetList
& rPresetList
= TransitionPreset::getTransitionPresetList();
1138 for (TransitionPresetPtr
const& pPreset
: rPresetList
)
1140 const OUString aLabel
= pPreset
->getSetLabel();
1141 if (!aLabel
.isEmpty())
1143 auto aIterator
= maTranstionMap
.find(pPreset
->getSetId());
1144 if (aIterator
== maTranstionMap
.end())
1146 auto pTransition
= std::make_unique
<TransitionEntry
>();
1147 const OUString aId
= weld::toId(pTransition
.get());
1149 pTransition
->msIcon
= u
"sd/cmd/transition-"_ustr
+ pPreset
->getSetId() + u
".png"_ustr
;
1150 pTransition
->msLabel
= aLabel
;
1151 pTransition
->mpPreset
= pPreset
;
1152 if (!pPreset
->getVariantLabel().isEmpty())
1153 pTransition
->mnVariants
.push_back(pPreset
->getVariantLabel());
1154 pTransition
->mnIndex
= nIndex
;
1157 mxTransitionsIconView
->append(aId
, pTransition
->msLabel
, pTransition
->msIcon
);
1158 maTranstionMap
.emplace(pPreset
->getSetId(), std::move(pTransition
));
1162 auto& pTransition
= aIterator
->second
;
1163 pTransition
->mnVariants
.push_back(pPreset
->getVariantLabel());
1167 mxTransitionsIconView
->set_size_request(0, 0);
1168 mxTransitionsIconView
->thaw();
1176 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */