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 <drawdoc.hxx>
31 #include <filedlg.hxx>
32 #include <strings.hrc>
33 #include <EventMultiplexer.hxx>
35 #include <comphelper/lok.hxx>
36 #include <sal/log.hxx>
37 #include <tools/debug.hxx>
38 #include <svx/gallery.hxx>
40 #include <vcl/stdtext.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/weld.hxx>
43 #include <tools/urlobj.hxx>
44 #include <slideshow.hxx>
45 #include <sdundogr.hxx>
46 #include <undoanim.hxx>
47 #include <optsitem.hxx>
49 #include <o3tl/safeint.hxx>
53 using namespace ::com::sun::star
;
55 using ::com::sun::star::uno::Reference
;
60 struct TransitionEffect
70 explicit TransitionEffect( const ::sd::TransitionPreset
& rPreset
) :
71 mnType( rPreset
.getTransition()),
72 mnSubType( rPreset
.getSubtype()),
73 mbDirection( rPreset
.getDirection()),
74 mnFadeColor( rPreset
.getFadeColor())
78 explicit TransitionEffect( const SdPage
& rPage
) :
79 mnType( rPage
.getTransitionType() ),
80 mnSubType( rPage
.getTransitionSubtype() ),
81 mbDirection( rPage
.getTransitionDirection() ),
82 mnFadeColor( rPage
.getTransitionFadeColor() )
86 mfDuration
= rPage
.getTransitionDuration();
87 mfTime
= rPage
.GetTime();
88 mePresChange
= rPage
.GetPresChange();
89 mbSoundOn
= rPage
.IsSoundOn();
90 maSound
= rPage
.GetSoundFile();
91 mbLoopSound
= rPage
.IsLoopSound();
92 mbStopSound
= rPage
.IsStopSound();
99 mePresChange
= PresChange::Manual
;
104 mbEffectAmbiguous
= false;
105 mbDurationAmbiguous
= false;
106 mbTimeAmbiguous
= false;
107 mbPresChangeAmbiguous
= false;
108 mbSoundAmbiguous
= false;
109 mbLoopSoundAmbiguous
= false;
112 void setAllAmbiguous()
114 mbEffectAmbiguous
= true;
115 mbDurationAmbiguous
= true;
116 mbTimeAmbiguous
= true;
117 mbPresChangeAmbiguous
= true;
118 mbSoundAmbiguous
= true;
119 mbLoopSoundAmbiguous
= true;
122 bool operator == ( const ::sd::TransitionPreset
& rPreset
) const
125 (mnType
== rPreset
.getTransition()) &&
126 (mnSubType
== rPreset
.getSubtype()) &&
127 (mbDirection
== rPreset
.getDirection()) &&
128 (mnFadeColor
== rPreset
.getFadeColor());
131 void applyTo( SdPage
& rOutPage
) const
133 if( ! mbEffectAmbiguous
)
135 rOutPage
.setTransitionType( mnType
);
136 rOutPage
.setTransitionSubtype( mnSubType
);
137 rOutPage
.setTransitionDirection( mbDirection
);
138 rOutPage
.setTransitionFadeColor( mnFadeColor
);
141 if( ! mbDurationAmbiguous
)
142 rOutPage
.setTransitionDuration( mfDuration
);
143 if( ! mbTimeAmbiguous
)
144 rOutPage
.SetTime( mfTime
);
145 if( ! mbPresChangeAmbiguous
)
146 rOutPage
.SetPresChange( mePresChange
);
147 if( ! mbSoundAmbiguous
)
151 rOutPage
.SetStopSound( true );
152 rOutPage
.SetSound( false );
156 rOutPage
.SetStopSound( false );
157 rOutPage
.SetSound( mbSoundOn
);
158 rOutPage
.SetSoundFile( maSound
);
161 if( ! mbLoopSoundAmbiguous
)
162 rOutPage
.SetLoopSound( mbLoopSound
);
165 void compareWith( const SdPage
& rPage
)
167 TransitionEffect
aOtherEffect( rPage
);
168 mbEffectAmbiguous
= mbEffectAmbiguous
|| aOtherEffect
.mbEffectAmbiguous
169 || (mnType
!= aOtherEffect
.mnType
)
170 || (mnSubType
!= aOtherEffect
.mnSubType
)
171 || (mbDirection
!= aOtherEffect
.mbDirection
)
172 || (mnFadeColor
!= aOtherEffect
.mnFadeColor
);
174 mbDurationAmbiguous
= mbDurationAmbiguous
|| aOtherEffect
.mbDurationAmbiguous
|| mfDuration
!= aOtherEffect
.mfDuration
;
175 mbTimeAmbiguous
= mbTimeAmbiguous
|| aOtherEffect
.mbTimeAmbiguous
|| mfTime
!= aOtherEffect
.mfTime
;
176 mbPresChangeAmbiguous
= mbPresChangeAmbiguous
|| aOtherEffect
.mbPresChangeAmbiguous
|| mePresChange
!= aOtherEffect
.mePresChange
;
177 mbSoundAmbiguous
= mbSoundAmbiguous
|| aOtherEffect
.mbSoundAmbiguous
|| mbSoundOn
!= aOtherEffect
.mbSoundOn
;
179 // Weird leftover isolated expression with no effect, introduced in 2007 in
180 // CWS impress122. Ifdeffed out to avoid compiler warning, kept here in case
181 // somebody who understands this code notices and understands what the
182 // "right" thing to do might be.
183 (!mbStopSound
&& !aOtherEffect
.mbStopSound
&& maSound
!= aOtherEffect
.maSound
) || (mbStopSound
!= aOtherEffect
.mbStopSound
);
185 mbLoopSoundAmbiguous
= mbLoopSoundAmbiguous
|| aOtherEffect
.mbLoopSoundAmbiguous
|| mbLoopSound
!= aOtherEffect
.mbLoopSound
;
192 sal_Int32 mnFadeColor
;
197 PresChange mePresChange
;
203 bool mbEffectAmbiguous
;
204 bool mbDurationAmbiguous
;
205 bool mbTimeAmbiguous
;
206 bool mbPresChangeAmbiguous
;
207 bool mbSoundAmbiguous
;
208 bool mbLoopSoundAmbiguous
;
211 } // namespace sd::impl
213 // Local Helper Functions
217 void lcl_ApplyToPages(
218 const ::sd::slidesorter::SharedPageSelection
& rpPages
,
219 const ::sd::impl::TransitionEffect
& rEffect
)
221 for( const auto& rpPage
: *rpPages
)
223 rEffect
.applyTo( *rpPage
);
227 void lcl_CreateUndoForPages(
228 const ::sd::slidesorter::SharedPageSelection
& rpPages
,
229 ::sd::ViewShellBase
const & rBase
)
231 ::sd::DrawDocShell
* pDocSh
= rBase
.GetDocShell();
234 SfxUndoManager
* pManager
= pDocSh
->GetUndoManager();
237 SdDrawDocument
* pDoc
= pDocSh
->GetDoc();
241 OUString
aComment( SdResId(STR_UNDO_SLIDE_PARAMS
) );
242 pManager
->EnterListAction(aComment
, aComment
, 0, rBase
.GetViewShellId());
243 std::unique_ptr
<SdUndoGroup
> pUndoGroup(new SdUndoGroup( pDoc
));
244 pUndoGroup
->SetComment( aComment
);
246 for( const auto& rpPage
: *rpPages
)
248 pUndoGroup
->AddAction( new sd::UndoTransition( pDoc
, rpPage
) );
251 pManager
->AddUndoAction( std::move(pUndoGroup
) );
252 pManager
->LeaveListAction();
255 struct lcl_EqualsSoundFileName
257 explicit lcl_EqualsSoundFileName( OUString aStr
) :
258 maStr(std::move( aStr
))
261 bool operator() ( const OUString
& rStr
) const
263 // note: formerly this was a case insensitive search for all
264 // platforms. It seems more sensible to do this platform-dependent
265 INetURLObject
aURL(rStr
);
267 return maStr
.equalsIgnoreAsciiCase( aURL
.GetBase() );
269 return maStr
== aURL
.GetBase();
277 // returns -1 if no object was found
278 bool lcl_findSoundInList( const ::std::vector
< OUString
> & rSoundList
,
279 std::u16string_view rFileName
,
280 ::std::vector
< OUString
>::size_type
& rOutPosition
)
282 INetURLObject
aURL(rFileName
);
283 ::std::vector
< OUString
>::const_iterator aIt
=
284 ::std::find_if( rSoundList
.begin(), rSoundList
.end(),
285 lcl_EqualsSoundFileName( aURL
.GetBase()));
286 if( aIt
!= rSoundList
.end())
288 rOutPosition
= ::std::distance( rSoundList
.begin(), aIt
);
295 OUString
lcl_getSoundFileURL(
296 const ::std::vector
< OUString
> & rSoundList
,
297 const weld::ComboBox
& rListBox
)
299 sal_Int32 nPos
= rListBox
.get_active();
300 // the first three entries are no actual sounds
303 DBG_ASSERT( static_cast<sal_uInt32
>(rListBox
.get_count() - 3) == rSoundList
.size(),
304 "Sound list-box is not synchronized to sound list" );
306 if( rSoundList
.size() > o3tl::make_unsigned(nPos
) )
307 return rSoundList
[ nPos
];
313 struct lcl_AppendSoundToListBox
315 explicit lcl_AppendSoundToListBox(weld::ComboBox
& rListBox
)
316 : mrListBox( rListBox
)
319 void operator() ( std::u16string_view rString
) const
321 INetURLObject
aURL( rString
);
322 mrListBox
.append_text( aURL
.GetBase() );
326 weld::ComboBox
& mrListBox
;
329 void lcl_FillSoundListBox(
330 const ::std::vector
< OUString
> & rSoundList
,
331 weld::ComboBox
& rOutListBox
)
333 sal_Int32 nCount
= rOutListBox
.get_count();
335 // keep first three entries
336 for( sal_Int32 i
=nCount
- 1; i
>=3; --i
)
337 rOutListBox
.remove( i
);
339 ::std::for_each( rSoundList
.begin(), rSoundList
.end(),
340 lcl_AppendSoundToListBox( rOutListBox
));
343 /// Returns an offset into the list of transition presets
344 size_t getPresetOffset( const sd::impl::TransitionEffect
&rEffect
)
346 const sd::TransitionPresetList
& rPresetList
=
347 sd::TransitionPreset::getTransitionPresetList();
350 for( const auto& aIt
: rPresetList
)
352 if( rEffect
.operator==( *aIt
))
359 } // anonymous namespace
364 class TransitionPane
: public ValueSet
367 explicit TransitionPane(std::unique_ptr
<weld::ScrolledWindow
> pScrolledWindow
)
368 : ValueSet(std::move(pScrolledWindow
))
374 GetScrollBar()->set_vpolicy(VclPolicyType::AUTOMATIC
);
375 RecalculateItemSizes();
378 virtual void SetDrawingArea(weld::DrawingArea
* pDrawingArea
) override
380 Size aSize
= pDrawingArea
->get_ref_device().LogicToPixel(Size(70, 88), MapMode(MapUnit::MapAppFont
));
381 pDrawingArea
->set_size_request(aSize
.Width(), aSize
.Height());
382 ValueSet::SetDrawingArea(pDrawingArea
);
383 SetOutputSizePixel(aSize
);
385 SetStyle(GetStyle() | WB_ITEMBORDER
| WB_FLATVALUESET
| WB_VSCROLL
);
386 EnableFullItemMode( false );
391 // SlideTransitionPane
392 SlideTransitionPane::SlideTransitionPane(
393 weld::Widget
* pParent
,
394 ViewShellBase
& rBase
) :
395 PanelLayout( pParent
, "SlideTransitionsPanel", "modules/simpress/ui/slidetransitionspanel.ui" ),
397 mpDrawDoc( rBase
.GetDocShell() ? rBase
.GetDocShell()->GetDoc() : nullptr ),
398 mbHasSelection( false ),
399 mbUpdatingControls( false ),
400 mbIsMainViewChangePending( false ),
401 maLateInitTimer("sd SlideTransitionPane maLateInitTimer")
403 Initialize(mpDrawDoc
);
406 css::ui::LayoutSize
SlideTransitionPane::GetHeightForWidth(const sal_Int32
/*nWidth*/)
408 sal_Int32 nMinimumHeight
= get_preferred_size().Height();
409 return css::ui::LayoutSize(nMinimumHeight
, -1, nMinimumHeight
);
412 constexpr sal_uInt16 nNoneId
= std::numeric_limits
<sal_uInt16
>::max();
414 void SlideTransitionPane::Initialize(SdDrawDocument
* pDoc
)
416 mxLB_VARIANT
= m_xBuilder
->weld_combo_box("variant_list");
417 mxCBX_duration
= m_xBuilder
->weld_metric_spin_button("transition_duration", FieldUnit::SECOND
);
418 mxFT_SOUND
= m_xBuilder
->weld_label("sound_label");
419 mxLB_SOUND
= m_xBuilder
->weld_combo_box("sound_list");
420 mxCB_LOOP_SOUND
= m_xBuilder
->weld_check_button("loop_sound");
421 mxRB_ADVANCE_ON_MOUSE
= m_xBuilder
->weld_radio_button("rb_mouse_click");
422 mxRB_ADVANCE_AUTO
= m_xBuilder
->weld_radio_button("rb_auto_after");
423 mxMF_ADVANCE_AUTO_AFTER
= m_xBuilder
->weld_metric_spin_button("auto_after_value", FieldUnit::SECOND
);
424 mxPB_APPLY_TO_ALL
= m_xBuilder
->weld_button("apply_to_all");
425 mxPB_PLAY
= m_xBuilder
->weld_button("play");
426 mxCB_AUTO_PREVIEW
= m_xBuilder
->weld_check_button("auto_preview");
428 auto nMax
= mxMF_ADVANCE_AUTO_AFTER
->get_max(FieldUnit::SECOND
);
429 mxMF_ADVANCE_AUTO_AFTER
->set_max(99, FieldUnit::SECOND
);
430 int nWidthChars
= mxMF_ADVANCE_AUTO_AFTER
->get_width_chars();
431 mxMF_ADVANCE_AUTO_AFTER
->set_max(nMax
, FieldUnit::SECOND
);
432 mxMF_ADVANCE_AUTO_AFTER
->set_width_chars(nWidthChars
);
433 mxCBX_duration
->set_width_chars(nWidthChars
);
435 mxVS_TRANSITION_ICONS
.reset(new TransitionPane(m_xBuilder
->weld_scrolled_window("transitions_iconswin", true)));
436 mxVS_TRANSITION_ICONSWin
.reset(new weld::CustomWeld(*m_xBuilder
, "transitions_icons", *mxVS_TRANSITION_ICONS
));
439 mxModel
.set( pDoc
->getUnoModel(), uno::UNO_QUERY
);
440 // TODO: get correct view
442 mxView
.set( mxModel
->getCurrentController(), uno::UNO_QUERY
);
444 // dummy list box of slide transitions for startup.
445 mxVS_TRANSITION_ICONS
->InsertItem(
446 nNoneId
, Image( StockImage::Yes
, "sd/cmd/transition-none.png" ),
447 SdResId( STR_SLIDETRANSITION_NONE
),
448 VALUESET_APPEND
, /* show legend */ true );
449 mxVS_TRANSITION_ICONS
->Recalculate();
452 mxCB_AUTO_PREVIEW
->set_active(true); // automatic preview on
454 // update control states before adding handlers
458 mxPB_APPLY_TO_ALL
->connect_clicked( LINK( this, SlideTransitionPane
, ApplyToAllButtonClicked
));
459 mxPB_PLAY
->connect_clicked( LINK( this, SlideTransitionPane
, PlayButtonClicked
));
461 mxVS_TRANSITION_ICONS
->SetSelectHdl( LINK( this, SlideTransitionPane
, TransitionSelected
));
463 mxLB_VARIANT
->connect_changed( LINK( this, SlideTransitionPane
, VariantListBoxSelected
));
464 mxCBX_duration
->connect_value_changed(LINK( this, SlideTransitionPane
, DurationModifiedHdl
));
465 mxCBX_duration
->connect_focus_out(LINK( this, SlideTransitionPane
, DurationLoseFocusHdl
));
466 mxLB_SOUND
->connect_changed( LINK( this, SlideTransitionPane
, SoundListBoxSelected
));
467 mxCB_LOOP_SOUND
->connect_toggled( LINK( this, SlideTransitionPane
, LoopSoundBoxChecked
));
469 mxRB_ADVANCE_ON_MOUSE
->connect_toggled( LINK( this, SlideTransitionPane
, AdvanceSlideRadioButtonToggled
));
470 mxRB_ADVANCE_AUTO
->connect_toggled( LINK( this, SlideTransitionPane
, AdvanceSlideRadioButtonToggled
));
471 mxMF_ADVANCE_AUTO_AFTER
->connect_value_changed( LINK( this, SlideTransitionPane
, AdvanceTimeModified
));
472 mxCB_AUTO_PREVIEW
->connect_toggled( LINK( this, SlideTransitionPane
, AutoPreviewClicked
));
475 maLateInitTimer
.SetTimeout(200);
476 maLateInitTimer
.SetInvokeHandler(LINK(this, SlideTransitionPane
, LateInitCallback
));
477 maLateInitTimer
.Start();
480 SlideTransitionPane::~SlideTransitionPane()
482 maLateInitTimer
.Stop();
484 mxVS_TRANSITION_ICONSWin
.reset();
485 mxVS_TRANSITION_ICONS
.reset();
486 mxLB_VARIANT
.reset();
487 mxCBX_duration
.reset();
490 mxCB_LOOP_SOUND
.reset();
491 mxRB_ADVANCE_ON_MOUSE
.reset();
492 mxRB_ADVANCE_AUTO
.reset();
493 mxMF_ADVANCE_AUTO_AFTER
.reset();
494 mxPB_APPLY_TO_ALL
.reset();
496 mxCB_AUTO_PREVIEW
.reset();
499 void SlideTransitionPane::onSelectionChanged()
504 void SlideTransitionPane::onChangeCurrentPage()
509 ::sd::slidesorter::SharedPageSelection
SlideTransitionPane::getSelectedPages() const
511 ::sd::slidesorter::SlideSorterViewShell
* pSlideSorterViewShell
512 = ::sd::slidesorter::SlideSorterViewShell::GetSlideSorter(mrBase
);
513 std::shared_ptr
<sd::slidesorter::SlideSorterViewShell::PageSelection
> pSelection
;
515 if( pSlideSorterViewShell
)
517 pSelection
= pSlideSorterViewShell
->GetPageSelection();
521 pSelection
= std::make_shared
<sd::slidesorter::SlideSorterViewShell::PageSelection
>();
524 SdPage
* pPage
= SdPage::getImplementation( mxView
->getCurrentPage() );
526 pSelection
->push_back(pPage
);
533 void SlideTransitionPane::updateControls()
535 ::sd::slidesorter::SharedPageSelection
pSelectedPages(getSelectedPages());
536 if( pSelectedPages
->empty())
538 mbHasSelection
= false;
541 mbHasSelection
= true;
543 DBG_ASSERT( ! mbUpdatingControls
, "Multiple Control Updates" );
544 mbUpdatingControls
= true;
546 // get model data for first page
547 SdPage
* pFirstPage
= pSelectedPages
->front();
548 DBG_ASSERT( pFirstPage
, "Invalid Page" );
550 impl::TransitionEffect
aEffect( *pFirstPage
);
552 // merge with other pages
554 // start with second page (note aIt != aEndIt, because ! aSelectedPages.empty())
555 for( const auto& rpPage
: *pSelectedPages
)
558 aEffect
.compareWith( *rpPage
);
561 // detect current slide effect
562 if( aEffect
.mbEffectAmbiguous
)
564 SAL_WARN( "sd.transitions", "Unusual, ambiguous transition effect" );
565 mxVS_TRANSITION_ICONS
->SelectItem(nNoneId
);
569 // ToDo: That 0 is "no transition" is documented nowhere except in the
571 if( aEffect
.mnType
== 0 )
572 mxVS_TRANSITION_ICONS
->SelectItem(nNoneId
);
574 updateVariants( getPresetOffset( aEffect
) );
577 if( aEffect
.mbDurationAmbiguous
)
579 mxCBX_duration
->set_text("");
580 //TODO mxCBX_duration->SetNoSelection();
584 mxCBX_duration
->set_value( (aEffect
.mfDuration
)*100.0, FieldUnit::SECOND
);
587 if( aEffect
.mbSoundAmbiguous
)
589 mxLB_SOUND
->set_active(-1);
590 maCurrentSoundFile
.clear();
594 maCurrentSoundFile
.clear();
595 if( aEffect
.mbStopSound
)
597 mxLB_SOUND
->set_active( 1 );
599 else if( aEffect
.mbSoundOn
&& !aEffect
.maSound
.isEmpty() )
601 std::vector
<OUString
>::size_type nPos
= 0;
602 if( lcl_findSoundInList( maSoundList
, aEffect
.maSound
, nPos
))
604 mxLB_SOUND
->set_active( nPos
+ 3 );
605 maCurrentSoundFile
= aEffect
.maSound
;
610 mxLB_SOUND
->set_active( 0 );
614 if( aEffect
.mbLoopSoundAmbiguous
)
616 mxCB_LOOP_SOUND
->set_state(TRISTATE_INDET
);
620 mxCB_LOOP_SOUND
->set_active(aEffect
.mbLoopSound
);
623 if( aEffect
.mbPresChangeAmbiguous
)
625 mxRB_ADVANCE_ON_MOUSE
->set_active( false );
626 mxRB_ADVANCE_AUTO
->set_active( false );
630 mxRB_ADVANCE_ON_MOUSE
->set_active( aEffect
.mePresChange
== PresChange::Manual
);
631 mxRB_ADVANCE_AUTO
->set_active( aEffect
.mePresChange
== PresChange::Auto
);
632 mxMF_ADVANCE_AUTO_AFTER
->set_value(aEffect
.mfTime
* 100.0, FieldUnit::SECOND
);
635 if (comphelper::LibreOfficeKit::isActive())
638 mxCB_AUTO_PREVIEW
->set_active(false);
639 mxCB_AUTO_PREVIEW
->hide();
642 mxCB_LOOP_SOUND
->hide();
646 SdOptions
* pOptions
= SD_MOD()->GetSdOptions(DocumentType::Impress
);
647 mxCB_AUTO_PREVIEW
->set_active( pOptions
->IsPreviewTransitions() );
650 mbUpdatingControls
= false;
652 updateControlState();
655 void SlideTransitionPane::updateControlState()
657 mxVS_TRANSITION_ICONSWin
->set_sensitive( mbHasSelection
);
658 mxLB_VARIANT
->set_sensitive( mbHasSelection
&& mxLB_VARIANT
->get_count() > 0 );
659 mxCBX_duration
->set_sensitive( mbHasSelection
);
660 mxLB_SOUND
->set_sensitive( mbHasSelection
);
661 mxCB_LOOP_SOUND
->set_sensitive( mbHasSelection
&& (mxLB_SOUND
->get_active() > 2));
662 mxRB_ADVANCE_ON_MOUSE
->set_sensitive( mbHasSelection
);
663 mxRB_ADVANCE_AUTO
->set_sensitive( mbHasSelection
);
664 mxMF_ADVANCE_AUTO_AFTER
->set_sensitive( mbHasSelection
&& mxRB_ADVANCE_AUTO
->get_active());
666 mxPB_APPLY_TO_ALL
->set_sensitive( mbHasSelection
);
667 mxPB_PLAY
->set_sensitive( mbHasSelection
);
668 mxCB_AUTO_PREVIEW
->set_sensitive( mbHasSelection
);
671 void SlideTransitionPane::updateSoundList()
675 GalleryExplorer::FillObjList( GALLERY_THEME_SOUNDS
, maSoundList
);
676 GalleryExplorer::FillObjList( GALLERY_THEME_USERSOUNDS
, maSoundList
);
678 lcl_FillSoundListBox( maSoundList
, *mxLB_SOUND
);
681 void SlideTransitionPane::openSoundFileDialog()
683 if( ! mxLB_SOUND
->get_sensitive())
686 weld::Window
* pDialogParent(GetFrameWeld());
687 SdOpenSoundFileDialog
aFileDialog(pDialogParent
);
689 DBG_ASSERT( mxLB_SOUND
->get_active() == 2,
690 "Dialog should only open when \"Other sound\" is selected" );
692 bool bValidSoundFile( false );
693 bool bQuitLoop( false );
695 while( ! bQuitLoop
&&
696 aFileDialog
.Execute() == ERRCODE_NONE
)
698 OUString aFile
= aFileDialog
.GetPath();
699 std::vector
<OUString
>::size_type nPos
= 0;
700 bValidSoundFile
= lcl_findSoundInList( maSoundList
, aFile
, nPos
);
702 if( bValidSoundFile
)
706 else // not in sound list
708 // try to insert into gallery
709 if( GalleryExplorer::InsertURL( GALLERY_THEME_USERSOUNDS
, aFile
) )
712 bValidSoundFile
= lcl_findSoundInList( maSoundList
, aFile
, nPos
);
713 DBG_ASSERT( bValidSoundFile
, "Adding sound to gallery failed" );
719 OUString
aStrWarning(SdResId(STR_WARNING_NOSOUNDFILE
));
720 aStrWarning
= aStrWarning
.replaceFirst("%", aFile
);
721 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(pDialogParent
,
722 VclMessageType::Warning
, VclButtonsType::NONE
,
724 xWarn
->add_button(GetStandardText(StandardButtonType::Retry
), RET_RETRY
);
725 xWarn
->add_button(GetStandardText(StandardButtonType::Cancel
), RET_CANCEL
);
726 bQuitLoop
= (xWarn
->run() != RET_RETRY
);
728 bValidSoundFile
= false;
732 if( bValidSoundFile
)
733 // skip first three entries in list
734 mxLB_SOUND
->set_active( nPos
+ 3 );
737 if( bValidSoundFile
)
740 if( !maCurrentSoundFile
.isEmpty() )
742 std::vector
<OUString
>::size_type nPos
= 0;
743 if( lcl_findSoundInList( maSoundList
, maCurrentSoundFile
, nPos
))
744 mxLB_SOUND
->set_active( nPos
+ 3 );
746 mxLB_SOUND
->set_active( 0 ); // NONE
749 mxLB_SOUND
->set_active( 0 ); // NONE
752 impl::TransitionEffect
SlideTransitionPane::getTransitionEffectFromControls() const
754 impl::TransitionEffect aResult
;
755 aResult
.setAllAmbiguous();
757 bool bNoneSelected
= mxVS_TRANSITION_ICONS
->IsNoSelection() || mxVS_TRANSITION_ICONS
->GetSelectedItemId() == nNoneId
;
759 // check first (aResult might be overwritten)
760 if( mxVS_TRANSITION_ICONSWin
->get_sensitive() &&
762 mxVS_TRANSITION_ICONS
->GetSelectedItemId() > 0 )
764 const sd::TransitionPresetList
& rPresetList
= sd::TransitionPreset::getTransitionPresetList();
765 auto aSelected
= rPresetList
.begin();
766 std::advance( aSelected
, mxVS_TRANSITION_ICONS
->GetSelectedItemId() - 1);
768 if (mxLB_VARIANT
->get_active() == -1)
770 // Transition with just one effect.
771 aResult
= impl::TransitionEffect( **aSelected
);
772 aResult
.setAllAmbiguous();
778 for( const auto& aIter
: rPresetList
)
780 if( aIter
->getSetId() == (*aSelected
)->getSetId() )
782 if( mxLB_VARIANT
->get_active() == nVariant
)
784 aResult
= impl::TransitionEffect( *aIter
);
785 aResult
.setAllAmbiguous();
800 aResult
.mbEffectAmbiguous
= false;
802 else if (bNoneSelected
)
804 aResult
.mbEffectAmbiguous
= false;
809 if( mxCBX_duration
->get_sensitive() && (!(mxCBX_duration
->get_text()).isEmpty()) )
811 aResult
.mfDuration
= static_cast<double>(mxCBX_duration
->get_value(FieldUnit::SECOND
))/100.0;
812 aResult
.mbDurationAmbiguous
= false;
815 // slide-advance mode
816 if( mxRB_ADVANCE_ON_MOUSE
->get_sensitive() && mxRB_ADVANCE_AUTO
->get_sensitive() &&
817 (mxRB_ADVANCE_ON_MOUSE
->get_active() || mxRB_ADVANCE_AUTO
->get_active()))
819 if( mxRB_ADVANCE_ON_MOUSE
->get_active())
820 aResult
.mePresChange
= PresChange::Manual
;
823 aResult
.mePresChange
= PresChange::Auto
;
824 if( mxMF_ADVANCE_AUTO_AFTER
->get_sensitive())
826 aResult
.mfTime
= static_cast<double>(mxMF_ADVANCE_AUTO_AFTER
->get_value(FieldUnit::SECOND
) ) / 100.0 ;
827 aResult
.mbTimeAmbiguous
= false;
831 aResult
.mbPresChangeAmbiguous
= false;
835 if( mxLB_SOUND
->get_sensitive())
837 maCurrentSoundFile
.clear();
838 sal_Int32 nPos
= mxLB_SOUND
->get_active();
841 aResult
.mbStopSound
= nPos
== 1;
842 aResult
.mbSoundOn
= nPos
> 1;
843 if( aResult
.mbStopSound
)
845 aResult
.maSound
.clear();
846 aResult
.mbSoundAmbiguous
= false;
850 aResult
.maSound
= lcl_getSoundFileURL(maSoundList
, *mxLB_SOUND
);
851 aResult
.mbSoundAmbiguous
= false;
852 maCurrentSoundFile
= aResult
.maSound
;
858 if( mxCB_LOOP_SOUND
->get_sensitive() )
860 aResult
.mbLoopSound
= mxCB_LOOP_SOUND
->get_active();
861 aResult
.mbLoopSoundAmbiguous
= false;
867 void SlideTransitionPane::applyToSelectedPages(bool bPreview
= true)
869 if( mbUpdatingControls
)
872 vcl::Window
*pFocusWindow
= Application::GetFocusWindow();
874 ::sd::slidesorter::SharedPageSelection
pSelectedPages( getSelectedPages());
875 impl::TransitionEffect aEffect
= getTransitionEffectFromControls();
876 if( ! pSelectedPages
->empty())
878 lcl_CreateUndoForPages( pSelectedPages
, mrBase
);
879 lcl_ApplyToPages( pSelectedPages
, aEffect
);
880 mrBase
.GetDocShell()->SetModified();
882 if( mxCB_AUTO_PREVIEW
->get_sensitive() &&
883 mxCB_AUTO_PREVIEW
->get_active() && bPreview
)
885 if (aEffect
.mnType
) // mnType = 0 denotes no transition
887 else if( mxView
.is() )
888 SlideShow::Stop( mrBase
);
892 pFocusWindow
->GrabFocus();
895 void SlideTransitionPane::playCurrentEffect()
900 Reference
< css::animations::XAnimationNode
> xNode
;
901 SlideShow::StartPreview( mrBase
, mxView
->getCurrentPage(), xNode
);
905 void SlideTransitionPane::addListener()
907 Link
<tools::EventMultiplexerEvent
&,void> aLink( LINK(this,SlideTransitionPane
,EventMultiplexerListener
) );
908 mrBase
.GetEventMultiplexer()->AddEventListener( aLink
);
911 void SlideTransitionPane::removeListener()
913 Link
<tools::EventMultiplexerEvent
&,void> aLink( LINK(this,SlideTransitionPane
,EventMultiplexerListener
) );
914 mrBase
.GetEventMultiplexer()->RemoveEventListener( aLink
);
917 IMPL_LINK(SlideTransitionPane
,EventMultiplexerListener
,
918 tools::EventMultiplexerEvent
&, rEvent
, void)
920 switch (rEvent
.meEventId
)
922 case EventMultiplexerEventId::EditViewSelection
:
923 onSelectionChanged();
926 case EventMultiplexerEventId::CurrentPageChanged
:
927 case EventMultiplexerEventId::SlideSortedSelection
:
928 onChangeCurrentPage();
931 case EventMultiplexerEventId::MainViewRemoved
:
933 onSelectionChanged();
934 onChangeCurrentPage();
937 case EventMultiplexerEventId::MainViewAdded
:
938 mbIsMainViewChangePending
= true;
941 case EventMultiplexerEventId::ConfigurationUpdated
:
942 if (mbIsMainViewChangePending
)
944 mbIsMainViewChangePending
= false;
946 // At this moment the controller may not yet been set at
947 // model or ViewShellBase. Take it from the view shell
948 // passed with the event.
949 if (mrBase
.GetMainViewShell() != nullptr)
951 mxView
.set(mrBase
.GetController(), css::uno::UNO_QUERY
);
952 onSelectionChanged();
953 onChangeCurrentPage();
959 if (rEvent
.meEventId
!= EventMultiplexerEventId::Disposing
)
961 onSelectionChanged();
962 onChangeCurrentPage();
968 IMPL_LINK_NOARG(SlideTransitionPane
, ApplyToAllButtonClicked
, weld::Button
&, void)
970 DBG_ASSERT( mpDrawDoc
, "Invalid Draw Document!" );
974 ::sd::slidesorter::SharedPageSelection pPages
=
975 std::make_shared
<::sd::slidesorter::SlideSorterViewShell::PageSelection
>();
977 sal_uInt16 nPageCount
= mpDrawDoc
->GetSdPageCount( PageKind::Standard
);
978 pPages
->reserve( nPageCount
);
979 for( sal_uInt16 i
=0; i
<nPageCount
; ++i
)
981 SdPage
* pPage
= mpDrawDoc
->GetSdPage( i
, PageKind::Standard
);
983 pPages
->push_back( pPage
);
986 if( ! pPages
->empty())
988 lcl_CreateUndoForPages( pPages
, mrBase
);
989 lcl_ApplyToPages( pPages
, getTransitionEffectFromControls() );
993 IMPL_LINK_NOARG(SlideTransitionPane
, PlayButtonClicked
, weld::Button
&, void)
998 IMPL_LINK_NOARG(SlideTransitionPane
, TransitionSelected
, ValueSet
*, void)
1000 updateVariants( mxVS_TRANSITION_ICONS
->GetSelectedItemId() - 1 );
1001 applyToSelectedPages();
1004 /// we use an integer offset into the list of transition presets
1005 void SlideTransitionPane::updateVariants( size_t nPresetOffset
)
1007 const sd::TransitionPresetList
& rPresetList
= sd::TransitionPreset::getTransitionPresetList();
1008 mxLB_VARIANT
->clear();
1009 mxVS_TRANSITION_ICONS
->SelectItem(nNoneId
);
1011 if( nPresetOffset
>= rPresetList
.size() )
1013 mxLB_VARIANT
->set_sensitive( false );
1017 auto pFound
= rPresetList
.begin();
1018 std::advance( pFound
, nPresetOffset
);
1020 // Fill in the variant listbox
1021 size_t nFirstItem
= 0, nItem
= 1;
1022 for( const auto& aIt
: rPresetList
)
1024 if( aIt
->getSetId() == (*pFound
)->getSetId() )
1028 if( !aIt
->getVariantLabel().isEmpty() )
1030 mxLB_VARIANT
->append_text( aIt
->getVariantLabel() );
1031 if( *pFound
== aIt
)
1032 mxLB_VARIANT
->set_active( mxLB_VARIANT
->get_count()-1 );
1038 if( mxLB_VARIANT
->get_count() == 0 )
1039 mxLB_VARIANT
->set_sensitive( false );
1041 mxLB_VARIANT
->set_sensitive(true);
1043 // item has the id of the first transition from this set.
1044 mxVS_TRANSITION_ICONS
->SelectItem( nFirstItem
);
1048 IMPL_LINK_NOARG(SlideTransitionPane
, AdvanceSlideRadioButtonToggled
, weld::Toggleable
&, void)
1050 updateControlState();
1051 applyToSelectedPages(false);
1054 IMPL_LINK_NOARG(SlideTransitionPane
, AdvanceTimeModified
, weld::MetricSpinButton
&, void)
1056 applyToSelectedPages(false);
1059 IMPL_LINK_NOARG(SlideTransitionPane
, VariantListBoxSelected
, weld::ComboBox
&, void)
1061 applyToSelectedPages();
1064 IMPL_LINK_NOARG(SlideTransitionPane
, DurationModifiedHdl
, weld::MetricSpinButton
&, void)
1066 double duration_value
= static_cast<double>(mxCBX_duration
->get_value(FieldUnit::SECOND
));
1067 if (duration_value
<= 0.0)
1068 mxCBX_duration
->set_value(0, FieldUnit::SECOND
);
1070 mxCBX_duration
->set_value(duration_value
, FieldUnit::SECOND
);
1072 applyToSelectedPages();
1075 IMPL_LINK_NOARG(SlideTransitionPane
, DurationLoseFocusHdl
, weld::Widget
&, void)
1077 applyToSelectedPages();
1080 IMPL_LINK_NOARG(SlideTransitionPane
, SoundListBoxSelected
, weld::ComboBox
&, void)
1082 sal_Int32 nPos
= mxLB_SOUND
->get_active();
1086 openSoundFileDialog();
1088 updateControlState();
1089 applyToSelectedPages();
1092 IMPL_LINK_NOARG(SlideTransitionPane
, LoopSoundBoxChecked
, weld::Toggleable
&, void)
1094 applyToSelectedPages();
1097 IMPL_LINK_NOARG(SlideTransitionPane
, AutoPreviewClicked
, weld::Toggleable
&, void)
1099 SdOptions
* pOptions
= SD_MOD()->GetSdOptions(DocumentType::Impress
);
1100 pOptions
->SetPreviewTransitions( mxCB_AUTO_PREVIEW
->get_active() );
1103 IMPL_LINK_NOARG(SlideTransitionPane
, LateInitCallback
, Timer
*, void)
1105 const TransitionPresetList
& rPresetList
= TransitionPreset::getTransitionPresetList();
1107 size_t nPresetOffset
= 0;
1108 for( const TransitionPresetPtr
& pPreset
: rPresetList
)
1110 const OUString
sLabel( pPreset
->getSetLabel() );
1111 if( !sLabel
.isEmpty() )
1113 if( m_aNumVariants
.find( pPreset
->getSetId() ) == m_aNumVariants
.end() )
1115 OUString
sImageName("sd/cmd/transition-" + pPreset
->getSetId() + ".png");
1116 BitmapEx
aIcon( sImageName
);
1117 if ( aIcon
.IsEmpty() ) // need a fallback
1118 sImageName
= "sd/cmd/transition-none.png";
1120 mxVS_TRANSITION_ICONS
->InsertItem(
1121 nPresetOffset
+ 1, Image(StockImage::Yes
, sImageName
), sLabel
,
1122 VALUESET_APPEND
, /* show legend */ true );
1124 m_aNumVariants
[ pPreset
->getSetId() ] = 1;
1128 m_aNumVariants
[ pPreset
->getSetId() ]++;
1133 mxVS_TRANSITION_ICONS
->Recalculate();
1135 SAL_INFO( "sd.transitions", "Item transition offsets in ValueSet:");
1136 for( size_t i
= 0; i
< mxVS_TRANSITION_ICONS
->GetItemCount(); ++i
)
1137 SAL_INFO( "sd.transitions", i
<< ":" << mxVS_TRANSITION_ICONS
->GetItemId( i
) );
1140 SAL_INFO( "sd.transitions", "Transition presets by offsets:");
1141 for( const auto& aIter
: rPresetList
)
1143 SAL_INFO( "sd.transitions", nPresetOffset
++ << " " <<
1144 aIter
->getPresetId() << ": " << aIter
->getSetId() );
1153 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */