Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sd/source/ui/animations/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 68 kB image not shown  

Quelle  CustomAnimationDialog.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <config_features.h>

#include <com/sun/star/presentation/EffectNodeType.hpp>
#include <com/sun/star/animations/Timing.hpp>
#include <com/sun/star/animations/Event.hpp>
#include <com/sun/star/animations/EventTrigger.hpp>
#include <com/sun/star/animations/AnimationFill.hpp>
#include <com/sun/star/presentation/TextAnimationType.hpp>
#include <com/sun/star/animations/ValuePair.hpp>
#include <com/sun/star/awt/FontSlant.hpp>
#include <com/sun/star/awt/FontWeight.hpp>
#include <com/sun/star/awt/FontUnderline.hpp>
#include <com/sun/star/drawing/XDrawPage.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/media/XPlayer.hpp>

#include <memory>

#include <comphelper/lok.hxx>
#include <i18nutil/unicode.hxx>
#include <vcl/svapp.hxx>
#include <vcl/stdtext.hxx>
#include <vcl/weld.hxx>
#include <vcl/settings.hxx>

#include <svtools/ctrltool.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/viewsh.hxx>
#include <tools/debug.hxx>
#include <tools/urlobj.hxx>
#include <comphelper/diagnose_ex.hxx>

#include <editeng/flstitem.hxx>

#include <svx/colorbox.hxx>
#include <svx/gallery.hxx>

#include <editeng/editids.hrc>
#include <sdresid.hxx>

#include "CustomAnimationDialog.hxx"
#include <CustomAnimationPane.hxx>
#include "STLPropertySet.hxx"
#include <CustomAnimationPreset.hxx>

#include <avmedia/mediawindow.hxx>

#include <filedlg.hxx>
#include <strings.hrc>
#include <helpids.h>

using namespace ::com::sun::star;
using namespace ::com::sun::star::animations;
using namespace ::com::sun::star::presentation;

using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Sequence;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Exception;
using ::com::sun::star::drawing::XShape;
using ::com::sun::star::drawing::XDrawPage;
using ::com::sun::star::beans::XPropertySet;

namespace sd {

SdPropertySubControl::SdPropertySubControl(weld::Container* pParent)
    : mxBuilder(Application::CreateBuilder(pParent, u"modules/simpress/ui/customanimationfragment.ui"_ustr,
        falsereinterpret_cast<sal_uInt64>(SfxViewShell::Current())))
    , mxContainer(mxBuilder->weld_container(u"EffectFragment"_ustr))
    , mpParent(pParent)
{
}

SdPropertySubControl::~SdPropertySubControl()
{
    mpParent->move(mxContainer.get(), nullptr);
}

namespace {

class SdPresetPropertyBox  : public SdPropertySubControl
{
public:
    SdPresetPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const OUString& aPresetId, const Link<LinkParamNone*,void>& rModifyHdl);

    virtual Any getValue() override;
    virtual void setValue( const Any& rValue, const OUString& rPresetId ) override;

private:
    std::vector<OUString> maPropertyValues;
    Link<LinkParamNone*,void> maModifyLink;
    std::unique_ptr<weld::ComboBox> mxControl;

    DECL_LINK(OnSelect, weld::ComboBox&, void);
};

}

SdPresetPropertyBox::SdPresetPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const OUString& aPresetId, const Link<LinkParamNone*,void>&&nbsp;rModifyHdl)
    : SdPropertySubControl(pParent)
    , maModifyLink(rModifyHdl)
    , mxControl(mxBuilder->weld_combo_box(u"combo"_ustr))
{
    mxControl->connect_changed(LINK(this, SdPresetPropertyBox, OnSelect));
    mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_PRESETPROPERTYBOX);
    mxControl->show();
    pLabel->set_mnemonic_widget(mxControl.get());
    setValue(rValue, aPresetId);
}

IMPL_LINK_NOARG(SdPresetPropertyBox, OnSelect, weld::ComboBox&, void)
{
    maModifyLink.Call(nullptr);
}

void SdPresetPropertyBox::setValue( const Any& rValue, const OUString& rPresetId )
{
    if (!mxControl)
        return;

    mxControl->freeze();
    mxControl->clear();
    maPropertyValues.clear();
    int nPos = -1;

    const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets();
    CustomAnimationPresetPtr pDescriptor = rPresets.getEffectDescriptor( rPresetId );
    if( pDescriptor )
    {

        OUString aPropertyValue;
        rValue >>= aPropertyValue;

        std::vector<OUString> aSubTypes( pDescriptor->getSubTypes() );

        mxControl->set_sensitive(!aSubTypes.empty());

        forconst auto& aSubType : aSubTypes )
        {
            mxControl->append_text(rPresets.getUINameForProperty(aSubType));
            maPropertyValues.push_back(aSubType);
            if (aSubType == aPropertyValue)
                nPos = maPropertyValues.size() - 1;
        }
    }
    else
    {
        mxControl->set_sensitive(false);
    }
    mxControl->thaw();
    if (nPos != -1)
        mxControl->set_active(nPos);
}

Any SdPresetPropertyBox::getValue()
{
    const int nIndex = mxControl->get_active();
    if (nIndex == -1)
        return Any();
    return Any(maPropertyValues[nIndex]);
}

namespace {

class SdColorPropertyBox : public SdPropertySubControl
{
public:
    SdColorPropertyBox(weld::Label* pLabel, weld::Container* pParent, weld::Window* pTopLevel, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);

    virtual Any getValue() override;
    virtual void setValue( const Any& rValue, const OUString& rPresetId  ) override;

private:
    Link<LinkParamNone*,void> maModifyLink;
    std::unique_ptr<ColorListBox> mxControl;

    DECL_LINK(OnSelect, ColorListBox&, void);
};

}

SdColorPropertyBox::SdColorPropertyBox(weld::Label* pLabel, weld::Container* pParent, weld::Window* pTopLevel, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
    : SdPropertySubControl(pParent)
    , maModifyLink(rModifyHdl)
    , mxControl(new ColorListBox(mxBuilder->weld_menu_button(u"color"_ustr), [pTopLevel]return pTopLevel; }))
{
    mxControl->SetSelectHdl(LINK(this, SdColorPropertyBox, OnSelect));
    mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_COLORPROPERTYBOX);
    pLabel->set_mnemonic_widget(&mxControl->get_widget());
    mxControl->show();

    Color nColor;
    rValue >>= nColor;
    mxControl->SelectEntry(nColor);
}

IMPL_LINK_NOARG(SdColorPropertyBox, OnSelect, ColorListBox&, void)
{
    maModifyLink.Call(nullptr);
}

void SdColorPropertyBox::setValue( const Any& rValue, const OUString& )
{
    if (mxControl)
    {
        Color nColor;
        rValue >>= nColor;

        mxControl->SetNoSelection();
        mxControl->SelectEntry(nColor);
    }
}

Any SdColorPropertyBox::getValue()
{
    return Any(sal_Int32(mxControl->GetSelectEntryColor().GetRGBColor()));
}

namespace {

class SdFontPropertyBox : public SdPropertySubControl
{
public:
    SdFontPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValueconst Link<LinkParamNone*,void>& rModifyHdl);

    virtual Any getValue() override;
    virtual void setValue(const Any& rValue, const OUString& rPresetId) override;

private:
    Link<LinkParamNone*,void>   maModifyHdl;
    std::unique_ptr<weld::ComboBox> mxControl;

    DECL_LINK(ControlSelectHdl, weld::ComboBox&, void);
};

}

SdFontPropertyBox::SdFontPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
    : SdPropertySubControl(pParent)
    , maModifyHdl(rModifyHdl)
    , mxControl(mxBuilder->weld_combo_box(u"fontname"_ustr))
{
    mxControl->connect_changed(LINK(this, SdFontPropertyBox, ControlSelectHdl));
    mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_FONTPROPERTYBOX);
    mxControl->show();
    pLabel->set_mnemonic_widget(mxControl.get());

    const FontList* pFontList = nullptr;
    bool bMustDelete = false;

    if (SfxObjectShell* pDocSh = SfxObjectShell::Current())
    {
        auto pItem = pDocSh->GetItem( SID_ATTR_CHAR_FONTLIST );
        if (pItem)
            pFontList = static_cast<const SvxFontListItem*>(pItem)->GetFontList();
    }

    if (!pFontList)
    {
        pFontList = new FontList(Application::GetDefaultDevice(), nullptr);
        bMustDelete = true;
    }

    mxControl->freeze();

    sal_uInt16 nFontCount = pFontList->GetFontNameCount();
    for (sal_uInt16 i = 0; i < nFontCount; ++i)
    {
        const FontMetric& rFontMetric = pFontList->GetFontName(i);
        mxControl->append_text(rFontMetric.GetFamilyName());
    }

    mxControl->thaw();

    if( bMustDelete )
        delete pFontList;

    setValue( rValue, OUString() );
}

IMPL_LINK_NOARG(SdFontPropertyBox, ControlSelectHdl, weld::ComboBox&, void)
{
    maModifyHdl.Call(nullptr);
}

void SdFontPropertyBox::setValue( const Any& rValue, const OUString& )
{
    if (mxControl)
    {
        OUString aFontName;
        rValue >>= aFontName;
        mxControl->set_entry_text(aFontName);
    }
}

