Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/sd/source/ui/animations/SlideTransitionPane.cxx
Line
Count
Source (jump to first uncovered line)
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/drawing/XDrawView.hpp>
21
#include <SlideTransitionPane.hxx>
22
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>
30
#include <sdmod.hxx>
31
#include <sdpage.hxx>
32
#include <filedlg.hxx>
33
#include <strings.hrc>
34
#include <EventMultiplexer.hxx>
35
36
#include <comphelper/lok.hxx>
37
#include <sal/log.hxx>
38
#include <tools/debug.hxx>
39
#include <svx/gallery.hxx>
40
#include <utility>
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>
49
50
#include <o3tl/safeint.hxx>
51
52
#include <algorithm>
53
54
using namespace ::com::sun::star;
55
56
using ::com::sun::star::uno::Reference;
57
58
59
namespace sd::impl
60
{
61
struct TransitionEffect
62
{
63
    TransitionEffect() :
64
0
            mnType( 0 ),
65
0
            mnSubType( 0 ),
66
0
            mbDirection( true ),
67
0
            mnFadeColor( 0 )
68
0
    {
69
0
        init();
70
0
    }
71
    explicit TransitionEffect( const ::sd::TransitionPreset & rPreset ) :
72
0
            mnType( rPreset.getTransition()),
73
0
            mnSubType( rPreset.getSubtype()),
74
0
            mbDirection( rPreset.getDirection()),
75
0
            mnFadeColor( rPreset.getFadeColor())
76
0
    {
77
0
        init();
78
0
    }
79
    explicit TransitionEffect( const SdPage & rPage ) :
80
0
            mnType( rPage.getTransitionType() ),
81
0
            mnSubType( rPage.getTransitionSubtype() ),
82
0
            mbDirection( rPage.getTransitionDirection() ),
83
0
            mnFadeColor( rPage.getTransitionFadeColor() )
84
0
    {
85
0
        init();
86
87
0
        mfDuration = rPage.getTransitionDuration();
88
0
        mfTime = rPage.GetTime();
89
0
        mePresChange = rPage.GetPresChange();
90
0
        mbSoundOn = rPage.IsSoundOn();
91
0
        maSound = rPage.GetSoundFile();
92
0
        mbLoopSound = rPage.IsLoopSound();
93
0
        mbStopSound = rPage.IsStopSound();
94
0
    }
95
96
    void init()
97
0
    {
98
0
        mfDuration = 2.0;
99
0
        mfTime = 0.0;
100
0
        mePresChange = PresChange::Manual;
101
0
        mbSoundOn = false;
102
0
        mbLoopSound = false;
103
0
        mbStopSound = false;
104
105
0
        mbEffectAmbiguous = false;
106
0
        mbDurationAmbiguous = false;
107
0
        mbTimeAmbiguous = false;
108
0
        mbPresChangeAmbiguous = false;
109
0
        mbSoundAmbiguous = false;
110
0
        mbLoopSoundAmbiguous = false;
111
0
    }
112
113
    void setAllAmbiguous()
114
0
    {
115
0
        mbEffectAmbiguous = true;
116
0
        mbDurationAmbiguous = true;
117
0
        mbTimeAmbiguous = true;
118
0
        mbPresChangeAmbiguous = true;
119
0
        mbSoundAmbiguous = true;
120
0
        mbLoopSoundAmbiguous = true;
121
0
    }
122
123
    bool operator == ( const ::sd::TransitionPreset & rPreset ) const
124
0
    {
125
0
        return
126
0
            (mnType == rPreset.getTransition()) &&
127
0
            (mnSubType == rPreset.getSubtype()) &&
128
0
            (mbDirection == rPreset.getDirection()) &&
129
0
            (mnFadeColor ==  rPreset.getFadeColor());
130
0
    }
131
132
    void applyTo( SdPage & rOutPage ) const
133
0
    {
134
0
        if( ! mbEffectAmbiguous )
135
0
        {
136
0
            rOutPage.setTransitionType( mnType );
137
0
            rOutPage.setTransitionSubtype( mnSubType );
138
0
            rOutPage.setTransitionDirection( mbDirection );
139
0
            rOutPage.setTransitionFadeColor( mnFadeColor );
140
0
        }
141
142
0
        if( ! mbDurationAmbiguous )
143
0
            rOutPage.setTransitionDuration( mfDuration );
144
0
        if( ! mbTimeAmbiguous )
145
0
            rOutPage.SetTime( mfTime );
146
0
        if( ! mbPresChangeAmbiguous )
147
0
            rOutPage.SetPresChange( mePresChange );
148
0
        if( ! mbSoundAmbiguous )
149
0
        {
150
0
            if( mbStopSound )
151
0
            {
152
0
                rOutPage.SetStopSound( true );
153
0
                rOutPage.SetSound( false );
154
0
            }
155
0
            else
156
0
            {
157
0
                rOutPage.SetStopSound( false );
158
0
                rOutPage.SetSound( mbSoundOn );
159
0
                rOutPage.SetSoundFile( maSound );
160
0
            }
161
0
        }
162
0
        if( ! mbLoopSoundAmbiguous )
163
0
            rOutPage.SetLoopSound( mbLoopSound );
164
0
    }
165
166
    void compareWith( const SdPage & rPage )
167
0
    {
168
0
        TransitionEffect aOtherEffect( rPage );
169
0
        mbEffectAmbiguous = mbEffectAmbiguous || aOtherEffect.mbEffectAmbiguous
170
0
                                              || (mnType != aOtherEffect.mnType)
171
0
                                              || (mnSubType != aOtherEffect.mnSubType)
172
0
                                              || (mbDirection != aOtherEffect.mbDirection)
173
0
                                              || (mnFadeColor != aOtherEffect.mnFadeColor);
174
175
0
        mbDurationAmbiguous = mbDurationAmbiguous || aOtherEffect.mbDurationAmbiguous || mfDuration != aOtherEffect.mfDuration;
176
0
        mbTimeAmbiguous = mbTimeAmbiguous || aOtherEffect.mbTimeAmbiguous || mfTime != aOtherEffect.mfTime;
177
0
        mbPresChangeAmbiguous = mbPresChangeAmbiguous || aOtherEffect.mbPresChangeAmbiguous || mePresChange != aOtherEffect.mePresChange;
178
0
        mbSoundAmbiguous = mbSoundAmbiguous || aOtherEffect.mbSoundAmbiguous || mbSoundOn != aOtherEffect.mbSoundOn;
179
#if 0
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);
185
#endif
186
0
        mbLoopSoundAmbiguous = mbLoopSoundAmbiguous || aOtherEffect.mbLoopSoundAmbiguous || mbLoopSound != aOtherEffect.mbLoopSound;
187
0
    }
188
189
    // effect
190
    sal_Int16 mnType;
191
    sal_Int16 mnSubType;
192
    bool  mbDirection;
193
    sal_Int32 mnFadeColor;
194
195
    // other settings
196
    double      mfDuration;
197
    double       mfTime;
198
    PresChange  mePresChange;
199
    bool        mbSoundOn;
200
    OUString    maSound;
201
    bool        mbLoopSound;
202
    bool        mbStopSound;
203
204
    bool mbEffectAmbiguous;
205
    bool mbDurationAmbiguous;
206
    bool mbTimeAmbiguous;
207
    bool mbPresChangeAmbiguous;
208
    bool mbSoundAmbiguous;
209
    bool mbLoopSoundAmbiguous;
210
};
211
212
} // namespace sd::impl
213
214
namespace sd
215
{
216
217
// Local Helper Functions
218
namespace
219
{
220
221
void lcl_ApplyToPages(
222
    const ::sd::slidesorter::SharedPageSelection& rpPages,
223
    const ::sd::impl::TransitionEffect & rEffect )
224
0
{
225
0
    for( const auto& rpPage : *rpPages )
226
0
    {
227
0
        rEffect.applyTo( *rpPage );
228
0
    }
229
0
}
230
231
void lcl_CreateUndoForPages(
232
    const ::sd::slidesorter::SharedPageSelection& rpPages,
233
    ::sd::ViewShellBase const & rBase )
234
0
{
235
0
    ::sd::DrawDocShell* pDocSh      = rBase.GetDocShell();
236
0
    if (!pDocSh)
237
0
        return;
238
0
    SfxUndoManager* pManager   = pDocSh->GetUndoManager();
239
0
    if (!pManager)
240
0
        return;
241
0
    SdDrawDocument* pDoc            = pDocSh->GetDoc();
242
0
    if (!pDoc)
243
0
        return;
244
245
0
    OUString aComment( SdResId(STR_UNDO_SLIDE_PARAMS) );
246
0
    pManager->EnterListAction(aComment, aComment, 0, rBase.GetViewShellId());
247
0
    std::unique_ptr<SdUndoGroup> pUndoGroup(new SdUndoGroup( *pDoc ));
248
0
    pUndoGroup->SetComment( aComment );
249
250
0
    for( const auto& rpPage : *rpPages )
251
0
    {
252
0
        pUndoGroup->AddAction( new sd::UndoTransition( *pDoc, rpPage ) );
253
0
    }
254
255
0
    pManager->AddUndoAction( std::move(pUndoGroup) );
256
0
    pManager->LeaveListAction();
257
0
}
258
259
struct lcl_EqualsSoundFileName
260
{
261
    explicit lcl_EqualsSoundFileName( OUString aStr ) :
262
0
            maStr(std::move( aStr ))
263
0
    {}
264
265
    bool operator() ( const OUString & rStr ) const
266
0
    {
267
        // note: formerly this was a case insensitive search for all
268
        // platforms. It seems more sensible to do this platform-dependent
269
0
        INetURLObject aURL(rStr);
270
#if defined(_WIN32)
271
        return maStr.equalsIgnoreAsciiCase( aURL.GetBase() );
272
#else
273
0
        return maStr == aURL.GetBase();
274
0
#endif
275
0
    }
276
277
private:
278
    OUString maStr;
279
};
280
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 )
285
0
{
286
0
    INetURLObject aURL(rFileName);
287
0
    ::std::vector< OUString >::const_iterator aIt =
288
0
          ::std::find_if( rSoundList.begin(), rSoundList.end(),
289
0
                          lcl_EqualsSoundFileName( aURL.GetBase()));
290
0
    if( aIt != rSoundList.end())
291
0
    {
292
0
        rOutPosition = ::std::distance( rSoundList.begin(), aIt );
293
0
        return true;
294
0
    }
295
296
0
    return false;
297
0
}
298
299
OUString lcl_getSoundFileURL(
300
    const ::std::vector< OUString > & rSoundList,
301
    const weld::ComboBox& rListBox )
302
0
{
303
0
    sal_Int32 nPos = rListBox.get_active();
304
    // the first three entries are no actual sounds
305
0
    if( nPos >= 3 )
306
0
    {
307
0
        DBG_ASSERT( static_cast<sal_uInt32>(rListBox.get_count() - 3) == rSoundList.size(),
308
0
                    "Sound list-box is not synchronized to sound list" );
309
0
        nPos -= 3;
310
0
        if( rSoundList.size() > o3tl::make_unsigned(nPos) )
311
0
            return rSoundList[ nPos ];
312
0
    }
313
314
0
    return OUString();
315
0
}
316
317
struct lcl_AppendSoundToListBox
318
{
319
    explicit lcl_AppendSoundToListBox(weld::ComboBox& rListBox)
320
0
        : mrListBox( rListBox )
321
0
    {}
322
323
    void operator() ( std::u16string_view rString ) const
324
0
    {
325
0
        INetURLObject aURL( rString );
326
0
        mrListBox.append_text( aURL.GetBase() );
327
0
    }
328
329
private:
330
    weld::ComboBox&  mrListBox;
331
};
332
333
void lcl_FillSoundListBox(
334
    const ::std::vector< OUString > & rSoundList,
335
    weld::ComboBox& rOutListBox )
336
0
{
337
0
    sal_Int32 nCount = rOutListBox.get_count();
338
339
    // keep first three entries
340
0
    for( sal_Int32 i=nCount - 1; i>=3; --i )
341
0
        rOutListBox.remove( i );
342
343
0
    ::std::for_each( rSoundList.begin(), rSoundList.end(),
344
0
                     lcl_AppendSoundToListBox( rOutListBox ));
345
0
}
346
347
/// Returns an offset into the list of transition presets
348
sd::TransitionPresetPtr getPreset(const sd::impl::TransitionEffect &rEffect)
349
0
{
350
0
    const sd::TransitionPresetList& rPresetList = sd::TransitionPreset::getTransitionPresetList();
351
352
0
    for (const auto& pPreset: rPresetList)
353
0
    {
354
0
        if (rEffect.operator==(*pPreset))
355
0
            return pPreset;
356
0
    }
357
0
    return sd::TransitionPresetPtr();
358
0
}
359
360
} // anonymous namespace
361
362
// SlideTransitionPane
363
SlideTransitionPane::SlideTransitionPane(
364
    weld::Widget* pParent,
365
    ViewShellBase & rBase) :