Any SdFontPropertyBox::getValue()
{
    OUString aFontName(mxControl->get_active_text());
    return Any(aFontName);
}

namespace {

class SdCharHeightPropertyBox : public SdPropertySubControl
{
public:
    SdCharHeightPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);

    virtual Any getValue() override;
    virtual void setValue( const Any& rValue, const OUString& ) override;

    DECL_LINK(implMenuSelectHdl, const OUString& rIdent, void);

private:
    Link<LinkParamNone*,void> maModifyHdl;
    std::unique_ptr<weld::MetricSpinButton> mxMetric;
    std::unique_ptr<weld::MenuButton> mxControl;

    DECL_LINK(EditModifyHdl, weld::MetricSpinButton&, void);
};

}

SdCharHeightPropertyBox::SdCharHeightPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
    : SdPropertySubControl(pParent)
    , maModifyHdl(rModifyHdl)
    , mxMetric(mxBuilder->weld_metric_spin_button(u"fontsize"_ustr, FieldUnit::PERCENT))
    , mxControl(mxBuilder->weld_menu_button(u"fontsizemenu"_ustr))
{
    mxMetric->connect_value_changed(LINK(this, SdCharHeightPropertyBox, EditModifyHdl));
    mxMetric->set_help_id(HID_SD_CUSTOMANIMATIONPANE_CHARHEIGHTPROPERTYBOX);
    mxMetric->show();
    pLabel->set_mnemonic_widget(&mxMetric->get_widget());

    mxControl->connect_selected(LINK(this, SdCharHeightPropertyBox, implMenuSelectHdl));
    mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_CHARHEIGHTPROPERTYBOX);
    mxControl->show();

    setValue(rValue, OUString());
}

IMPL_LINK_NOARG(SdCharHeightPropertyBox, EditModifyHdl, weld::MetricSpinButton&, ;void)
{
    maModifyHdl.Call(nullptr);
}

IMPL_LINK(SdCharHeightPropertyBox, implMenuSelectHdl, const OUString&, rIdent, void)
{
    sal_Int32 nValue = rIdent.toInt32();
    mxMetric->set_value(nValue, FieldUnit::PERCENT);
    EditModifyHdl(*mxMetric);
}

void SdCharHeightPropertyBox::setValue( const Any& rValue, const OUString& )
{
    if (mxMetric)
    {
        double fValue = 0.0;
        rValue >>= fValue;
        mxMetric->set_value(static_cast<::tools::Long>(fValue * 100.0), FieldUnit::PERCENT);
    }
}

Any SdCharHeightPropertyBox::getValue()
{
    return Any(static_cast<double>(mxMetric->get_value(FieldUnit::PERCENT)) / 100.0);
}

namespace {

class SdTransparencyPropertyBox : public SdPropertySubControl
{
public:
    SdTransparencyPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any&&nbsp;rValue, const Link<LinkParamNone*,void>& rModifyHdl);

    virtual Any getValue() override;
    virtual void setValue( const Any& rValue, const OUString& rPresetId  ) override;

    DECL_LINK(implMenuSelectHdl, const OUString&, void);
    DECL_LINK(implModifyHdl, weld::MetricSpinButton&, void);

    void updateMenu();

private:
    Link<LinkParamNone*,void> maModifyHdl;

    std::unique_ptr<weld::MetricSpinButton> mxMetric;
    std::unique_ptr<weld::MenuButton> mxControl;
};

}

SdTransparencyPropertyBox::SdTransparencyPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
    : SdPropertySubControl(pParent)
    , maModifyHdl(rModifyHdl)
    , mxMetric(mxBuilder->weld_metric_spin_button(u"transparent"_ustr, FieldUnit::PERCENT))
    , mxControl(mxBuilder->weld_menu_button(u"transparentmenu"_ustr))
{
    for (sal_Int32 i = 25; i < 101; i += 25)
    {
        OUString aStr(unicode::formatPercent(i,
            Application::GetSettings().GetUILanguageTag()));
        mxControl->append_item_check(OUString::number(i), aStr);
    }

    mxControl->connect_selected(LINK(this, SdTransparencyPropertyBox, implMenuSelectHdl));
    mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_TRANSPARENCYPROPERTYBOX);
    mxControl->show();

    mxMetric->connect_value_changed(LINK(this, SdTransparencyPropertyBox, implModifyHdl));
    mxMetric->set_help_id(HID_SD_CUSTOMANIMATIONPANE_TRANSPARENCYPROPERTYBOX);
    mxMetric->show();
    pLabel->set_mnemonic_widget(&mxMetric->get_widget());

    setValue(rValue, OUString());
}

void SdTransparencyPropertyBox::updateMenu()
{
    sal_Int64 nValue = mxMetric->get_value(FieldUnit::PERCENT);
    for (sal_uInt16 i = 25; i < 101; i += 25)
        mxControl->set_item_active(OUString::number(i), nValue == i);
}

IMPL_LINK_NOARG(SdTransparencyPropertyBox, implModifyHdl, weld::MetricSpinButton&,&nbsp;void)
{
    updateMenu();
    maModifyHdl.Call(nullptr);
}

IMPL_LINK(SdTransparencyPropertyBox, implMenuSelectHdl, const OUString&, rIdent, void)
{
    auto nValue = rIdent.toInt32();
    if (nValue != mxMetric->get_value(FieldUnit::PERCENT))
    {
        mxMetric->set_value(nValue, FieldUnit::PERCENT);
        implModifyHdl(*mxMetric);
    }
}

void SdTransparencyPropertyBox::setValue(const Any& rValue, const OUString&)
{
    if (mxMetric)
    {
        double fValue = 0.0;
        rValue >>= fValue;
        ::tools::Long nValue = static_cast<::tools::Long>(fValue * 100);
        mxMetric->set_value(nValue, FieldUnit::PERCENT);
        updateMenu();
    }
}

Any SdTransparencyPropertyBox::getValue()
{
    return Any(static_cast<double>(mxMetric->get_value(FieldUnit::PERCENT)) / 100.0);
}

namespace {

class SdRotationPropertyBox : public SdPropertySubControl
{
public:
    SdRotationPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);

    virtual Any getValue() override;
    virtual void setValue( const Any& rValue, const OUString& ) override;

    DECL_LINK(implMenuSelectHdl, const OUString&, void);
    DECL_LINK(implModifyHdl, weld::MetricSpinButton&, void);

    void updateMenu();

private:
    Link<LinkParamNone*,void> maModifyHdl;

    std::unique_ptr<weld::MetricSpinButton> mxMetric;
    std::unique_ptr<weld::MenuButton> mxControl;
};

}

SdRotationPropertyBox::SdRotationPropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
    : SdPropertySubControl(pParent)
    , maModifyHdl(rModifyHdl)
    , mxMetric(mxBuilder->weld_metric_spin_button(u"rotate"_ustr, FieldUnit::DEGREE))
    , mxControl(mxBuilder->weld_menu_button(u"rotatemenu"_ustr))
{
    mxMetric->connect_value_changed(LINK( this, SdRotationPropertyBox, implModifyHdl));
    mxMetric->set_help_id(HID_SD_CUSTOMANIMATIONPANE_ROTATIONPROPERTYBOX);
    mxMetric->show();
    pLabel->set_mnemonic_widget(&mxMetric->get_widget());

    mxControl->connect_selected(LINK(this, SdRotationPropertyBox, implMenuSelectHdl));
    mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_ROTATIONPROPERTYBOX);
    mxControl->show();

    setValue(rValue, OUString());
}

void SdRotationPropertyBox::updateMenu()
{
    sal_Int64 nValue = mxMetric->get_value(FieldUnit::DEGREE);
    bool bDirection = nValue >= 0;
    nValue = (nValue < 0 ? -nValue : nValue);

    mxControl->set_item_active(u"90"_ustr, nValue == 90);
    mxControl->set_item_active(u"180"_ustr, nValue == 180);
    mxControl->set_item_active(u"360"_ustr, nValue == 360);
    mxControl->set_item_active(u"720"_ustr, nValue == 720);

    mxControl->set_item_active(u"clockwise"_ustr, bDirection);
    mxControl->set_item_active(u"counterclock"_ustr, !bDirection);
}

IMPL_LINK_NOARG(SdRotationPropertyBox, implModifyHdl, weld::MetricSpinButton&, void)
{
    updateMenu();
    maModifyHdl.Call(nullptr);
}

IMPL_LINK(SdRotationPropertyBox, implMenuSelectHdl, const OUString&, rIdent, void)
{
    auto nValue = mxMetric->get_value(FieldUnit::DEGREE);
    bool bDirection = nValue >= 0;
    nValue = (nValue < 0 ? -nValue : nValue);

    if (rIdent == "clockwise")
        bDirection = true;
    else if (rIdent == "counterclock")
        bDirection = false;
    else
        nValue = rIdent.toInt32();

    if( !bDirection )
        nValue = -nValue;

    if (nValue != mxMetric->get_value(FieldUnit::DEGREE))
    {
        mxMetric->set_value(nValue, FieldUnit::DEGREE);
        implModifyHdl(*mxMetric);
    }
}