366
0
        PanelLayout( pParent, u"SlideTransitionsPanel"_ustr, u"modules/simpress/ui/slidetransitionspanel.ui"_ustr ),
367
0
        mrBase( rBase ),
368
0
        mpDrawDoc( rBase.GetDocShell() ? rBase.GetDocShell()->GetDoc() : nullptr ),
369
0
        mxTransitionsIconView(m_xBuilder->weld_icon_view("transitions_icons")),
370
0
        mxTransitionsScrollWindow(m_xBuilder->weld_scrolled_window("transitions_icons_scrolled_window")),
371
0
        mxRepeatAutoFrame(m_xBuilder->weld_frame("repeat_after_frame")),
372
0
        mbHasSelection( false ),
373
0
        mbUpdatingControls( false ),
374
0
        mbIsMainViewChangePending( false ),
375
0
        maLateInitTimer("sd SlideTransitionPane maLateInitTimer")
376
0
{
377
0
    Initialize(mpDrawDoc);
378
0
}
379
380
css::ui::LayoutSize SlideTransitionPane::GetHeightForWidth(const sal_Int32 /*nWidth*/)
381
0
{
382
0
    sal_Int32 nMinimumHeight = get_preferred_size().Height();
383
0
    return css::ui::LayoutSize(nMinimumHeight, -1, nMinimumHeight);
384
0
}
385
386
void SlideTransitionPane::Initialize(SdDrawDocument* pDoc)
387
0
{
388
0
    mxLB_VARIANT = m_xBuilder->weld_combo_box(u"variant_list"_ustr);
389
0
    mxCBX_duration = m_xBuilder->weld_metric_spin_button(u"transition_duration"_ustr, FieldUnit::SECOND);
390
0
    mxFT_SOUND = m_xBuilder->weld_label(u"sound_label"_ustr);
391
0
    mxLB_SOUND = m_xBuilder->weld_combo_box(u"sound_list"_ustr);
392
0
    mxCB_LOOP_SOUND = m_xBuilder->weld_check_button(u"loop_sound"_ustr);
393
0
    mxRB_ADVANCE_ON_MOUSE = m_xBuilder->weld_radio_button(u"rb_mouse_click"_ustr);
394
0
    mxRB_ADVANCE_AUTO = m_xBuilder->weld_radio_button(u"rb_auto_after"_ustr);
395
0
    mxMF_ADVANCE_AUTO_AFTER  = m_xBuilder->weld_metric_spin_button(u"auto_after_value"_ustr, FieldUnit::SECOND);
396
0
    mxRB_REPEAT_DISABLED = m_xBuilder->weld_radio_button(u"rb_disabled"_ustr);
397
0
    mxRB_REPEAT_AUTO = m_xBuilder->weld_radio_button(u"rb_auto_repeat"_ustr);
398
0
    mxMF_REPEAT_AUTO_AFTER  = m_xBuilder->weld_metric_spin_button(u"rb_auto_repeat_value"_ustr, FieldUnit::SECOND);
399
0
    mxPB_APPLY_TO_ALL = m_xBuilder->weld_button(u"apply_to_all"_ustr);
400
0
    mxPB_PLAY = m_xBuilder->weld_button(u"play"_ustr);
401
0
    mxCB_AUTO_PREVIEW = m_xBuilder->weld_check_button(u"auto_preview"_ustr);
402
403
0
    auto nMax = mxMF_ADVANCE_AUTO_AFTER->get_max(FieldUnit::SECOND);
404
0
    mxMF_ADVANCE_AUTO_AFTER->set_max(99, FieldUnit::SECOND);
405
0
    int nWidthChars = mxMF_ADVANCE_AUTO_AFTER->get_width_chars();
406
0
    mxMF_ADVANCE_AUTO_AFTER->set_max(nMax, FieldUnit::SECOND);
407
0
    mxMF_ADVANCE_AUTO_AFTER->set_width_chars(nWidthChars);
408
0
    mxMF_REPEAT_AUTO_AFTER->set_max(nMax, FieldUnit::SECOND);
409
0
    mxMF_REPEAT_AUTO_AFTER->set_width_chars(nWidthChars);
410
0
    mxCBX_duration->set_width_chars(nWidthChars);
411
412
0
    if( pDoc )
413
0
        mxModel = pDoc->getUnoModel();
414
    // TODO: get correct view
415
0
    if( mxModel.is())
416
0
        mxView.set( mxModel->getCurrentController(), uno::UNO_QUERY );
417
418
    // set defaults
419
0
    mxCB_AUTO_PREVIEW->set_active(true);      // automatic preview on
420
421
    // update control states before adding handlers
422
0
    updateControls();
423
424
    // set handlers
425
0
    mxPB_APPLY_TO_ALL->connect_clicked( LINK( this, SlideTransitionPane, ApplyToAllButtonClicked ));
426
0
    mxPB_PLAY->connect_clicked( LINK( this, SlideTransitionPane, PlayButtonClicked ));
427
428
0
    mxTransitionsIconView->connect_item_activated(LINK(this, SlideTransitionPane, TransitionSelected));
429
430
0
    mxLB_VARIANT->connect_changed( LINK( this, SlideTransitionPane, VariantListBoxSelected ));
431
0
    mxCBX_duration->connect_value_changed(LINK( this, SlideTransitionPane, DurationModifiedHdl));
432
0
    mxCBX_duration->connect_focus_out(LINK( this, SlideTransitionPane, DurationLoseFocusHdl));
433
0
    mxLB_SOUND->connect_changed( LINK( this, SlideTransitionPane, SoundListBoxSelected ));
434
0
    mxCB_LOOP_SOUND->connect_toggled( LINK( this, SlideTransitionPane, LoopSoundBoxChecked ));
435
436
0
    mxRB_ADVANCE_ON_MOUSE->connect_toggled( LINK( this, SlideTransitionPane, AdvanceSlideRadioButtonToggled ));
437
0
    mxRB_ADVANCE_AUTO->connect_toggled( LINK( this, SlideTransitionPane, AdvanceSlideRadioButtonToggled ));
438
0
    mxMF_ADVANCE_AUTO_AFTER->connect_value_changed( LINK( this, SlideTransitionPane, AdvanceTimeModified ));
439
0
    mxRB_REPEAT_DISABLED->connect_toggled( LINK( this, SlideTransitionPane, RepeatAfterRadioButtonToggled ));
440
0
    mxRB_REPEAT_AUTO->connect_toggled( LINK( this, SlideTransitionPane, RepeatAfterRadioButtonToggled ));
441
0
    mxMF_REPEAT_AUTO_AFTER->connect_value_changed( LINK( this, SlideTransitionPane, RepeatAfterTimeModified ));
442
0
    mxCB_AUTO_PREVIEW->connect_toggled( LINK( this, SlideTransitionPane, AutoPreviewClicked ));
443
0
    addListener();
444
445
0
    mxRB_REPEAT_DISABLED->set_active( true );
446
447
0
    maLateInitTimer.SetTimeout(200);
448
0
    maLateInitTimer.SetInvokeHandler(LINK(this, SlideTransitionPane, LateInitCallback));
449
0
    maLateInitTimer.Start();
450
0
}
451
452
SlideTransitionPane::~SlideTransitionPane()
453
0
{
454
0
    maLateInitTimer.Stop();
455
0
    removeListener();
456
0
    mxTransitionsScrollWindow.reset();
457
0
    mxTransitionsIconView.reset();
458
0
    mxRepeatAutoFrame.reset();
459
0
    mxLB_VARIANT.reset();
460
0
    mxCBX_duration.reset();
461
0
    mxFT_SOUND.reset();
462
0
    mxLB_SOUND.reset();
463
0
    mxCB_LOOP_SOUND.reset();
464
0
    mxRB_ADVANCE_ON_MOUSE.reset();
465
0
    mxRB_ADVANCE_AUTO.reset();
466
0
    mxMF_ADVANCE_AUTO_AFTER.reset();
467
0
    mxRB_REPEAT_DISABLED.reset();
468
0
    mxRB_REPEAT_AUTO.reset();
469
0
    mxMF_REPEAT_AUTO_AFTER.reset();
470
0
    mxPB_APPLY_TO_ALL.reset();
471
0
    mxPB_PLAY.reset();
472
0
    mxCB_AUTO_PREVIEW.reset();
473
0
}
474
475
void SlideTransitionPane::onSelectionChanged()
476
0
{
477
0
    updateControls();
478
0
}
479
480
void SlideTransitionPane::onChangeCurrentPage()
481
0
{
482
0
    updateControls();
483
0
}
484
485
::sd::slidesorter::SharedPageSelection SlideTransitionPane::getSelectedPages() const
486
0
{
487
0
    ::sd::slidesorter::SlideSorterViewShell * pSlideSorterViewShell
488
0
        = ::sd::slidesorter::SlideSorterViewShell::GetSlideSorter(mrBase);
489
0
    std::shared_ptr<sd::slidesorter::SlideSorterViewShell::PageSelection> pSelection;
490
491
0
    if( pSlideSorterViewShell )
492
0
    {
493
0
        pSelection = pSlideSorterViewShell->GetPageSelection();
494
0
    }
495
0
    else
496
0
    {
497
0
        pSelection = std::make_shared<sd::slidesorter::SlideSorterViewShell::PageSelection>();
498
0
        if( mxView.is() )
499
0
        {
500
0
            SdPage* pPage = SdPage::getImplementation( mxView->getCurrentPage() );
501
0
            if( pPage )
502
0
                pSelection->push_back(pPage);
503
0
        }
504
0
    }
505
506
0
    return pSelection;
507
0
}
508
509
void SlideTransitionPane::updateControls()
510
0
{
511
0
    ::sd::slidesorter::SharedPageSelection pSelectedPages(getSelectedPages());
512
0
    if( pSelectedPages->empty())
513
0
    {
514
0
        mbHasSelection = false;
515
0
        return;
516
0
    }
517
0
    mbHasSelection = true;
518
519
0
    DBG_ASSERT( ! mbUpdatingControls, "Multiple Control Updates" );
520
0
    mbUpdatingControls = true;
521
522
    // get model data for first page
523
0
    SdPage * pFirstPage = pSelectedPages->front();
524
0
    DBG_ASSERT( pFirstPage, "Invalid Page" );
525
526
0
    impl::TransitionEffect aEffect( *pFirstPage );
527
528
    // merge with other pages
529
530
    // start with second page (note aIt != aEndIt, because ! aSelectedPages.empty())
531
0
    for( const auto& rpPage : *pSelectedPages )
532
0
    {
533
0
        if( rpPage )
534
0
            aEffect.compareWith( *rpPage );
535
0
    }
536
537
    // detect current slide effect
538
0
    if( aEffect.mbEffectAmbiguous )
539
0
    {
540
0
        SAL_WARN( "sd.transitions", "Unusual, ambiguous transition effect" );
541
0
        mxTransitionsIconView->select(0);
542
0
    }
543
0
    else
544
0
    {
545
         // ToDo: That 0 is "no transition" is documented nowhere except in the
546
        // CTOR of sdpage
547
0
        if( aEffect.mnType == 0 )
548
0
            mxTransitionsIconView->select(0);
549
0
        else
550
0
            updateVariants(getPreset(aEffect));
551
0
    }
552
553
0
    if( aEffect.mbDurationAmbiguous )
554
0
    {
555
0
        mxCBX_duration->set_text(u""_ustr);
556
//TODO        mxCBX_duration->SetNoSelection();
557
0
    }
558
0
    else
559
0
    {
560
0
        mxCBX_duration->set_value( (aEffect.mfDuration)*100.0, FieldUnit::SECOND );
561
0
    }
562
563
0
    if( aEffect.mbSoundAmbiguous )
564
0
    {
565
0
        mxLB_SOUND->set_active(-1);
566
0
        maCurrentSoundFile.clear();
567
0
    }
568
0
    else
569
0
    {
570
0
        maCurrentSoundFile.clear();
571
0
        if( aEffect.mbStopSound )
572
0
        {
573
0
            mxLB_SOUND->set_active( 1 );
574
0
        }
575
0
        else if( aEffect.mbSoundOn && !aEffect.maSound.isEmpty() )
576
0
        {
577
0
            std::vector<OUString>::size_type nPos = 0;
578
0
            if( lcl_findSoundInList( maSoundList, aEffect.maSound, nPos ))
579
0
            {
580
0
                mxLB_SOUND->set_active( nPos + 3 );
581
0
                maCurrentSoundFile = aEffect.maSound;
582
0
            }
583
0
        }
584
0
        else
585
0
        {
586
0
            mxLB_SOUND->set_active( 0 );
587
0
        }
588
0
    }
589
590
0
    if( aEffect.mbLoopSoundAmbiguous )
591
0
    {
592
0
        mxCB_LOOP_SOUND->set_state(TRISTATE_INDET);
593
0
    }
594
0
    else
595
0
    {
596
0
        mxCB_LOOP_SOUND->set_active(aEffect.mbLoopSound);
597
0
    }
598
599
0
    if( aEffect.mbPresChangeAmbiguous )
600
0
    {
601
0
        mxRB_ADVANCE_ON_MOUSE->set_active( false );
602
0
        mxRB_ADVANCE_AUTO->set_active( false );
603
0
    }
604
0
    else
605
0
    {
606
0
        mxRB_ADVANCE_ON_MOUSE->set_active( aEffect.mePresChange == PresChange::Manual );
607
0
        mxRB_ADVANCE_AUTO->set_active( aEffect.mePresChange == PresChange::Auto );
608
0
        mxMF_ADVANCE_AUTO_AFTER->set_value(aEffect.mfTime * 100.0, FieldUnit::SECOND);
609
0
    }
610
611
0
    sd::PresentationSettings& rSettings = mpDrawDoc->getPresentationSettings();
612
613
0
    if ( !rSettings.mbEndless )
614
0
    {
615
0
        mxRB_REPEAT_DISABLED->set_active( true );
616
0
        mxRB_REPEAT_AUTO->set_active( false );
617
0
    }
618
0
    else
619
0
    {
620
0
        mxRB_REPEAT_DISABLED->set_active( false );
621
0
        mxRB_REPEAT_AUTO->set_active( true );
622
0
        mxMF_REPEAT_AUTO_AFTER->set_value(rSettings.mnPauseTimeout * 100.0, FieldUnit::SECOND);
623
0
    }
624
625
0
    if (comphelper::LibreOfficeKit::isActive())
626
0
    {
627
0
        mxPB_PLAY->hide();
628
0
        mxCB_AUTO_PREVIEW->set_active(false);
629
0
        mxCB_AUTO_PREVIEW->hide();
630
0
        mxFT_SOUND->hide();
631
0
        mxLB_SOUND->hide();
632
0
        mxCB_LOOP_SOUND->hide();
633
0
    }
634
0
    else
635
0
    {
636
0
        mxRepeatAutoFrame->hide();
637
0
        SdOptions* pOptions = SdModule::get()->GetSdOptions(DocumentType::Impress);
638
0
        mxCB_AUTO_PREVIEW->set_active( pOptions->IsPreviewTransitions() );
639
0
    }
640
641
0
    mbUpdatingControls = false;
642
643
0
    updateControlState();
644
0
}
645
646
void SlideTransitionPane::updateControlState()
647
0
{
648
0
    if (mxTransitionsScrollWindow)
649
0
        mxTransitionsScrollWindow->set_sensitive(mbHasSelection);
650
0
    mxLB_VARIANT->set_sensitive( mbHasSelection && mxLB_VARIANT->get_count() > 0 );
651
0
    mxCBX_duration->set_sensitive( mbHasSelection );
652
0
    mxLB_SOUND->set_sensitive( mbHasSelection );
653
0
    mxCB_LOOP_SOUND->set_sensitive( mbHasSelection && (mxLB_SOUND->get_active() > 2));
654
0
    mxRB_ADVANCE_ON_MOUSE->set_sensitive( mbHasSelection );
655
0
    mxRB_ADVANCE_AUTO->set_sensitive( mbHasSelection );
656
0
    mxMF_ADVANCE_AUTO_AFTER->set_sensitive( mbHasSelection && mxRB_ADVANCE_AUTO->get_active());
657
0
    mxRB_REPEAT_DISABLED->set_sensitive( mbHasSelection );
658
0
    mxRB_REPEAT_AUTO->set_sensitive( mbHasSelection );
659
0
    mxMF_REPEAT_AUTO_AFTER->set_sensitive( mbHasSelection && mxRB_REPEAT_AUTO->get_active());
660
661
0
    mxPB_APPLY_TO_ALL->set_sensitive( mbHasSelection );
662
0
    mxPB_PLAY->set_sensitive( mbHasSelection );
663
0
    mxCB_AUTO_PREVIEW->set_sensitive( mbHasSelection );
664
0
}
665
666
void SlideTransitionPane::updateSoundList()
667
0
{
668
0
    maSoundList.clear();
669
670
0
    GalleryExplorer::FillObjList( GALLERY_THEME_SOUNDS, maSoundList );
671
0
    GalleryExplorer::FillObjList( GALLERY_THEME_USERSOUNDS, maSoundList );
672
673
0
    lcl_FillSoundListBox( maSoundList, *mxLB_SOUND );
674
0
}
675
676
void SlideTransitionPane::openSoundFileDialog()
677
0
{
678
0
    if( ! mxLB_SOUND->get_sensitive())
679
0
        return;
680
681
0
    weld::Window* pDialogParent(GetFrameWeld());
682
0
    SdOpenSoundFileDialog aFileDialog(pDialogParent);
683
684
0
    DBG_ASSERT( mxLB_SOUND->get_active() == 2,
685
0
                "Dialog should only open when \"Other sound\" is selected" );
686
687
0
    bool bValidSoundFile( false );
688
0
    bool bQuitLoop( false );
689
690
0
    while( ! bQuitLoop &&
691
0
           aFileDialog.Execute() == ERRCODE_NONE )
692
0
    {
693
0
        OUString aFile = aFileDialog.GetPath();
694
0
        std::vector<OUString>::size_type nPos = 0;
695
0
        bValidSoundFile = lcl_findSoundInList( maSoundList, aFile, nPos );
696
697
0
        if( bValidSoundFile )
698
0
        {
699
0
            bQuitLoop = true;
700
0
        }
701
0
        else // not in sound list
702
0
        {
703
            // try to insert into gallery
704
0
            if( GalleryExplorer::InsertURL( GALLERY_THEME_USERSOUNDS, aFile ) )
705
0
            {
706
0
                updateSoundList();
707
0
                bValidSoundFile = lcl_findSoundInList( maSoundList, aFile, nPos );
708
0
                DBG_ASSERT( bValidSoundFile, "Adding sound to gallery failed" );
709
710
0
                bQuitLoop = true;
711
0
            }
712
0
            else
713
0
            {
714
0
                OUString aStrWarning(SdResId(STR_WARNING_NOSOUNDFILE));
715
0
                aStrWarning = aStrWarning.replaceFirst("%", aFile);
716
0
                std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pDialogParent,
717
0
                                                           VclMessageType::Warning, VclButtonsType::NONE,
718
0
                                                           aStrWarning));
719
0
                xWarn->add_button(GetStandardText(StandardButtonType::Retry), RET_RETRY);
720
0
                xWarn->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
721
0
                bQuitLoop = (xWarn->run() != RET_RETRY);
722
723
0
                bValidSoundFile = false;
724
0
            }
725
0
        }