void SdRotationPropertyBox::setValue( const Any& rValue, const OUString& )
{
    if (mxMetric)
    {
        double fValue = 0.0;
        rValue >>= fValue;
        ::tools::Long nValue = static_cast<::tools::Long>(fValue);
        mxMetric->set_value(nValue, FieldUnit::DEGREE);
        updateMenu();
    }
}

Any SdRotationPropertyBox::getValue()
{
    return Any(static_cast<double>(mxMetric->get_value(FieldUnit::DEGREE)));
}

namespace {

class SdScalePropertyBox : public SdPropertySubControl
{
public:
    SdScalePropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);

    virtual Any getValue() override;
    virtual void setValue( const Any& rValue, const OUString& ) override;

    DECL_LINK(implMenuSelectHdl, const OUString&, void);
    DECL_LINK(implModifyHdl, weld::MetricSpinButton&, void);

    void updateMenu();

private:
    Link<LinkParamNone*,void> maModifyHdl;
    int                       mnDirection;

    std::unique_ptr<weld::MetricSpinButton> mxMetric;
    std::unique_ptr<weld::MenuButton> mxControl;
};

}

SdScalePropertyBox::SdScalePropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl)
    : SdPropertySubControl(pParent)
    , maModifyHdl( rModifyHdl )
    , mxMetric(mxBuilder->weld_metric_spin_button(u"scale"_ustr, FieldUnit::PERCENT))
    , mxControl(mxBuilder->weld_menu_button(u"scalemenu"_ustr))
{
    mxControl->connect_selected(LINK(this, SdScalePropertyBox, implMenuSelectHdl));
    mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_SCALEPROPERTYBOX);
    mxControl->show();

    mxMetric->connect_value_changed(LINK(this, SdScalePropertyBox, implModifyHdl));
    mxMetric->set_help_id(HID_SD_CUSTOMANIMATIONPANE_SCALEPROPERTYBOX);
    mxMetric->show();
    pLabel->set_mnemonic_widget(&mxMetric->get_widget());

    setValue(rValue, OUString());
}

void SdScalePropertyBox::updateMenu()
{
    auto nValue = mxMetric->get_value(FieldUnit::PERCENT);

    mxControl->set_item_active(u"25scale"_ustr, nValue == 25);
    mxControl->set_item_active(u"50scale"_ustr, nValue == 50);
    mxControl->set_item_active(u"150scale"_ustr, nValue == 150);
    mxControl->set_item_active(u"400scale"_ustr, nValue == 400);

    mxControl->set_item_active(u"hori"_ustr, mnDirection == 1);
    mxControl->set_item_active(u"vert"_ustr, mnDirection == 2);
    mxControl->set_item_active(u"both"_ustr, mnDirection == 3);
}

IMPL_LINK_NOARG(SdScalePropertyBox, implModifyHdl, weld::MetricSpinButton&, void)
{
    updateMenu();
    maModifyHdl.Call(nullptr);
}

IMPL_LINK(SdScalePropertyBox, implMenuSelectHdl, const OUString&, rIdent, void)
{
    auto nValue = mxMetric->get_value(FieldUnit::PERCENT);

    int nDirection = mnDirection;

    if (rIdent == "hori")
        nDirection = 1;
    else if (rIdent == "vert")
        nDirection = 2;
    else if (rIdent == "both")
        nDirection = 3;
    else
        nValue = rIdent.toInt32(); // Getting here indicates a UI bug and should be handled better

    bool bModified = false;

    if( nDirection != mnDirection )
    {
        mnDirection = nDirection;
        bModified = true;
    }

    if (nValue != mxMetric->get_value(FieldUnit::PERCENT))
    {
        mxMetric->set_value(nValue, FieldUnit::PERCENT);
        bModified = true;
    }

    if(bModified)
    {
        implModifyHdl(*mxMetric);
        updateMenu();
    }
}

void SdScalePropertyBox::setValue(const Any& rValue, const OUString&)
{
    if (!mxMetric)
        return;

    ValuePair aValues;
    rValue >>= aValues;

    double fValue1 = 0.0;
    double fValue2 = 0.0;

    aValues.First >>= fValue1;
    aValues.Second >>= fValue2;

    // 'Size' drop down menu set by mnDirection when loading Grow and Shrink Animation
    // Shouldn't compare a float directly to zero... should be fixed with delta epsilon compare
    // Might be better to just have a flag in the content.xml for this
    if( (fValue1 == 0.0) && (fValue2 == 0.0) )
        mnDirection = 3; // assume 'Both' scaling option when both are zero
    else if( (fValue1 != 0.0) && (fValue2 == 0.0) )
        mnDirection = 1;
    else if( (fValue1 == 0.0) && (fValue2 != 0.0) )
        mnDirection = 2;
    else
        mnDirection = 3;

    // Grow and Shrink Animation is a relative change with value stored in content.xml under tag
    // smil:by=*,*
    // An offset of 1 must be added to properly translate from content.xml to UI value displayed
    // e.g. if in content.xml smil:by=0.5,0.5 then 1 + (0.5,0.5) = (1.5,1.5) => grow by 150% of the
    // size horizontal and vertical
    // e.g. if in content.xml smil:by=-0.5,-0.5 then 1 + (-0.5,-0.5) = (0.5,0.5) => shrink by 50%
    // of the size horizontal and vertical
    fValue1 += 1;
    fValue2 += 1;

    // Determine value from file for UI 'Size' field based on determined mnDirection
    ::tools::Long nValue;
    if( mnDirection == 1 )
        nValue = static_cast<::tools::Long>(fValue1 * 100.0);
    else if( mnDirection == 2 )
        nValue = static_cast<::tools::Long>(fValue2 * 100.0);
    else if( mnDirection == 3 ){
        if (fValue1 >= fValue2)
            nValue = static_cast<::tools::Long>(fValue1 * 100.0);
        else
            nValue = static_cast<::tools::Long>(fValue2 * 100.0);
    }
    else
        nValue = static_cast<::tools::Long>(100.0); // default to 100% in UI if something goes wrong

    mxMetric->set_value(nValue, FieldUnit::PERCENT);
    updateMenu();
}

Any SdScalePropertyBox::getValue()
{
    double fValue1 = static_cast<double>(mxMetric->get_value(FieldUnit::PERCENT)) / 100.0;

    // Grow and Shrink Animation is a relative change with value stored in content.xml under tag
    // smil:by=*,*
    // An offset of 1 must be subtracted to properly translate UI value displayed and save to
    // content.xml
    // e.g. if UI value is 150% then  1.5 - 1 = 0.5 and is set to smil:by=0.5,0.5 in content.xml
    // e.g. if UI value is 50% then  0.5 - 1 = -0.5 and is set to smil:by=-0.5,-0.5 in content.xml
    fValue1 -= 1;

    double fValue2 = fValue1;

    // mnDirection set by 'Size' drop down menu and used to zero out either horizontal or vertical
    // scaling depending on what option is selected
    if( mnDirection == 1 )
        fValue2 = 0.0;
    else if( mnDirection == 2 )
        fValue1 = 0.0;

    ValuePair aValues;
    aValues.First <<= fValue1;
    aValues.Second <<= fValue2;

    return Any( aValues );
}

namespace {

class SdFontStylePropertyBox : public SdPropertySubControl
{
public:
    SdFontStylePropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl);

    virtual Any getValue() override;
    virtual void setValue( const Any& rValue, const OUString& ) override;

    DECL_LINK(implMenuSelectHdl, const OUString&, void);

    void update();

private:
    float mfFontWeight;
    awt::FontSlant meFontSlant;
    sal_Int16 mnFontUnderline;
    Link<LinkParamNone*,void> maModifyHdl;

    std::unique_ptr<weld::Entry> mxEdit;
    std::unique_ptr<weld::MenuButton> mxControl;
};

}

SdFontStylePropertyBox::SdFontStylePropertyBox(weld::Label* pLabel, weld::Container* pParent, const Any& rValue, const Link<LinkParamNone*,void>& rModifyHdl )
    : SdPropertySubControl(pParent)
    , maModifyHdl( rModifyHdl )
    , mxEdit(mxBuilder->weld_entry(u"entry"_ustr))
    , mxControl(mxBuilder->weld_menu_button(u"entrymenu"_ustr))
{
    mxEdit->set_text(SdResId(STR_CUSTOMANIMATION_SAMPLE));
    mxEdit->set_help_id(HID_SD_CUSTOMANIMATIONPANE_FONTSTYLEPROPERTYBOX);
    pLabel->set_mnemonic_widget(mxEdit.get());
    mxEdit->show();

    mxControl->connect_selected(LINK(this, SdFontStylePropertyBox, implMenuSelectHdl));
    mxControl->set_help_id(HID_SD_CUSTOMANIMATIONPANE_FONTSTYLEPROPERTYBOX);
    mxControl->show();

    setValue(rValue, OUString());
}

void SdFontStylePropertyBox::update()
{
    // update menu
    mxControl->set_item_active(u"bold"_ustr, mfFontWeight == awt::FontWeight::BOLD);
    mxControl->set_item_active(u"italic"_ustr, meFontSlant == awt::FontSlant_ITALIC);
    mxControl->set_item_active(u"underline"_ustr, mnFontUnderline != awt::FontUnderline::NONE );

    // update sample edit
    vcl::Font aFont(mxEdit->get_font());
    aFont.SetWeight(mfFontWeight == awt::FontWeight::BOLD ? WEIGHT_BOLD : WEIGHT_NORMAL);
    aFont.SetItalic(meFontSlant == awt::FontSlant_ITALIC ? ITALIC_NORMAL : ITALIC_NONE);
    aFont.SetUnderline(mnFontUnderline == awt::FontUnderline::NONE ? LINESTYLE_NONE : LINESTYLE_SINGLE);
    mxEdit->set_font(aFont);
}

IMPL_LINK(SdFontStylePropertyBox, implMenuSelectHdl, const OUString&, rIdent, void)
{
    if (rIdent == "bold")
    {
        if( mfFontWeight == awt::FontWeight::BOLD )
            mfFontWeight = awt::FontWeight::NORMAL;
        else
            mfFontWeight = awt::FontWeight::BOLD;
    }
    else if (rIdent == "italic")
    {
        if( meFontSlant == awt::FontSlant_ITALIC )
            meFontSlant = awt::FontSlant_NONE;
        else
            meFontSlant = awt::FontSlant_ITALIC;
    }
    else if (rIdent == "underline")
    {
        if( mnFontUnderline == awt::FontUnderline::SINGLE )
            mnFontUnderline = awt::FontUnderline::NONE;
        else
            mnFontUnderline = awt::FontUnderline::SINGLE;
    }

    update();
    maModifyHdl.Call(nullptr);
}

void SdFontStylePropertyBox::setValue( const Any& rValue, const OUString& )
{
    Sequence<Any> aValues;
    rValue >>= aValues;

    aValues[0] >>= mfFontWeight;
    aValues[1] >>= meFontSlant;
    aValues[2] >>= mnFontUnderline;

    update();
}

Any SdFontStylePropertyBox::getValue()
{
    Sequence<Any> aValues{ Any(mfFontWeight), Any(meFontSlant), Any(mnFontUnderline) };
    return Any( aValues );
}

class CustomAnimationEffectTabPage
{
public:
    CustomAnimationEffectTabPage(weld::Container* pParent, weld::Window* pDialog, const STLPropertySet* pSet);

    void update( STLPropertySet* pSet );
    DECL_LINK(implSelectHdl, weld::ComboBox&, void);
    DECL_LINK(implClickHdl, weld::Button&, void);
    void implHdl(const weld::Widget*);

private:
    void updateControlStates();
    void fillSoundListBox();
    void clearSoundListBox();
    sal_Int32 getSoundObject( std::u16string_view rStr );
    void openSoundFileDialog();
    void onSoundPreview();
    weld::Window* GetFrameWeld() const { return mpDialog; }

private:
    ::std::vector< OUString > maSoundList;
    bool mbHasText;
    const STLPropertySet* mpSet;
    css::uno::Reference<css::media::XPlayer> mxPlayer;

    weld::Window* mpDialog;
    std::unique_ptr<weld::Builder> mxBuilder;
    std::unique_ptr<weld::Container> mxContainer;
    std::unique_ptr<weld::Widget> mxSettings;
    std::unique_ptr<weld::Label> mxFTProperty1;
    std::unique_ptr<weld::Container> mxPlaceholderBox;
    std::unique_ptr<weld::CheckButton> mxCBSmoothStart;
    std::unique_ptr<weld::CheckButton> mxCBSmoothEnd;
    std::unique_ptr<weld::Label> mxFTSound;
    std::unique_ptr<weld::ComboBox> mxLBSound;
    std::unique_ptr<weld::Button> mxPBSoundPreview;
    std::unique_ptr<weld::ComboBox> mxLBAfterEffect;
    std::unique_ptr<weld::Label> mxFTDimColor;
    std::unique_ptr<ColorListBox> mxCLBDimColor;
    std::unique_ptr<weld::Label> mxFTTextAnim;
    std::unique_ptr<weld::ComboBox> mxLBTextAnim;
    std::unique_ptr<weld::MetricSpinButton> mxMFTextDelay;
    std::unique_ptr<weld::Label> mxFTTextDelay;
    std::unique_ptr<SdPropertySubControl> mxLBSubControl;
};

CustomAnimationEffectTabPage::CustomAnimationEffectTabPage(weld::Container* pParent, weld::Window* pDialog, const STLPropertySet* pSet)
    : mbHasText(false)
    , mpSet(pSet)
    , mpDialog(pDialog)
    , mxBuilder(Application::CreateBuilder(pParent, u"modules/simpress/ui/customanimationeffecttab.ui"_ustr))
    , mxContainer(mxBuilder->weld_container(u"EffectTab"_ustr))
    , mxSettings(mxBuilder->weld_widget(u"settings"_ustr))
    , mxFTProperty1(mxBuilder->weld_label(u"prop_label1"_ustr))
    , mxPlaceholderBox(mxBuilder->weld_container(u"placeholder"_ustr))
    , mxCBSmoothStart(mxBuilder->weld_check_button(u"smooth_start"_ustr))
    , mxCBSmoothEnd(mxBuilder->weld_check_button(u"smooth_end"_ustr))
    , mxFTSound(mxBuilder->weld_label(u"sound_label"_ustr))
    , mxLBSound(mxBuilder->weld_combo_box(u"sound_list"_ustr))
    , mxPBSoundPreview(mxBuilder->weld_button(u"sound_preview"_ustr))
    , mxLBAfterEffect(mxBuilder->weld_combo_box(u"aeffect_list"_ustr))
    , mxFTDimColor(mxBuilder->weld_label(u"dim_color_label"_ustr))
    , mxCLBDimColor(new ColorListBox(mxBuilder->weld_menu_button(u"dim_color_list"_ustr), [pDialog]{ return pDialog; }))
    , mxFTTextAnim(mxBuilder->weld_label(u"text_animation_label"_ustr))
    , mxLBTextAnim(mxBuilder->weld_combo_box(u"text_animation_list"_ustr))
    , mxMFTextDelay(mxBuilder->weld_metric_spin_button(u"text_delay"_ustr, FieldUnit::PERCENT))
    , mxFTTextDelay(mxBuilder->weld_label(u"text_delay_label"_ustr))
{
    mxCLBDimColor->SelectEntry(COL_BLACK);

    // fill the soundbox
    fillSoundListBox();

    mxLBSound->connect_changed(LINK(this, CustomAnimationEffectTabPage, implSelectHdl));
    mxPBSoundPreview->connect_clicked(LINK(this, CustomAnimationEffectTabPage, implClickHdl));

    // only show settings if all selected effects have the same preset-id
    if( pSet->getPropertyState( nHandlePresetId ) != STLPropertyState::Ambiguous )
    {
        OUString aPresetId;
        pSet->getPropertyValue( nHandlePresetId ) >>= aPresetId;

        // property 1

        if( pSet->getPropertyState( nHandleProperty1Type ) != STLPropertyState::Ambiguous )
        {
            sal_Int32 nType = 0;
            pSet->getPropertyValue( nHandleProperty1Type ) >>= nType;

            if( nType != nPropertyTypeNone )
            {
                // set ui name for property at fixed text
                OUString aPropertyName( getPropertyName( nType ) );

                if( !aPropertyName.isEmpty() )
                {
                    mxSettings->show();
                    mxFTProperty1->set_label(aPropertyName);
                }

                // get property value
                const Any aValue( pSet->getPropertyValue( nHandleProperty1Value ) );

                // create property sub control
                mxLBSubControl = SdPropertySubControl::create(nType, mxFTProperty1.get(), mxPlaceholderBox.get(), mpDialog, aValue, aPresetId, Link<LinkParamNone*,void>());
            }
        }

        mxFTProperty1->set_sensitive(mxPlaceholderBox->get_sensitive());

        // accelerate & decelerate

        if( pSet->getPropertyState( nHandleAccelerate ) == STLPropertyState::Direct )
        {
            mxCBSmoothStart->show();
            mxCBSmoothEnd->show();

            double fTemp = 0.0;
            pSet->getPropertyValue( nHandleAccelerate ) >>= fTemp;
            mxCBSmoothStart->set_active( fTemp > 0.0 );

            pSet->getPropertyValue( nHandleDecelerate ) >>= fTemp;
            mxCBSmoothEnd->set_active( fTemp > 0.0 );
        }
    }

    // init after effect controls

    mxLBAfterEffect->connect_changed(LINK(this, CustomAnimationEffectTabPage, implSelectHdl));
    mxLBTextAnim->connect_changed(LINK(this, CustomAnimationEffectTabPage, implSelectHdl));

    if( (pSet->getPropertyState( nHandleHasAfterEffect ) != STLPropertyState::Ambiguous) &&
        (pSet->getPropertyState( nHandleAfterEffectOnNextEffect ) != STLPropertyState::Ambiguous) &&
        (pSet->getPropertyState( nHandleDimColor ) != STLPropertyState::Ambiguous))
    {
        bool bHasAfterEffect = false;
        pSet->getPropertyValue( nHandleHasAfterEffect ) >>= bHasAfterEffect;

        sal_Int32 nPos = 0;
        if( bHasAfterEffect )
        {
            nPos++;

            bool bAfterEffectOnNextClick = false;
            pSet->getPropertyValue( nHandleAfterEffectOnNextEffect ) >>= bAfterEffectOnNextClick;
            Any aDimColor( pSet->getPropertyValue( nHandleDimColor ) );

            if( aDimColor.hasValue() )
            {
                Color aColor;
                aDimColor >>= aColor;
                mxCLBDimColor->SelectEntry(aColor);
            }
            else
            {
                nPos++;
                if( bAfterEffectOnNextClick )
                    nPos++;
            }
        }

        mxLBAfterEffect->set_active(nPos);
    }

    if( pSet->getPropertyState( nHandleHasText ) != STLPropertyState::Ambiguous )
        pSet->getPropertyValue( nHandleHasText ) >>= mbHasText;

    if( mbHasText )
    {
        if( pSet->getPropertyState( nHandleIterateType ) != STLPropertyState::Ambiguous)
        {
            int nPos = -1;

            sal_Int32 nIterateType = 0;
            pSet->getPropertyValue( nHandleIterateType ) >>= nIterateType;
            switch( nIterateType )
            {
            case TextAnimationType::BY_PARAGRAPH:   nPos = 0; break;
            case TextAnimationType::BY_WORD:        nPos = 1; break;
            case TextAnimationType::BY_LETTER:      nPos = 2; break;
            }

            mxLBTextAnim->set_active(nPos);
        }

        if( pSet->getPropertyState( nHandleIterateInterval ) != STLPropertyState::Default )
        {
            double fIterateInterval = 0.0;
            pSet->getPropertyValue( nHandleIterateInterval ) >>= fIterateInterval;
            mxMFTextDelay->set_value(static_cast<::tools::Long>(fIterateInterval*10), FieldUnit::NONE);
        }
    }
    else
    {
        mxFTTextAnim->set_sensitive(false);
        mxLBTextAnim->set_sensitive(false);
        mxMFTextDelay->set_sensitive(false);
        mxFTTextDelay->set_sensitive(false);

    }

    if( pSet->getPropertyState( nHandleSoundURL ) != STLPropertyState::Ambiguous )
    {
        sal_Int32 nPos = 0;

        const Any aValue( pSet->getPropertyValue( nHandleSoundURL ) );

        if( aValue.getValueType() == ::cppu::UnoType<sal_Bool>::get() )
        {
            nPos = 1;
        }
        else
        {
            OUString aSoundURL;
            aValue >>= aSoundURL;

            if( !aSoundURL.isEmpty() )
            {
                sal_uLong i;
                for( i = 0; i < maSoundList.size(); i++ )
                {
                    OUString aString = maSoundList[ i ];
                    if( aString == aSoundURL )
                    {
                        nPos = static_cast<sal_Int32>(i)+2;
                        break;
                    }
                }

                if( nPos == 0 )
                {
                    nPos = static_cast<sal_Int32>(maSoundList.size())+2;
                    maSoundList.push_back( aSoundURL );
                    INetURLObject aURL( aSoundURL );
                    mxLBSound->insert_text(nPos, aURL.GetBase());
                }
            }
        }

        if( nPos != -1)
            mxLBSound->set_active(nPos);
    }

    updateControlStates();

}