726
727
0
        if( bValidSoundFile )
728
            // skip first three entries in list
729
0
            mxLB_SOUND->set_active( nPos + 3 );
730
0
    }
731
732
0
    if(  bValidSoundFile )
733
0
        return;
734
735
0
    if( !maCurrentSoundFile.isEmpty() )
736
0
    {
737
0
        std::vector<OUString>::size_type nPos = 0;
738
0
        if( lcl_findSoundInList( maSoundList, maCurrentSoundFile, nPos ))
739
0
            mxLB_SOUND->set_active( nPos + 3 );
740
0
        else
741
0
            mxLB_SOUND->set_active( 0 );  // NONE
742
0
    }
743
0
    else
744
0
        mxLB_SOUND->set_active( 0 );  // NONE
745
0
}
746
747
impl::TransitionEffect SlideTransitionPane::getTransitionEffectFromControls() const
748
0
{
749
0
    impl::TransitionEffect aResult;
750
0
    aResult.setAllAmbiguous();
751
752
0
    OUString sSelectedId = mxTransitionsIconView->get_selected_id();
753
0
    auto* pTransitionEntry = weld::fromId<TransitionEntry*>(sSelectedId);
754
0
    if (!pTransitionEntry)
755
0
        return aResult;
756
757
0
    const sd::TransitionPresetList& rPresetList = sd::TransitionPreset::getTransitionPresetList();
758
759
0
    if (pTransitionEntry->mpPreset)
760
0
    {
761
0
        auto pSelectedPreset = pTransitionEntry->mpPreset;
762
763
0
        if (mxLB_VARIANT->get_active() == -1)
764
0
        {
765
            // Transition with just one effect.
766
0
            aResult = impl::TransitionEffect(*pSelectedPreset);
767
0
            aResult.setAllAmbiguous();
768
0
        }
769
0
        else
770
0
        {
771
0
            int nVariant = 0;
772
0
            bool bFound = false;
773
0
            for(const auto& rPreset: rPresetList)
774
0
            {
775
0
                if (rPreset->getSetId() == pSelectedPreset->getSetId() )
776
0
                {
777
0
                    if( mxLB_VARIANT->get_active() == nVariant)
778
0
                    {
779
0
                        aResult = impl::TransitionEffect(*rPreset);
780
0
                        aResult.setAllAmbiguous();
781
0
                        bFound = true;
782
0
                        break;
783
0
                    }
784
0
                    else
785
0
                    {
786
0
                        nVariant++;
787
0
                    }
788
0
                }
789
0
            }
790
0
            if( !bFound )
791
0
            {
792
0
                aResult.mnType = 0;
793
0
            }
794
0
        }
795
0
        aResult.mbEffectAmbiguous = false;
796
0
    }
797
0
    else
798
0
    {
799
0
        aResult.mbEffectAmbiguous = false;
800
0
    }
801
802
    //duration
803
804
0
    if( mxCBX_duration->get_sensitive() && (!(mxCBX_duration->get_text()).isEmpty()) )
805
0
    {
806
0
        aResult.mfDuration = static_cast<double>(mxCBX_duration->get_value(FieldUnit::SECOND))/100.0;
807
0
        aResult.mbDurationAmbiguous = false;
808
0
    }
809
810
    // slide-advance mode
811
0
    if( mxRB_ADVANCE_ON_MOUSE->get_sensitive() && mxRB_ADVANCE_AUTO->get_sensitive() &&
812
0
        (mxRB_ADVANCE_ON_MOUSE->get_active() || mxRB_ADVANCE_AUTO->get_active()))
813
0
    {
814
0
        if( mxRB_ADVANCE_ON_MOUSE->get_active())
815
0
            aResult.mePresChange = PresChange::Manual;
816
0
        else
817
0
        {
818
0
            aResult.mePresChange = PresChange::Auto;
819
0
            if( mxMF_ADVANCE_AUTO_AFTER->get_sensitive())
820
0
            {
821
0
                aResult.mfTime = static_cast<double>(mxMF_ADVANCE_AUTO_AFTER->get_value(FieldUnit::SECOND) ) / 100.0 ;
822
0
                aResult.mbTimeAmbiguous = false;
823
0
            }
824
0
        }
825
826
0
        aResult.mbPresChangeAmbiguous = false;
827
0
    }
828
829
    // transition repeat after
830
0
    if (mxRB_REPEAT_DISABLED->get_sensitive() && mxRB_REPEAT_AUTO->get_sensitive()
831
0
            && (mxRB_REPEAT_DISABLED->get_active() || mxRB_REPEAT_AUTO->get_active()))
832
0
    {
833
0
        sd::PresentationSettings& rSettings = mpDrawDoc->getPresentationSettings();
834
835
0
        if ( mxRB_REPEAT_DISABLED->get_active() )
836
0
        {
837
0
            rSettings.mbEndless = false;
838
0
            rSettings.mnPauseTimeout = 0;
839
0
        }
840
0
        else
841
0
        {
842
0
            if ( mxMF_REPEAT_AUTO_AFTER->get_sensitive() )
843
0
            {
844
0
                rSettings.mbEndless = true;
845
0
                rSettings.mnPauseTimeout = static_cast<sal_uInt32>(mxMF_REPEAT_AUTO_AFTER->get_value(FieldUnit::SECOND) / 100.0) ;
846
0
            }
847
0
        }
848
0
    }
849
850
    // sound
851
0
    if( mxLB_SOUND->get_sensitive())
852
0
    {
853
0
        maCurrentSoundFile.clear();
854
0
        sal_Int32 nPos = mxLB_SOUND->get_active();
855
0
        if (nPos != -1)
856
0
        {
857
0
            aResult.mbStopSound = nPos == 1;
858
0
            aResult.mbSoundOn = nPos > 1;
859
0
            if( aResult.mbStopSound )
860
0
            {
861
0
                aResult.maSound.clear();
862
0
                aResult.mbSoundAmbiguous = false;
863
0
            }
864
0
            else
865
0
            {
866
0
                aResult.maSound = lcl_getSoundFileURL(maSoundList, *mxLB_SOUND);
867
0
                aResult.mbSoundAmbiguous = false;
868
0
                maCurrentSoundFile = aResult.maSound;
869
0
            }
870
0
        }
871
0
    }
872
873
    // sound loop
874
0
    if( mxCB_LOOP_SOUND->get_sensitive() )
875
0
    {
876
0
        aResult.mbLoopSound = mxCB_LOOP_SOUND->get_active();
877
0
        aResult.mbLoopSoundAmbiguous = false;
878
0
    }
879
880
0
    return aResult;
881
0
}
882
883
void SlideTransitionPane::applyToSelectedPages(bool bPreview = true)
884
0
{
885
0
    if(  mbUpdatingControls )
886
0
        return;
887
888
0
    vcl::Window *pFocusWindow = Application::GetFocusWindow();
889
890
0
    ::sd::slidesorter::SharedPageSelection pSelectedPages( getSelectedPages());
891
0
    impl::TransitionEffect aEffect = getTransitionEffectFromControls();
892
0
    if( ! pSelectedPages->empty())
893
0
    {
894
0
        lcl_CreateUndoForPages( pSelectedPages, mrBase );
895
0
        lcl_ApplyToPages( pSelectedPages, aEffect );
896
0
        mrBase.GetDocShell()->SetModified();
897
0
    }
898
0
    if( mxCB_AUTO_PREVIEW->get_sensitive() &&
899
0
        mxCB_AUTO_PREVIEW->get_active() && bPreview)
900
0
    {
901
0
        if (aEffect.mnType) // mnType = 0 denotes no transition
902
0
            playCurrentEffect();
903
0
        else if( mxView.is() && !SlideShow::IsInteractiveSlideshow(&mrBase)) // IASS
904
0
            SlideShow::Stop( mrBase );
905
0
    }
906
907
0
    if (pFocusWindow)
908
0
        pFocusWindow->GrabFocus();
909
0
}
910
911
void SlideTransitionPane::playCurrentEffect()
912
0
{
913
0
    if( mxView.is() )
914
0
    {
915
916
0
        Reference< css::animations::XAnimationNode > xNode;
917
0
        SlideShow::StartPreview( mrBase, mxView->getCurrentPage(), xNode );
918
0
    }
919
0
}
920
921
void SlideTransitionPane::addListener()
922
0
{
923
0
    Link<tools::EventMultiplexerEvent&,void> aLink( LINK(this,SlideTransitionPane,EventMultiplexerListener) );
924
0
    mrBase.GetEventMultiplexer()->AddEventListener( aLink );
925
0
}
926
927
void SlideTransitionPane::removeListener()
928
0
{
929
0
    Link<tools::EventMultiplexerEvent&,void> aLink( LINK(this,SlideTransitionPane,EventMultiplexerListener) );
930
0
    mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
931
0
}
932
933
IMPL_LINK(SlideTransitionPane,EventMultiplexerListener,
934
    tools::EventMultiplexerEvent&, rEvent, void)