void CustomAnimationEffectTabPage::updateControlStates()
{
    auto nPos = mxLBAfterEffect->get_active();
    mxCLBDimColor->set_sensitive( nPos == 1 );
    mxFTDimColor->set_sensitive( nPos == 1 );

    if( mbHasText )
    {
        nPos = mxLBTextAnim->get_active();
        mxMFTextDelay->set_sensitive( nPos != 0 );
        mxFTTextDelay->set_sensitive( nPos != 0 );
    }

    if (comphelper::LibreOfficeKit::isActive())
    {
        mxFTSound->hide();
        mxLBSound->hide();
        mxPBSoundPreview->hide();
    }
    else
    {
        nPos = mxLBSound->get_active();
        mxPBSoundPreview->set_sensitive( nPos >= 2 );
    }

}

IMPL_LINK(CustomAnimationEffectTabPage, implClickHdl, weld::Button&, rBtn, void)
{
    implHdl(&rBtn);
}

IMPL_LINK(CustomAnimationEffectTabPage, implSelectHdl, weld::ComboBox&, rListBoxvoid)
{
    implHdl(&rListBox);
}

void CustomAnimationEffectTabPage::implHdl(const weld::Widget* pControl)
{
    if (pControl == mxLBTextAnim.get())
    {
        if (mxMFTextDelay->get_value(FieldUnit::NONE) == 0)
            mxMFTextDelay->set_value(100, FieldUnit::NONE);
    }
    else if (pControl == mxLBSound.get())
    {
        auto nPos = mxLBSound->get_active();
        if (nPos == (mxLBSound->get_count() - 1))
        {
            openSoundFileDialog();
        }
    }
    else if (pControl == mxPBSoundPreview.get())
    {
        onSoundPreview();
    }

    updateControlStates();
}

void CustomAnimationEffectTabPage::update( STLPropertySet* pSet )
{
    if (mxLBSubControl)
    {
        Any aNewValue(mxLBSubControl->getValue());
        Any aOldValue;
        if( mpSet->getPropertyState( nHandleProperty1Value ) != STLPropertyState::Ambiguous)
            aOldValue = mpSet->getPropertyValue( nHandleProperty1Value );

        if( aOldValue != aNewValue )
            pSet->setPropertyValue( nHandleProperty1Value, aNewValue );
    }

    if (mxCBSmoothStart->get_visible())
    {
        // set selected value for accelerate if different than in original set

        double fTemp = mxCBSmoothStart->get_active() ? 0.5 : 0.0;

        double fOldTemp = 0.0;
        if(mpSet->getPropertyState( nHandleAccelerate ) != STLPropertyState::Ambiguous)
            mpSet->getPropertyValue( nHandleAccelerate ) >>= fOldTemp;
        else
            fOldTemp = -2.0;

        if( fOldTemp != fTemp )
            pSet->setPropertyValue( nHandleAccelerate, Any( fTemp ) );

        // set selected value for decelerate if different than in original set
        fTemp = mxCBSmoothEnd->get_active() ? 0.5 : 0.0;

        if(mpSet->getPropertyState( nHandleDecelerate ) != STLPropertyState::Ambiguous)
            mpSet->getPropertyValue( nHandleDecelerate ) >>= fOldTemp;
        else
            fOldTemp = -2.0;

        if( fOldTemp != fTemp )
            pSet->setPropertyValue( nHandleDecelerate, Any( fTemp ) );
    }

    auto nPos = mxLBAfterEffect->get_active();
    if (nPos != -1)
    {
        bool bAfterEffect = nPos != 0;

        bool bOldAfterEffect = false;

        if(mpSet->getPropertyState( nHandleHasAfterEffect ) != STLPropertyState::Ambiguous)
            mpSet->getPropertyValue( nHandleHasAfterEffect ) >>= bOldAfterEffect;
        else
            bOldAfterEffect = !bAfterEffect;

        if( bOldAfterEffect != bAfterEffect )
            pSet->setPropertyValue( nHandleHasAfterEffect, Any( bAfterEffect ) );

        Any aDimColor;
        if( nPos == 1 )
        {
            Color aSelectedColor = mxCLBDimColor->GetSelectEntryColor();
            aDimColor <<= aSelectedColor.GetRGBColor();
        }

        if( (mpSet->getPropertyState( nHandleDimColor ) == STLPropertyState::Ambiguous) ||
            (mpSet->getPropertyValue( nHandleDimColor ) != aDimColor) )
            pSet->setPropertyValue( nHandleDimColor, aDimColor );

        bool bAfterEffectOnNextEffect = nPos != 2;
        bool bOldAfterEffectOnNextEffect = !bAfterEffectOnNextEffect;

        if( mpSet->getPropertyState( nHandleAfterEffectOnNextEffect ) != STLPropertyState::Ambiguous)
            mpSet->getPropertyValue( nHandleAfterEffectOnNextEffect ) >>= bOldAfterEffectOnNextEffect;

        if( bAfterEffectOnNextEffect != bOldAfterEffectOnNextEffect )
            pSet->setPropertyValue( nHandleAfterEffectOnNextEffect, Any( bAfterEffectOnNextEffect ) );
    }

    nPos = mxLBTextAnim->get_active();
    if (nPos != -1)
    {
        sal_Int16 nIterateType;

        switch( nPos )
        {
        case 1: nIterateType = TextAnimationType::BY_WORD; break;
        case 2: nIterateType = TextAnimationType::BY_LETTER; break;
        default:
            nIterateType = TextAnimationType::BY_PARAGRAPH;
        }

        sal_Int16 nOldIterateType = nIterateType-1;

        if(mpSet->getPropertyState( nHandleIterateType ) != STLPropertyState::Ambiguous)
            mpSet->getPropertyValue( nHandleIterateType ) >>= nOldIterateType;

        if( nIterateType != nOldIterateType )
            pSet->setPropertyValue( nHandleIterateType, Any( nIterateType ) );
    }

    {
        double fIterateInterval = static_cast<double>(mxMFTextDelay->get_value(FieldUnit::NONE)) / 10;
        double fOldIterateInterval = -1.0;

        if( mpSet->getPropertyState( nHandleIterateInterval ) != STLPropertyState::Ambiguous )
            mpSet->getPropertyValue( nHandleIterateInterval ) >>= fOldIterateInterval;

        if( fIterateInterval != fOldIterateInterval )
            pSet->setPropertyValue( nHandleIterateInterval, Any( fIterateInterval ) );
    }

    nPos = mxLBSound->get_active();
    if (nPos == -1)
        return;

    Any aNewSoundURL, aOldSoundURL( Any( sal_Int32(0) ) );

    if( nPos == 0 )
    {
        // 0 means no sound, so leave any empty
    }
    else if( nPos == 1 )
    {
        // this means stop sound
        aNewSoundURL <<= true;
    }
    else
    {
        OUString aSoundURL( maSoundList[ nPos-2 ] );
        aNewSoundURL <<= aSoundURL;
    }

    if( mpSet->getPropertyState( nHandleSoundURL ) != STLPropertyState::Ambiguous )
        aOldSoundURL = mpSet->getPropertyValue( nHandleSoundURL  );

    if( aNewSoundURL != aOldSoundURL )
        pSet->setPropertyValue( nHandleSoundURL, aNewSoundURL );
}

void CustomAnimationEffectTabPage::fillSoundListBox()
{
    GalleryExplorer::FillObjList( GALLERY_THEME_SOUNDS, maSoundList );
    GalleryExplorer::FillObjList( GALLERY_THEME_USERSOUNDS, maSoundList );

    mxLBSound->append_text( SdResId(STR_CUSTOMANIMATION_NO_SOUND) );
    mxLBSound->append_text( SdResId(STR_CUSTOMANIMATION_STOP_PREVIOUS_SOUND) );
    for(const OUString & rString : maSoundList)
    {
        INetURLObject aURL( rString );
        mxLBSound->append_text( aURL.GetBase() );
    }
    mxLBSound->append_text( SdResId(STR_CUSTOMANIMATION_BROWSE_SOUND) );
}

void CustomAnimationEffectTabPage::clearSoundListBox()
{
    maSoundList.clear();
    mxLBSound->clear();
}

sal_Int32 CustomAnimationEffectTabPage::getSoundObject( std::u16string_view rStr )
{
    size_t i;
    const size_t nCount = maSoundList.size();
    for( i = 0; i < nCount; i++ )
    {
        if( maSoundList[ i ].equalsIgnoreAsciiCase(rStr) )
            return i+2;
    }

    return -1;
}

void CustomAnimationEffectTabPage::openSoundFileDialog()
{
    SdOpenSoundFileDialog aFileDialog(GetFrameWeld());

    bool bValidSoundFile = false;
    bool bQuitLoop = false;
    ::tools::Long nPos = 0;

    while( !bQuitLoop && (aFileDialog.Execute() == ERRCODE_NONE) )
    {
        OUString aFile = aFileDialog.GetPath();
        nPos = getSoundObject( aFile );

        if( nPos < 0 ) // not in Soundliste
        {
            // try to insert in Gallery
            if( GalleryExplorer::InsertURL( GALLERY_THEME_USERSOUNDS, aFile ) )
            {
                clearSoundListBox();
                fillSoundListBox();

                nPos = getSoundObject( aFile );
                DBG_ASSERT( nPos >= 0, "sd::CustomAnimationEffectTabPage::openSoundFileDialog(), Recently inserted sound not in list!" );

                bValidSoundFile=true;
                bQuitLoop=true;
            }
            else
            {
                OUString aStrWarning(SdResId(STR_WARNING_NOSOUNDFILE));
                aStrWarning = aStrWarning.replaceFirst("%", aFile);
                std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(nullptr,
                                                           VclMessageType::Warning, VclButtonsType::NONE,
                                                           aStrWarning));
                xWarn->add_button(GetStandardText(StandardButtonType::Retry), RET_RETRY);
                xWarn->add_button(GetStandardText(StandardButtonType::Cancel), RET_CANCEL);
                bQuitLoop = xWarn->run() != RET_RETRY;

                bValidSoundFile=false;
            }
        }
        else
        {
            bValidSoundFile=true;
            bQuitLoop=true;
        }
    }

    if( !bValidSoundFile )
        nPos = 0;

    mxLBSound->set_active(nPos);
}

void CustomAnimationEffectTabPage::onSoundPreview()
{
#if HAVE_FEATURE_AVMEDIA
    const auto nPos = mxLBSound->get_active();

    if( nPos >= 2 ) try
    {
        const OUString aSoundURL( maSoundList[ nPos-2 ] );
        mxPlayer.set( avmedia::MediaWindow::createPlayer( aSoundURL, u""_ustr ), uno::UNO_SET_THROW );
        mxPlayer->start();
    }
    catch( uno::Exception& )
    {
        TOOLS_WARN_EXCEPTION( "sd""CustomAnimationEffectTabPage::onSoundPreview()" );
    }
#endif
}

class CustomAnimationDurationTabPage
{
public:
    CustomAnimationDurationTabPage(weld::Container* pParent, const STLPropertySet* pSet);

    void update( STLPropertySet* pSet );

    DECL_LINK(implControlHdl, weld::ComboBox&, void);
    DECL_LINK(DurationModifiedHdl, weld::MetricSpinButton&, void);

private:
    const STLPropertySet* mpSet;

    std::unique_ptr<weld::Builder> mxBuilder;
    std::unique_ptr<weld::Container> mxContainer;
    std::unique_ptr<weld::ComboBox> mxLBStart;
    std::unique_ptr<weld::MetricSpinButton> mxMFStartDelay;
    std::unique_ptr<weld::Label> mxFTDuration;
    std::unique_ptr<weld::MetricSpinButton> mxCBXDuration;
    std::unique_ptr<weld::Label> mxFTRepeat;
    std::unique_ptr<weld::ComboBox> mxCBRepeat;
    std::unique_ptr<weld::CheckButton> mxCBXRewind;
    std::unique_ptr<weld::RadioButton> mxRBClickSequence;
    std::unique_ptr<weld::RadioButton> mxRBInteractive;
    std::unique_ptr<weld::ComboBox> mxLBTrigger;
};

CustomAnimationDurationTabPage::CustomAnimationDurationTabPage(weld::Container* pParent, const STLPropertySet* pSet)
    : mpSet(pSet)
    , mxBuilder(Application::CreateBuilder(pParent, u"modules/simpress/ui/customanimationtimingtab.ui"_ustr))
    , mxContainer(mxBuilder->weld_container(u"TimingTab"_ustr))
    , mxLBStart(mxBuilder->weld_combo_box(u"start_list"_ustr))
    , mxMFStartDelay(mxBuilder->weld_metric_spin_button(u"delay_value"_ustr, FieldUnit::SECOND))
    , mxFTDuration(mxBuilder->weld_label(u"duration_label"_ustr))
    , mxCBXDuration(mxBuilder->weld_metric_spin_button(u"anim_duration"_ustr, FieldUnit::SECOND))
    , mxFTRepeat(mxBuilder->weld_label(u"repeat_label"_ustr))
    , mxCBRepeat(mxBuilder->weld_combo_box(u"repeat_list"_ustr))
    , mxCBXRewind(mxBuilder->weld_check_button(u"rewind"_ustr))
    , mxRBClickSequence(mxBuilder->weld_radio_button(u"rb_click_sequence"_ustr))
    , mxRBInteractive(mxBuilder->weld_radio_button(u"rb_interactive"_ustr))
    , mxLBTrigger(mxBuilder->weld_combo_box(u"trigger_list"_ustr))
{
    mxLBTrigger->set_size_request(mxLBTrigger->get_approximate_digit_width() * 20, -1);

    fillRepeatComboBox(*mxCBRepeat);

    mxLBTrigger->connect_changed(LINK(this, CustomAnimationDurationTabPage, implControlHdl));
    mxCBXDuration->connect_value_changed(LINK( this, CustomAnimationDurationTabPage, DurationModifiedHdl));

    if( pSet->getPropertyState( nHandleStart ) != STLPropertyState::Ambiguous )
    {
        sal_Int16 nStart = 0;
        pSet->getPropertyValue( nHandleStart ) >>= nStart;
        sal_Int32 nPos = 0;
        switch( nStart )
        {
            case EffectNodeType::WITH_PREVIOUS:     nPos = 1; break;
            case EffectNodeType::AFTER_PREVIOUS:    nPos = 2; break;
        }
        mxLBStart->set_active(nPos);
    }

    if( pSet->getPropertyState( nHandleBegin ) != STLPropertyState::Ambiguous )
    {
        double fBegin = 0.0;
        pSet->getPropertyValue( nHandleBegin ) >>= fBegin;
        mxMFStartDelay->set_value(static_cast<::tools::Long>(fBegin*10), FieldUnit::NONE);
    }

    if( pSet->getPropertyState( nHandleDuration ) != STLPropertyState::Ambiguous )
    {
        double fDuration = 0.0;
        pSet->getPropertyValue( nHandleDuration ) >>= fDuration;

        if( fDuration == 0.001 )
        {
            mxFTDuration->set_sensitive(false);
            mxCBXDuration->set_sensitive(false);
            mxFTRepeat->set_sensitive(false);
            mxCBRepeat->set_sensitive(false);
            mxCBXRewind->set_sensitive(false);
        }
        else
        {
            mxCBXDuration->set_value(fDuration * 100.0, FieldUnit::NONE);
        }
    }

    if( pSet->getPropertyState( nHandleRepeat ) != STLPropertyState::Ambiguous )
    {
        Any aRepeatCount( pSet->getPropertyValue( nHandleRepeat ) );
        if( (aRepeatCount.getValueType() == ::cppu::UnoType<double>::get()) || !aRepeatCount.hasValue() )
        {
            double fRepeat = 0.0;
            if( aRepeatCount.hasValue() )
                aRepeatCount >>= fRepeat;

            auto nPos = -1;

            if( fRepeat == 0 )
                nPos = 0;
            else if( fRepeat == 2.0 )
                nPos = 1;
            else if( fRepeat == 3.0 )
                nPos = 2;
            else if( fRepeat == 4.0 )
                nPos = 3;
            else if( fRepeat == 5.0 )
                nPos = 4;
            else if( fRepeat == 10.0 )
                nPos = 5;

            if (nPos != -1)
                mxCBRepeat->set_active(nPos);
            else
                mxCBRepeat->set_entry_text(OUString::number(fRepeat));
        }
        else if( aRepeatCount.getValueType() == ::cppu::UnoType<Timing>::get() )
        {
            Any aEnd;
            if( pSet->getPropertyState( nHandleEnd ) != STLPropertyState::Ambiguous )
                aEnd = pSet->getPropertyValue( nHandleEnd );

            mxCBRepeat->set_active(aEnd.hasValue() ? 6 : 7);
        }
    }

    if( pSet->getPropertyState( nHandleRewind ) != STLPropertyState::Ambiguous )
    {
        sal_Int16 nFill = 0;
        if( pSet->getPropertyValue( nHandleRewind ) >>= nFill )
        {
            mxCBXRewind->set_active(nFill == AnimationFill::REMOVE);
        }
        else
        {
            mxCBXRewind->set_state(TRISTATE_INDET);
        }
    }

    Reference< XShape > xTrigger;

    if( pSet->getPropertyState( nHandleTrigger ) != STLPropertyState::Ambiguous )
    {
        pSet->getPropertyValue( nHandleTrigger ) >>= xTrigger;

        mxRBInteractive->set_active(xTrigger.is());
        mxRBClickSequence->set_active(!xTrigger.is());
    }

    Reference< XDrawPage > xCurrentPage;
    pSet->getPropertyValue( nHandleCurrentPage ) >>= xCurrentPage;
    if( !xCurrentPage.is() )
        return;

    static constexpr OUString aStrIsEmptyPresObj( u"IsEmptyPresentationObject"_ustr );

    sal_Int32 nShape, nCount = xCurrentPage->getCount();
    for( nShape = 0; nShape < nCount; nShape++ )
    {
        Reference< XShape > xShape( xCurrentPage->getByIndex( nShape ), UNO_QUERY );

        if( !xShape.is() )
            continue;

        Reference< XPropertySet > xSet( xShape, UNO_QUERY );
        if( xSet.is() && xSet->getPropertySetInfo()->hasPropertyByName( aStrIsEmptyPresObj ) )
        {
            bool bIsEmpty = false;
            xSet->getPropertyValue( aStrIsEmptyPresObj ) >>= bIsEmpty;
            if( bIsEmpty )
                continue;
        }

        OUString aDescription( getShapeDescription( xShape, true ) );
        mxLBTrigger->append(OUString::number(nShape), aDescription);
        auto nPos = mxLBTrigger->get_count() - 1;
        if (xShape == xTrigger)
            mxLBTrigger->set_active(nPos);
    }
}

IMPL_LINK_NOARG(CustomAnimationDurationTabPage, implControlHdl, weld::ComboBox&, ;void)
{
    mxRBInteractive->set_active(true);
    assert(!mxRBClickSequence->get_active());
}

IMPL_LINK_NOARG(CustomAnimationDurationTabPage, DurationModifiedHdl, weld::MetricSpinButton&, void)
{
    if (!mxCBXDuration->get_text().isEmpty())
    {
        double duration_value = static_cast<double>(mxCBXDuration->get_value(FieldUnit::NONE));
        if(duration_value <= 0.0)
            mxCBXDuration->set_value(1, FieldUnit::NONE);
        else
            mxCBXDuration->set_value(duration_value, FieldUnit::NONE);
    }
}

void CustomAnimationDurationTabPage::update( STLPropertySet* pSet )
{
    auto nPos = mxLBStart->get_active();
    if (nPos != -1)
    {
        sal_Int16 nStart;
        sal_Int16 nOldStart = -1;

        switch( nPos )
        {
        case 1: nStart = EffectNodeType::WITH_PREVIOUS; break;
        case 2: nStart = EffectNodeType::AFTER_PREVIOUS; break;
        default:
            nStart = EffectNodeType::ON_CLICK; break;
        }

        if(mpSet->getPropertyState( nHandleStart ) != STLPropertyState::Ambiguous)
            mpSet->getPropertyValue( nHandleStart ) >>= nOldStart;

        if( nStart != nOldStart )
            pSet->setPropertyValue( nHandleStart, Any( nStart ) );
    }

    {
        double fBegin = static_cast<double>(mxMFStartDelay->get_value(FieldUnit::NONE)) / 10.0;
        double fOldBegin = -1.0;

        if( mpSet->getPropertyState( nHandleBegin ) != STLPropertyState::Ambiguous )
            mpSet->getPropertyValue( nHandleBegin ) >>= fOldBegin;

        if( fBegin != fOldBegin )
            pSet->setPropertyValue( nHandleBegin, Any( fBegin ) );
    }

    nPos = mxCBRepeat->get_active();
    if (nPos != -1 || !mxCBRepeat->get_active_text().isEmpty())
    {
        Any aRepeatCount;
        Any aEnd;

        switch( nPos )
        {
        case 0:
            break;

        case 6:
            {
                Event aEvent;
                aEvent.Trigger = EventTrigger::ON_NEXT;
                aEvent.Repeat = 0;
                aEnd <<= aEvent;
            }
            [[fallthrough]];
        case 7:
            aRepeatCount <<= Timing_INDEFINITE;
            break;
        default:
            {
                OUString aText(mxCBRepeat->get_text(nPos));
                if( !aText.isEmpty() )
                    aRepeatCount <<= aText.toDouble();
            }
        }

        Any aOldRepeatCount( aRepeatCount );
        if( mpSet->getPropertyState( nHandleRepeat ) != STLPropertyState::Ambiguous )
            aOldRepeatCount = mpSet->getPropertyValue( nHandleRepeat );

        if( aRepeatCount != aOldRepeatCount )
            pSet->setPropertyValue( nHandleRepeat, aRepeatCount );

        Any aOldEnd( aEnd );
        if( mpSet->getPropertyState( nHandleEnd ) != STLPropertyState::Ambiguous )
            aOldEnd = mpSet->getPropertyValue( nHandleEnd );

        if( aEnd != aOldEnd )
            pSet->setPropertyValue( nHandleEnd, aEnd );
    }

    double fDuration = -1.0;

    if (!mxCBXDuration->get_text().isEmpty())
    {
        double duration_value = static_cast<double>(mxCBXDuration->get_value(FieldUnit::NONE));

        if(duration_value > 0)
            fDuration = duration_value/100.0;
    }

    if( fDuration != -1.0 )
    {
        double fOldDuration = -1;

        if( mpSet->getPropertyState( nHandleDuration ) != STLPropertyState::Ambiguous )
            mpSet->getPropertyValue( nHandleDuration ) >>= fOldDuration;

        if( fDuration != fOldDuration )
            pSet->setPropertyValue( nHandleDuration, Any( fDuration ) );
    }

    if (mxCBXRewind->get_state() != TRISTATE_INDET)
    {
        sal_Int16 nFill = mxCBXRewind->get_active() ? AnimationFill::REMOVE : AnimationFill::HOLD;

        bool bSet = true;

        if( mpSet->getPropertyState( nHandleRewind ) != STLPropertyState::Ambiguous )
        {
            sal_Int16 nOldFill = 0;
            mpSet->getPropertyValue( nHandleRewind ) >>= nOldFill;
            bSet = nFill != nOldFill;
        }

        if( bSet )
            pSet->setPropertyValue( nHandleRewind, Any( nFill ) );
    }

    Reference< XShape > xTrigger;

    if (mxRBInteractive->get_active())
    {
        nPos = mxLBTrigger->get_active();
        if (nPos != -1)
        {
            sal_Int32 nShape = mxLBTrigger->get_id(nPos).toInt32();

            Reference< XDrawPage > xCurrentPage;
            mpSet->getPropertyValue( nHandleCurrentPage ) >>= xCurrentPage;

            if( xCurrentPage.is() && (nShape >= 0) && (nShape < xCurrentPage->getCount()) )
                xCurrentPage->getByIndex( nShape ) >>= xTrigger;
        }
    }

    if (xTrigger.is() || mxRBClickSequence->get_active())
    {
        Any aNewValue( xTrigger );
        Any aOldValue;

        if( mpSet->getPropertyState( nHandleTrigger ) != STLPropertyState::Ambiguous )
            aOldValue = mpSet->getPropertyValue( nHandleTrigger );

        if( aNewValue != aOldValue )
            pSet->setPropertyValue( nHandleTrigger, aNewValue );
    }
}

class CustomAnimationTextAnimTabPage
{
public:
    CustomAnimationTextAnimTabPage(weld::Container* pParent, const STLPropertySet* pSet);

    void update( STLPropertySet* pSet );

    void updateControlStates();
    DECL_LINK(implSelectHdl, weld::ComboBox&, void);

private:
    const STLPropertySet* mpSet;
    bool mbHasVisibleShapes;

    std::unique_ptr<weld::Builder> mxBuilder;
    std::unique_ptr<weld::Container> mxContainer;
    std::unique_ptr<weld::ComboBox> mxLBGroupText;
    std::unique_ptr<weld::CheckButton> mxCBXGroupAuto;
    std::unique_ptr<weld::MetricSpinButton> mxMFGroupAuto;
    std::unique_ptr<weld::CheckButton> mxCBXAnimateForm;
    std::unique_ptr<weld::CheckButton> mxCBXReverse;
};

CustomAnimationTextAnimTabPage::CustomAnimationTextAnimTabPage(weld::Container* pParent, const STLPropertySet* pSet)
    : mpSet(pSet)
    , mbHasVisibleShapes(true)
    , mxBuilder(Application::CreateBuilder(pParent, u"modules/simpress/ui/customanimationtexttab.ui"_ustr))
    , mxContainer(mxBuilder->weld_container(u"TextAnimationTab"_ustr))
    , mxLBGroupText(mxBuilder->weld_combo_box(u"group_text_list"_ustr))
    , mxCBXGroupAuto(mxBuilder->weld_check_button(u"auto_after"_ustr))
    , mxMFGroupAuto(mxBuilder->weld_metric_spin_button(u"auto_after_value"_ustr,FieldUnit::SECOND))
    , mxCBXAnimateForm(mxBuilder->weld_check_button(u"animate_shape"_ustr))
    , mxCBXReverse(mxBuilder->weld_check_button(u"reverse_order"_ustr))
{
    mxLBGroupText->connect_changed(LINK(this, CustomAnimationTextAnimTabPage, implSelectHdl));

    if( pSet->getPropertyState( nHandleTextGrouping ) != STLPropertyState::Ambiguous )
    {
        sal_Int32 nTextGrouping = 0;
        if( pSet->getPropertyValue( nHandleTextGrouping ) >>= nTextGrouping )
            mxLBGroupText->set_active(nTextGrouping + 1);
    }

    if( pSet->getPropertyState( nHandleHasVisibleShape ) != STLPropertyState::Ambiguous )
        pSet->getPropertyValue( nHandleHasVisibleShape ) >>= mbHasVisibleShapes;

    if( pSet->getPropertyState( nHandleTextGroupingAuto ) != STLPropertyState::Ambiguous )
    {
        double fTextGroupingAuto = 0.0;
        if( pSet->getPropertyValue( nHandleTextGroupingAuto ) >>= fTextGroupingAuto )
        {
            mxCBXGroupAuto->set_active(fTextGroupingAuto >= 0.0);
            if( fTextGroupingAuto >= 0.0 )
                mxMFGroupAuto->set_value(static_cast<::tools::Long>(fTextGroupingAuto*10), FieldUnit::NONE);
        }
    }
    else
    {
        mxCBXGroupAuto->set_state( TRISTATE_INDET );
    }

    mxCBXAnimateForm->set_state( TRISTATE_INDET );
    if( pSet->getPropertyState( nHandleAnimateForm ) != STLPropertyState::Ambiguous )
    {
        bool bAnimateForm = false;
        if( pSet->getPropertyValue( nHandleAnimateForm ) >>= bAnimateForm )
        {
            mxCBXAnimateForm->set_active( bAnimateForm );
        }
    }
    else
    {
        mxCBXAnimateForm->set_sensitive(false);
    }

    mxCBXReverse->set_state(TRISTATE_INDET);
    if( pSet->getPropertyState( nHandleTextReverse ) != STLPropertyState::Ambiguous )
    {
        bool bTextReverse = false;
        if( pSet->getPropertyValue( nHandleTextReverse ) >>= bTextReverse )
        {
            mxCBXReverse->set_active( bTextReverse );
        }
    }

    if( pSet->getPropertyState( nHandleMaxParaDepth ) == STLPropertyState::Direct )
    {
        sal_Int32 nMaxParaDepth = 0;
        pSet->getPropertyValue( nHandleMaxParaDepth ) >>= nMaxParaDepth;
        nMaxParaDepth += 1;

        sal_Int32 nPos = 6;
        while( (nPos > 2) && (nPos > nMaxParaDepth) )
        {
            mxLBGroupText->remove(nPos);
            nPos--;
        }
    }

    updateControlStates();
}

void CustomAnimationTextAnimTabPage::update( STLPropertySet* pSet )
{
    auto nPos = mxLBGroupText->get_active();
    if (nPos != -1)
    {
        sal_Int32 nTextGrouping = nPos - 1;
        sal_Int32 nOldGrouping = -2;

        if(mpSet->getPropertyState( nHandleTextGrouping ) != STLPropertyState::Ambiguous)
            mpSet->getPropertyValue( nHandleTextGrouping ) >>= nOldGrouping;

        if( nTextGrouping != nOldGrouping )
            pSet->setPropertyValue( nHandleTextGrouping, Any( nTextGrouping ) );
    }

    if (nPos != 0)
    {
        bool bTextReverse = mxCBXReverse->get_active();
        bool bOldTextReverse = !bTextReverse;

        if(mpSet->getPropertyState( nHandleTextReverse ) != STLPropertyState::Ambiguous)
            mpSet->getPropertyValue( nHandleTextReverse ) >>= bOldTextReverse;

        if( bTextReverse != bOldTextReverse )
            pSet->setPropertyValue( nHandleTextReverse, Any( bTextReverse ) );

        if( nPos > 1 )
        {
            double fTextGroupingAuto = mxCBXGroupAuto->get_active() ? mxMFGroupAuto->get_value(FieldUnit::NONE) / 10.0 : -1.0;
            double fOldTextGroupingAuto = -2.0;

            if(mpSet->getPropertyState( nHandleTextGroupingAuto ) != STLPropertyState::Ambiguous)
                mpSet->getPropertyValue( nHandleTextGroupingAuto ) >>= fOldTextGroupingAuto;

            if( fTextGroupingAuto != fOldTextGroupingAuto )
                pSet->setPropertyValue( nHandleTextGroupingAuto, Any( fTextGroupingAuto ) );
        }
    }
    //#i120049# impress crashes when modifying the "Random effects" animation
    //effect's trigger condition to "Start effect on click of".
    //If this control is disabled, we should ignore its value
    if (mxCBXAnimateForm->get_sensitive())
    {
        bool bAnimateForm = mxCBXAnimateForm->get_active();
        bool bOldAnimateForm = !bAnimateForm;

        if(mpSet->getPropertyState( nHandleAnimateForm ) != STLPropertyState::Ambiguous)
            mpSet->getPropertyValue( nHandleAnimateForm ) >>= bOldAnimateForm;

        if( bAnimateForm != bOldAnimateForm )
            pSet->setPropertyValue( nHandleAnimateForm, Any( bAnimateForm ) );
    }
}

void CustomAnimationTextAnimTabPage::updateControlStates()
{
    auto nPos = mxLBGroupText->get_active();

    mxCBXGroupAuto->set_sensitive( nPos > 1 );
    mxMFGroupAuto->set_sensitive( nPos > 1 );
    mxCBXReverse->set_sensitive( nPos > 0 );

    if( !mbHasVisibleShapes && nPos > 0 )
    {
        mxCBXAnimateForm->set_active(false);
        mxCBXAnimateForm->set_sensitive(false);
    }
    else
    {
        mxCBXAnimateForm->set_sensitive(true);
    }
}

IMPL_LINK_NOARG(CustomAnimationTextAnimTabPage, implSelectHdl, weld::ComboBox&, void)
{
    updateControlStates();
}

CustomAnimationDialog::CustomAnimationDialog(weld::Window* pParent, std::unique_ptr<STLPropertySet> pSet, const OUString& rPage)
    : GenericDialogController(pParent, u"modules/simpress/ui/customanimationproperties.ui"_ustr, u"CustomAnimationProperties"_ustr)
    , mxSet(std::move(pSet))
    , mxTabControl(m_xBuilder->weld_notebook(u"tabcontrol"_ustr))
    , mxDurationTabPage(new CustomAnimationDurationTabPage(mxTabControl->get_page(u"timing"_ustr), mxSet.get()))
    , mxEffectTabPage(new CustomAnimationEffectTabPage(mxTabControl->get_page(u"effect"_ustr), m_xDialog.get(), mxSet.get()))
{
    bool bHasText = false;
    if( mxSet->getPropertyState( nHandleHasText ) != STLPropertyState::Ambiguous )
        mxSet->getPropertyValue( nHandleHasText ) >>= bHasText;

    if( bHasText )
    {
        mxTextAnimTabPage.reset(new CustomAnimationTextAnimTabPage(mxTabControl->get_page(u"textanim"_ustr), mxSet.get()));
    }
    else
    {
        mxTabControl->remove_page(u"textanim"_ustr);
    }

    if (!rPage.isEmpty())
        mxTabControl->set_current_page(rPage);
}

CustomAnimationDialog::~CustomAnimationDialog()
{
}

STLPropertySet* CustomAnimationDialog::getResultSet()
{
    mxResultSet = createDefaultSet();

    mxEffectTabPage->update( mxResultSet.get() );
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.