935
0
{
936
0
    switch (rEvent.meEventId)
937
0
    {
938
0
        case EventMultiplexerEventId::EditViewSelection:
939
0
            onSelectionChanged();
940
0
            break;
941
942
0
        case EventMultiplexerEventId::CurrentPageChanged:
943
0
        case EventMultiplexerEventId::SlideSortedSelection:
944
0
            onChangeCurrentPage();
945
0
            break;
946
947
0
        case EventMultiplexerEventId::MainViewRemoved:
948
0
            mxView.clear();
949
0
            onSelectionChanged();
950
0
            onChangeCurrentPage();
951
0
            break;
952
953
0
        case EventMultiplexerEventId::MainViewAdded:
954
0
            mbIsMainViewChangePending = true;
955
0
            break;
956
957
0
        case EventMultiplexerEventId::ConfigurationUpdated:
958
0
            if (mbIsMainViewChangePending)
959
0
            {
960
0
                mbIsMainViewChangePending = false;
961
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
0
                if (mrBase.GetMainViewShell() != nullptr)
966
0
                {
967
0
                    mxView.set(mrBase.GetController(), css::uno::UNO_QUERY);
968
0
                    onSelectionChanged();
969
0
                    onChangeCurrentPage();
970
0
                }
971
0
            }
972
0
            break;
973
974
0
        default:
975
0
            if (rEvent.meEventId != EventMultiplexerEventId::Disposing)
976
0
            {
977
0
                onSelectionChanged();
978
0
                onChangeCurrentPage();
979
0
            }
980
0
            break;
981
0
    }
982
0
}
983
984
IMPL_LINK_NOARG(SlideTransitionPane, ApplyToAllButtonClicked, weld::Button&, void)
985
0
{
986
0
    DBG_ASSERT( mpDrawDoc, "Invalid Draw Document!" );
987
0
    if( !mpDrawDoc )
988
0
        return;
989
990
0
    ::sd::slidesorter::SharedPageSelection pPages =
991
0
        std::make_shared<::sd::slidesorter::SlideSorterViewShell::PageSelection>();
992
993
0
    sal_uInt16 nPageCount = mpDrawDoc->GetSdPageCount( PageKind::Standard );
994
0
    pPages->reserve( nPageCount );
995
0
    for( sal_uInt16 i=0; i<nPageCount; ++i )
996
0
    {
997
0
        SdPage * pPage = mpDrawDoc->GetSdPage( i, PageKind::Standard );
998
0
        if( pPage )
999
0
            pPages->push_back( pPage );
1000
0
    }
1001
1002
0
    if( ! pPages->empty())
1003
0
    {
1004
0
        lcl_CreateUndoForPages( pPages, mrBase );
1005
0
        lcl_ApplyToPages( pPages, getTransitionEffectFromControls() );
1006
0
    }
1007
0
}
1008
1009
IMPL_LINK_NOARG(SlideTransitionPane, PlayButtonClicked, weld::Button&, void)
1010
0
{
1011
0
    playCurrentEffect();
1012
0
}
1013
1014
IMPL_LINK_NOARG(SlideTransitionPane, TransitionSelected, weld::IconView&, bool)
1015
0
{
1016
0
    OUString sSelectedId = mxTransitionsIconView->get_selected_id();
1017
0
    auto* pTransitionEntry = weld::fromId<TransitionEntry*>(sSelectedId);
1018
0
    updateVariants(pTransitionEntry->mpPreset);
1019
0
    applyToSelectedPages();
1020
0
    return true;
1021
0
}
1022
1023
/// we use an integer offset into the list of transition presets
1024
void SlideTransitionPane::updateVariants(TransitionPresetPtr const& pPreset)
1025
0
{
1026
0
    mxLB_VARIANT->clear();
1027
0
    mxLB_VARIANT->set_sensitive(false);
1028
0
    mxLB_VARIANT->set_active(0);
1029
1030
0
    if (!pPreset)
1031
0
    {
1032
0
        mxTransitionsIconView->select(0);
1033
0
    }
1034
0
    else
1035
0
    {
1036
0
        auto iterator = maTranstionMap.find(pPreset->getSetId());
1037
0
        if (iterator != maTranstionMap.end())
1038
0
        {
1039
0
            auto& pTransitionEntry = iterator->second;
1040
0
            if (!pTransitionEntry->mnVariants.empty())
1041
0
            {
1042
0
                for (OUString const& rCurrentVariant : pTransitionEntry->mnVariants)
1043
0
                {
1044
0
                    mxLB_VARIANT->append_text(rCurrentVariant);
1045
0
                    if (pPreset->getVariantLabel() == rCurrentVariant)
1046
0
                        mxLB_VARIANT->set_active(mxLB_VARIANT->get_count() - 1);
1047
0
                }
1048
0
                mxLB_VARIANT->set_sensitive(true);
1049
0
            }
1050
1051
0
            mxTransitionsIconView->select(pTransitionEntry->mnIndex);
1052
0
        }
1053
0
    }
1054
0
}
1055
1056
IMPL_LINK_NOARG(SlideTransitionPane, AdvanceSlideRadioButtonToggled, weld::Toggleable&, void)
1057
0
{
1058
0
    updateControlState();
1059
0
    applyToSelectedPages(false);
1060
0
}
1061
1062
IMPL_LINK_NOARG(SlideTransitionPane, RepeatAfterRadioButtonToggled, weld::Toggleable&, void)
1063
0
{
1064
0
    updateControlState();
1065
0
    applyToSelectedPages(false);
1066
0
}
1067
1068
IMPL_LINK_NOARG(SlideTransitionPane, AdvanceTimeModified, weld::MetricSpinButton&, void)
1069
0
{
1070
0
    applyToSelectedPages(false);
1071
0
}
1072
1073
IMPL_LINK_NOARG(SlideTransitionPane, RepeatAfterTimeModified, weld::MetricSpinButton&, void)
1074
0
{
1075
0
    applyToSelectedPages(false);
1076
0
}
1077
1078
IMPL_LINK_NOARG(SlideTransitionPane, VariantListBoxSelected, weld::ComboBox&, void)
1079
0
{
1080
0
    applyToSelectedPages();
1081
0
}
1082
1083
IMPL_LINK_NOARG(SlideTransitionPane, DurationModifiedHdl, weld::MetricSpinButton&, void)
1084
0
{
1085
0
    double duration_value = static_cast<double>(mxCBX_duration->get_value(FieldUnit::SECOND));
1086
0
    if (duration_value <= 0.0)
1087
0
        mxCBX_duration->set_value(0, FieldUnit::SECOND);
1088
0
    else
1089
0
        mxCBX_duration->set_value(duration_value, FieldUnit::SECOND);
1090
1091
0
    applyToSelectedPages();
1092
0
}
1093
1094
IMPL_LINK_NOARG(SlideTransitionPane, DurationLoseFocusHdl, weld::Widget&, void)
1095
0
{
1096
0
    applyToSelectedPages();
1097
0
}
1098
1099
IMPL_LINK_NOARG(SlideTransitionPane, SoundListBoxSelected, weld::ComboBox&, void)
1100
0
{
1101
0
    sal_Int32 nPos = mxLB_SOUND->get_active();
1102
0
    if( nPos == 2 )
1103
0
    {
1104
        // other sound...
1105
0
        openSoundFileDialog();
1106
0
    }
1107
0
    updateControlState();
1108
0
    applyToSelectedPages();
1109
0
}
1110
1111
IMPL_LINK_NOARG(SlideTransitionPane, LoopSoundBoxChecked, weld::Toggleable&, void)
1112
0
{
1113
0
    applyToSelectedPages();
1114
0
}
1115
1116
IMPL_LINK_NOARG(SlideTransitionPane, AutoPreviewClicked, weld::Toggleable&, void)
1117
0
{
1118
0
    SdOptions* pOptions = SdModule::get()->GetSdOptions(DocumentType::Impress);
1119
0
    pOptions->SetPreviewTransitions( mxCB_AUTO_PREVIEW->get_active() );
1120
0
}
1121
1122
IMPL_LINK_NOARG(SlideTransitionPane, LateInitCallback, Timer *, void)
1123
0
{
1124
0
    mxTransitionsIconView->freeze();
1125
1126
0
    {
1127
0
        auto pTransition = std::make_unique<TransitionEntry>();
1128
0
        const OUString aId = weld::toId(pTransition.get());
1129
0
        pTransition->msIcon = u"sd/cmd/transition-none.png"_ustr;
1130
0
        pTransition->msLabel = SdResId(STR_SLIDETRANSITION_NONE);
1131
0
        pTransition->mnIndex = 0;
1132
0
        mxTransitionsIconView->append(aId, pTransition->msLabel, pTransition->msIcon);
1133
0
        maTranstionMap.emplace(u"None"_ustr, std::move(pTransition));
1134
0
    }
1135
1136
0
    const TransitionPresetList& rPresetList = TransitionPreset::getTransitionPresetList();
1137
0
    size_t nIndex = 1;
1138
0
    for (TransitionPresetPtr const& pPreset: rPresetList)
1139
0
    {
1140
0
        const OUString aLabel = pPreset->getSetLabel();
1141
0
        if (!aLabel.isEmpty())
1142
0
        {
1143
0
            auto aIterator = maTranstionMap.find(pPreset->getSetId());
1144
0
            if (aIterator == maTranstionMap.end())
1145
0
            {
1146
0
                auto pTransition = std::make_unique<TransitionEntry>();
1147
0
                const OUString aId = weld::toId(pTransition.get());
1148
1149
0
                pTransition->msIcon = u"sd/cmd/transition-"_ustr + pPreset->getSetId() + u".png"_ustr;
1150
0
                pTransition->msLabel = aLabel;
1151
0
                pTransition->mpPreset = pPreset;
1152
0
                if (!pPreset->getVariantLabel().isEmpty())
1153
0
                    pTransition->mnVariants.push_back(pPreset->getVariantLabel());
1154
0
                pTransition->mnIndex = nIndex;
1155
0
                nIndex++;
1156
1157
0
                mxTransitionsIconView->append(aId, pTransition->msLabel, pTransition->msIcon);
1158
0
                maTranstionMap.emplace(pPreset->getSetId(), std::move(pTransition));
1159
0
            }
1160
0
            else
1161
0
            {
1162
0
                auto& pTransition = aIterator->second;
1163
0
                pTransition->mnVariants.push_back(pPreset->getVariantLabel());
1164
0
            }
1165
0
        }
1166
0
    }
1167
0
    mxTransitionsIconView->set_size_request(0, 0);
1168
0
    mxTransitionsIconView->thaw();
1169
1170
0
    updateSoundList();
1171
0
    updateControls();
1172
0
}
1173
1174
} //  namespace sd
1175
1176
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */