tdf#87813: Moving effects list into the animation tab

Adding the animation effect -
1.Press the + button

Modifying the animation effect
1. Select the animation from the list of added animations
2. Select the animation style from the Listbox

Change-Id: I14f9242b9f04279622d879ae8c3e162ded6e3e3d
Reviewed-on: https://gerrit.libreoffice.org/17008
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Katarina Behrens <Katarina.Behrens@cib.de>
diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk
index 66dca43..c54bd6d 100644
--- a/sd/Library_sd.mk
+++ b/sd/Library_sd.mk
@@ -174,7 +174,7 @@ $(eval $(call gb_Library_add_exception_objects,sd,\
	sd/source/ui/accessibility/AccessibleSlideSorterView \
	sd/source/ui/accessibility/AccessibleViewForwarder \
	sd/source/ui/accessibility/SdShapeTypes \
	sd/source/ui/animations/CustomAnimationCreateDialog \
    sd/source/ui/animations/CategoryListBox \
	sd/source/ui/animations/CustomAnimationDialog \
	sd/source/ui/animations/CustomAnimationList \
	sd/source/ui/animations/CustomAnimationPane \
diff --git a/sd/UIConfig_simpress.mk b/sd/UIConfig_simpress.mk
index d42ef0a..a0d70e9 100644
--- a/sd/UIConfig_simpress.mk
+++ b/sd/UIConfig_simpress.mk
@@ -71,8 +71,6 @@ $(eval $(call gb_UIConfig_add_toolbarfiles,modules/simpress,\

$(eval $(call gb_UIConfig_add_uifiles,modules/simpress,\
	sd/uiconfig/simpress/ui/assistentdialog \
	sd/uiconfig/simpress/ui/customanimationcreatedialog \
	sd/uiconfig/simpress/ui/customanimationcreatetab \
	sd/uiconfig/simpress/ui/customanimationspanel \
	sd/uiconfig/simpress/ui/customanimationproperties \
	sd/uiconfig/simpress/ui/customanimationeffecttab \
diff --git a/sd/source/ui/animations/CategoryListBox.cxx b/sd/source/ui/animations/CategoryListBox.cxx
new file mode 100644
index 0000000..93364d4
--- /dev/null
+++ b/sd/source/ui/animations/CategoryListBox.cxx
@@ -0,0 +1,77 @@
#include "CategoryListBox.hxx"

namespace sd {

CategoryListBox::CategoryListBox( vcl::Window* pParent )
: ListBox( pParent, WB_TABSTOP | WB_BORDER )
{
    EnableUserDraw( true );
    SetDoubleClickHdl( LINK( this, CategoryListBox, implDoubleClickHdl ) );
}

VCL_BUILDER_FACTORY(CategoryListBox)

CategoryListBox::~CategoryListBox()
{
}

sal_Int32  CategoryListBox::InsertCategory( const OUString& rStr, sal_Int32  nPos /* = LISTBOX_APPEND */ )
{
    sal_Int32  n = ListBox::InsertEntry( rStr, nPos );
    if( n != LISTBOX_ENTRY_NOTFOUND )
        ListBox::SetEntryFlags( n, ListBox::GetEntryFlags(n) | ListBoxEntryFlags::DisableSelection );

    return n;
}

void CategoryListBox::UserDraw( const UserDrawEvent& rUDEvt )
{
    const sal_uInt16 nItem = rUDEvt.GetItemId();

    if( ListBox::GetEntryFlags(nItem) & ListBoxEntryFlags::DisableSelection )
    {
        Rectangle aOutRect( rUDEvt.GetRect() );
        vcl::RenderContext* pDev = rUDEvt.GetRenderContext();

        // fill the background
        Color aColor (GetSettings().GetStyleSettings().GetDialogColor());

        pDev->SetFillColor (aColor);
        pDev->SetLineColor ();
        pDev->DrawRect(aOutRect);

        // Erase the four corner pixels to make the rectangle appear rounded.
        pDev->SetLineColor( GetSettings().GetStyleSettings().GetWindowColor());
        pDev->DrawPixel( aOutRect.TopLeft());
        pDev->DrawPixel( Point(aOutRect.Right(), aOutRect.Top()));
        pDev->DrawPixel( Point(aOutRect.Left(), aOutRect.Bottom()));
        pDev->DrawPixel( Point(aOutRect.Right(), aOutRect.Bottom()));

        // draw the category title
        pDev->DrawText (aOutRect, GetEntry(nItem), DrawTextFlags::Center );
    }
    else
    {
        DrawEntry( rUDEvt, true, true );
    }
}

IMPL_LINK_NOARG_TYPED(CategoryListBox, implDoubleClickHdl, ListBox&, void)
{
    CaptureMouse();
}

void CategoryListBox::MouseButtonUp( const MouseEvent& rMEvt )
{
    ReleaseMouse();
    if( rMEvt.IsLeft() && (rMEvt.GetClicks() == 2) )
    {
        maDoubleClickHdl.Call( *this );
    }
    else
    {
        ListBox::MouseButtonUp( rMEvt );
    }
}

}
diff --git a/sd/source/ui/animations/CategoryListBox.hxx b/sd/source/ui/animations/CategoryListBox.hxx
new file mode 100644
index 0000000..4b9debb
--- /dev/null
+++ b/sd/source/ui/animations/CategoryListBox.hxx
@@ -0,0 +1,31 @@
#ifndef INCLUDED_SD_SOURCE_UI_ANIMATIONS_CATEGORYLISTBOX_HXX
#define INCLUDED_SD_SOURCE_UI_ANIMATIONS_CATEGORYLISTBOX_HXX

#include <vcl/lstbox.hxx>
#include <vcl/builderfactory.hxx>

namespace sd {

class CategoryListBox : public ListBox
{
public:
    CategoryListBox( vcl::Window* pParent );
    virtual ~CategoryListBox();

    virtual void        MouseButtonUp( const MouseEvent& rMEvt ) SAL_OVERRIDE;

    sal_Int32           InsertCategory( const OUString& rStr, sal_Int32  nPos = LISTBOX_APPEND );

    void                SetDoubleClickLink( const Link<CategoryListBox&,void>& rDoubleClickHdl ) { maDoubleClickHdl = rDoubleClickHdl; }

    DECL_LINK_TYPED(implDoubleClickHdl, ListBox&, void);

private:
    virtual void    UserDraw( const UserDrawEvent& rUDEvt ) SAL_OVERRIDE;

    Link<CategoryListBox&,void>     maDoubleClickHdl;
};

}

#endif
diff --git a/sd/source/ui/animations/CustomAnimationPane.cxx b/sd/source/ui/animations/CustomAnimationPane.cxx
index 3a23d71..9535844 100644
--- a/sd/source/ui/animations/CustomAnimationPane.cxx
+++ b/sd/source/ui/animations/CustomAnimationPane.cxx
@@ -40,7 +40,6 @@
#include "STLPropertySet.hxx"
#include "CustomAnimationPane.hxx"
#include "CustomAnimationDialog.hxx"
#include "CustomAnimationCreateDialog.hxx"
#include "CustomAnimation.hrc"
#include "CustomAnimationList.hxx"
#include "createcustomanimationpanel.hxx"
@@ -67,6 +66,7 @@
#include "undoanim.hxx"
#include "optsitem.hxx"
#include "sddll.hxx"
#include "sdmod.hxx"
#include "framework/FrameworkHelper.hxx"

#include "EventMultiplexer.hxx"
@@ -76,6 +76,8 @@
#include "drawdoc.hxx"
#include "app.hrc"

#include <svx/svdetc.hxx>
#include <svx/svdstr.hrc>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/range/b2drange.hxx>
@@ -101,6 +103,11 @@ using ::com::sun::star::container::XEnumerationAccess;
using ::com::sun::star::container::XEnumeration;
using ::com::sun::star::text::XText;
using ::sd::framework::FrameworkHelper;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::uno::UNO_QUERY_THROW;
using ::com::sun::star::uno::Any;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Exception;

namespace sd {

@@ -151,13 +158,14 @@ CustomAnimationPane::CustomAnimationPane( Window* pParent, ViewShellBase& rBase,
    mrBase( rBase ),
    mpCustomAnimationPresets(nullptr),
    mnPropertyType( nPropertyTypeNone ),
    mnCurvePathPos( LISTBOX_ENTRY_NOTFOUND ),
    mnPolygonPathPos( LISTBOX_ENTRY_NOTFOUND ),
    mnFreeformPathPos( LISTBOX_ENTRY_NOTFOUND ),
    maLateInitTimer()
{
    // load resources
    get(mpPBAddEffect, "add_effect");
    get(mpPBChangeEffect, "change_effect");
    get(mpPBRemoveEffect, "remove_effect");

    get(mpFTEffect, "effect_label");

    get(mpFTStart, "start_effect");
@@ -169,11 +177,18 @@ CustomAnimationPane::CustomAnimationPane( Window* pParent, ViewShellBase& rBase,

    get(mpFTSpeed, "effect_speed");
    get(mpCBSpeed, "effect_speed_list");

    get(mpFTCategory, "categorylabel");
    get(mpLBCategory, "categorylb");
    get(mpFTAnimation, "effectlabel");
    get(mpLBAnimation, "effect_list");
    mpLBAnimation->SetSelectHdl(LINK(this, CustomAnimationPane, AnimationSelectHdl));
    get(mpCustomAnimationList, "custom_animation_list");
    mpCustomAnimationList->setController( dynamic_cast<ICustomAnimationListController*> ( this ) );
    mpCustomAnimationList->set_width_request(mpCustomAnimationList->approximate_char_width() * 16);
    mpCustomAnimationList->set_height_request(mpCustomAnimationList->GetTextHeight() * 16);
    mpCustomAnimationList->set_height_request(mpCustomAnimationList->GetTextHeight() * 8);

    mpLBAnimation->set_width_request(mpLBAnimation->approximate_char_width() * 16);
    mpLBAnimation->set_height_request(mpLBAnimation->GetTextHeight() * 8);

    get(mpPBMoveUp, "move_up");
    get(mpPBMoveDown, "move_down");
@@ -185,7 +200,6 @@ CustomAnimationPane::CustomAnimationPane( Window* pParent, ViewShellBase& rBase,
    fillDurationComboBox( mpCBSpeed );

    mpPBAddEffect->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
    mpPBChangeEffect->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
    mpPBRemoveEffect->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
    mpLBStart->SetSelectHdl( LINK( this, CustomAnimationPane, implControlListBoxHdl ) );
    mpCBSpeed->SetSelectHdl( LINK( this, CustomAnimationPane, implControlListBoxHdl ) );
@@ -194,6 +208,7 @@ CustomAnimationPane::CustomAnimationPane( Window* pParent, ViewShellBase& rBase,
    mpPBMoveDown->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
    mpPBPlay->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
    mpCBAutoPreview->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
    mpLBCategory->SetSelectHdl( LINK(this, CustomAnimationPane, UpdateAnimationLB) );

    maStrModify = mpFTEffect->GetText();

@@ -216,7 +231,6 @@ CustomAnimationPane::CustomAnimationPane( Window* pParent, ViewShellBase& rBase,
    maLateInitTimer.SetTimeout(100);
    maLateInitTimer.SetTimeoutHdl(LINK(this, CustomAnimationPane, lateInitCallback));
    maLateInitTimer.Start();

    UpdateLook();
}

@@ -238,7 +252,6 @@ void CustomAnimationPane::dispose()
        (*aIter)->Dispose();

    mpPBAddEffect.clear();
    mpPBChangeEffect.clear();
    mpPBRemoveEffect.clear();
    mpFTEffect.clear();
    mpFTStart.clear();
@@ -254,9 +267,38 @@ void CustomAnimationPane::dispose()
    mpPBMoveDown.clear();
    mpPBPlay.clear();
    mpCBAutoPreview.clear();
    mpFTCategory.clear();
    mpLBCategory.clear();
    mpFTAnimation.clear();
    mpLBAnimation.clear();

    PanelLayout::dispose();
}

PathKind CustomAnimationPane::getCreatePathKind() const
{
    PathKind eKind = PathKind::NONE;

    if( mpLBAnimation->GetSelectEntryCount() == 1 )
    {
        const sal_Int32 nPos = mpLBAnimation->GetSelectEntryPos();
        if( nPos == mnCurvePathPos )
        {
            eKind = PathKind::CURVE;
        }
        else if( nPos == mnPolygonPathPos )
        {
            eKind = PathKind::POLYGON;
        }
        else if( nPos == mnFreeformPathPos )
        {
            eKind = PathKind::FREEFORM;
        }
    }

    return eKind;
}

void CustomAnimationPane::addUndo()
{
    ::svl::IUndoManager* pManager = mrBase.GetDocShell()->GetUndoManager();
@@ -481,13 +523,17 @@ void CustomAnimationPane::updateControls()
    if( !mxView.is() )
    {
        mpPBAddEffect->Enable( false );
        mpPBChangeEffect->Enable( false );
        mpPBRemoveEffect->Enable( false );
        mpFTStart->Enable( false );
        mpLBStart->Enable( false );
        mpPBPropertyMore->Enable( false );
        mpLBProperty->Enable( false );
        mpFTProperty->Enable( false );
        mpFTCategory->Disable();
        mpLBCategory->Disable();
        mpFTAnimation->Disable();
        mpLBAnimation->Disable();
        mpLBAnimation->Clear();
        mpCustomAnimationList->clear();
        return;
    }
@@ -495,11 +541,26 @@ void CustomAnimationPane::updateControls()
    const int nSelectionCount = maListSelection.size();

    mpPBAddEffect->Enable( maViewSelection.hasValue() );
    mpPBChangeEffect->Enable( nSelectionCount);
    mpPBRemoveEffect->Enable(nSelectionCount);
    if(maViewSelection.hasValue() && (nSelectionCount == 1))
    {
        mpFTAnimation->Enable();
        mpLBAnimation->Enable();
        fillAnimationLB();
    }
    else
    {
        mpFTAnimation->Disable();
        mpLBAnimation->Disable();
        mpLBAnimation->Clear();
    }

    mpLBCategory->Enable(maViewSelection.hasValue() && (nSelectionCount == 1));
    mpFTCategory->Enable(maViewSelection.hasValue() && (nSelectionCount == 1));

    mpFTStart->Enable(nSelectionCount > 0);
    mpLBStart->Enable(nSelectionCount > 0);
    mpLBProperty->Enable(nSelectionCount > 0);
    mpPBPropertyMore->Enable(nSelectionCount > 0);

    mpFTProperty->SetText( maStrProperty );
@@ -566,6 +627,42 @@ void CustomAnimationPane::updateControls()
            mpLBProperty->Enable( false );
            mpPBPropertyMore->Enable( false );
        }
        sal_uInt32 nCategoryPos = LISTBOX_ENTRY_NOTFOUND;
        switch(pEffect->getPresetClass())
        {
            case EffectPresetClass::MOTIONPATH: nCategoryPos = 0; break;
            case EffectPresetClass::EMPHASIS: nCategoryPos = 1; break;
            case EffectPresetClass::ENTRANCE: nCategoryPos = 2; break;
            case EffectPresetClass::EXIT: nCategoryPos = 3; break;
            default:
                break;
        }
        switch(pEffect->getCommand())
        {
            case EffectCommands::TOGGLEPAUSE:
            case EffectCommands::STOP:
            case EffectCommands::PLAY:
                nCategoryPos = 4; break;
            default:
            break;
        }
        mpLBCategory->SelectEntryPos(nCategoryPos);
        fillAnimationLB();
        OUString rsPresetId = pEffect->getPresetId();
        sal_Int32 nAnimationPos = mpLBAnimation->GetEntryCount();
        while( nAnimationPos-- )
        {
            void* pEntryData = mpLBAnimation->GetEntryData( nAnimationPos );
            if( pEntryData )
            {
                CustomAnimationPresetPtr& pPtr = *static_cast< CustomAnimationPresetPtr* >(pEntryData);
                if( pPtr.get() && pPtr->getPresetId() == rsPresetId )
                {
                    mpLBAnimation->SelectEntryPos( nAnimationPos );
                    break;
                }
            }
        }

        sal_uInt16 nPos = 0xffff;

@@ -613,7 +710,6 @@ void CustomAnimationPane::updateControls()
        mpPBPropertyMore->Enable( false );
        mpFTSpeed->Enable(false);
        mpCBSpeed->Enable(false);
        mpLBStart->SetNoSelection();
        mpCBSpeed->SetNoSelection();
        mpFTEffect->SetText( maStrModify );
    }
@@ -822,7 +918,7 @@ void CustomAnimationPane::onContextMenu( sal_uInt16 nSelectedPopupEntry )
        onRemove();
        break;
    case CM_CREATE:
        if( maViewSelection.hasValue() ) onChange( true );
        if( maViewSelection.hasValue() ) onChange();
        break;
    }

@@ -1672,164 +1768,161 @@ bool getTextSelection( const Any& rSelection, Reference< XShape >& xShape, std::
    return false;
}

void CustomAnimationPane::onChange( bool bCreate )
void CustomAnimationPane::animationChange()
{
    bool bHasText = true;

    // first create vector of targets for dialog preview
    std::vector< Any > aTargets;
    OUString sPresetId;
    double fDuration = 2.0f;

    if( bCreate )
    if( maListSelection.size() == 1 )
    {
        // gather shapes from the selection
        Reference< XSelectionSupplier >  xSel( mxView, UNO_QUERY_THROW );
        maViewSelection = xSel->getSelection();
        CustomAnimationPresetPtr* pPreset = static_cast< CustomAnimationPresetPtr* >(mpLBAnimation->GetSelectEntryData());
        const double fDuration = (*pPreset)->getDuration();
        CustomAnimationPresetPtr pDescriptor(*pPreset);
        MainSequenceRebuildGuard aGuard( mpMainSequence );

        if( maViewSelection.getValueType() == cppu::UnoType<XShapes>::get())
        {
            Reference< XIndexAccess > xShapes;
            maViewSelection >>= xShapes;

            sal_Int32 nCount = xShapes->getCount();
            sal_Int32 nIndex;
            for( nIndex = 0; nIndex < nCount; nIndex++ )
            {
                Any aTarget( xShapes->getByIndex( nIndex ) );
                aTargets.push_back( aTarget );
                if( bHasText )
                {
                    Reference< XText > xText;
                    aTarget >>= xText;
                    if( !xText.is() || xText->getString().isEmpty() )
                        bHasText = false;
                }
            }
        }
        else if ( maViewSelection.getValueType() == cppu::UnoType<XShape>::get())
        {
            aTargets.push_back( maViewSelection );
            Reference< XText > xText;
            maViewSelection >>= xText;
            if( !xText.is() || xText->getString().isEmpty() )
                bHasText = false;
        }
        else if ( maViewSelection.getValueType() == cppu::UnoType<XTextCursor>::get())
        {
            Reference< XShape > xShape;
            std::list< sal_Int16 > aParaList;
            if( getTextSelection( maViewSelection, xShape, aParaList ) )
            {
                ParagraphTarget aParaTarget;
                aParaTarget.Shape = xShape;

                std::list< sal_Int16 >::iterator aIter( aParaList.begin() );
                for( ; aIter != aParaList.end(); ++aIter )
                {
                    aParaTarget.Paragraph = (*aIter);
                    aTargets.push_back( makeAny( aParaTarget ) );
                   }
            }
        }
        else
        {
            OSL_FAIL("sd::CustomAnimationPane::onChange(), unknown view selection!" );
            return;
        }
    }
    else
    {
        // get selected effect
        EffectSequence::iterator aIter( maListSelection.begin() );
        const EffectSequence::iterator aEnd( maListSelection.end() );
        while( aIter != aEnd )
        {
            if( !bHasText || !(*aIter)->hasText() )
                bHasText = false;
            CustomAnimationEffectPtr pEffect = (*aIter++);

            if( sPresetId.isEmpty() )
            EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
            if( !pEffectSequence )
                pEffectSequence = mpMainSequence.get();

            pEffectSequence->replace( pEffect, pDescriptor, fDuration );
        }
        onPreview(true);
    }

}

void CustomAnimationPane::onChange()
{
    bool bHasText = true;

    // first create vector of targets for dialog preview
    std::vector< Any > aTargets;

    // gather shapes from the selection
    Reference< XSelectionSupplier >  xSel( mxView, UNO_QUERY_THROW );
    maViewSelection = xSel->getSelection();

    if( maViewSelection.getValueType() == cppu::UnoType<XShapes>::get())
    {
        Reference< XIndexAccess > xShapes;
        maViewSelection >>= xShapes;

        sal_Int32 nCount = xShapes->getCount();
        sal_Int32 nIndex;
        for( nIndex = 0; nIndex < nCount; nIndex++ )
        {
            Any aTarget( xShapes->getByIndex( nIndex ) );
            aTargets.push_back( aTarget );
            if( bHasText )
            {
                sPresetId = (*aIter)->getPresetId();
                fDuration = (*aIter)->getDuration();
                Reference< XText > xText;
                aTarget >>= xText;
                if( !xText.is() || xText->getString().isEmpty() )
                    bHasText = false;
            }
        }
    }
    else if ( maViewSelection.getValueType() == cppu::UnoType<XShape>::get())
    {
        aTargets.push_back( maViewSelection );
        Reference< XText > xText;
        maViewSelection >>= xText;
        if( !xText.is() || xText->getString().isEmpty() )
            bHasText = false;
    }
    else if ( maViewSelection.getValueType() == cppu::UnoType<XTextCursor>::get())
    {
        Reference< XShape > xShape;
        std::list< sal_Int16 > aParaList;
        if( getTextSelection( maViewSelection, xShape, aParaList ) )
        {
            ParagraphTarget aParaTarget;
            aParaTarget.Shape = xShape;

            aTargets.push_back( (*aIter++)->getTarget() );
            std::list< sal_Int16 >::iterator aIter( aParaList.begin() );                for( ; aIter != aParaList.end(); ++aIter )
            for( ; aIter != aParaList.end(); ++aIter )
            {
                aParaTarget.Paragraph = (*aIter);
                aTargets.push_back( makeAny( aParaTarget ) );
            }
        }
    }
    else
    {
        OSL_FAIL("sd::CustomAnimationPane::onChange(), unknown view selection!" );
        return;
    }

    CustomAnimationPresetPtr pDescriptor;
    mpFTCategory->Enable();
    mpLBCategory->Enable();
    mpFTAnimation->Enable();
    mpLBAnimation->Enable();
    mpLBCategory->SelectEntryPos(1);
    fillAnimationLB();
    void* pEntryData = mpLBAnimation->GetSelectEntryData();
    if( pEntryData )
        pDescriptor = *static_cast< CustomAnimationPresetPtr* >( pEntryData );

    const double fDuration = pDescriptor->getDuration();
    sal_uInt32 nPos = LISTBOX_ENTRY_NOTFOUND;
    if( fDuration == 5.0 )
        nPos = 0;
    else if( fDuration == 3.0 )
        nPos = 1;
    else if( fDuration == 2.0 )
        nPos = 2;
    else if( fDuration == 1.0 )
        nPos = 3;
    else if( fDuration == 0.5 )
        nPos = 4;
    mpCBSpeed->SelectEntryPos( nPos );
    bool bHasSpeed = pDescriptor->getDuration() > 0.001;
    mpCBSpeed->Enable( bHasSpeed );
    mpFTSpeed->Enable( bHasSpeed );

    if( pDescriptor.get() )
    {
        {
            mpCustomAnimationList->SelectAll( false );

            // gather shapes from the selection
            std::vector< Any >::iterator aIter( aTargets.begin() );
            const std::vector< Any >::iterator aEnd( aTargets.end() );
            bool bFirst = true;
            for( ; aIter != aEnd; ++aIter )
            {
                CustomAnimationEffectPtr pCreated = mpMainSequence->append( pDescriptor, (*aIter), fDuration );

                // if only one shape with text and no fill or outline is selected, animate only by first level paragraphs
                if( bHasText && (aTargets.size() == 1) )
                {
                    Reference< XShape > xShape( (*aIter), UNO_QUERY );
                    if( xShape.is() && !hasVisibleShape( xShape ) )
                    {
                        mpMainSequence->createTextGroup( pCreated, 1, -1.0, false, false );
                    }
                }

                if( bFirst )
                    bFirst = false;
                else
                    pCreated->setNodeType( EffectNodeType::WITH_PREVIOUS );

                if( pCreated.get() )
                    mpCustomAnimationList->select( pCreated );
            }
        }
    }

    {
        ScopedVclPtrInstance< CustomAnimationCreateDialog > pDlg( this, this, aTargets, bHasText, sPresetId, fDuration );
        if( pDlg->Execute() )
        {
            addUndo();
            fDuration = pDlg->getSelectedDuration();
            CustomAnimationPresetPtr pDescriptor = pDlg->getSelectedPreset();
            if( pDescriptor.get() )
            {
                if( bCreate )
                {
                    mpCustomAnimationList->SelectAll( false );

                    // gather shapes from the selection
                    std::vector< Any >::iterator aIter( aTargets.begin() );
                    const std::vector< Any >::iterator aEnd( aTargets.end() );
                    bool bFirst = true;
                    for( ; aIter != aEnd; ++aIter )
                    {
                        CustomAnimationEffectPtr pCreated = mpMainSequence->append( pDescriptor, (*aIter), fDuration );

                        // if only one shape with text and no fill or outline is selected, animate only by first level paragraphs
                        if( bHasText && (aTargets.size() == 1) )
                        {
                            Reference< XShape > xShape( (*aIter), UNO_QUERY );
                            if( xShape.is() && !hasVisibleShape( xShape ) )
                            {
                                mpMainSequence->createTextGroup( pCreated, 1, -1.0, false, false );
                            }
                        }

                        if( bFirst )
                            bFirst = false;
                        else
                            pCreated->setNodeType( EffectNodeType::WITH_PREVIOUS );

                        if( pCreated.get() )
                            mpCustomAnimationList->select( pCreated );
                    }
                }
                else
                {
                    MainSequenceRebuildGuard aGuard( mpMainSequence );

                    // get selected effect
                    EffectSequence::iterator aIter( maListSelection.begin() );
                    const EffectSequence::iterator aEnd( maListSelection.end() );
                    while( aIter != aEnd )
                    {
                        CustomAnimationEffectPtr pEffect = (*aIter++);

                        EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
                        if( !pEffectSequence )
                            pEffectSequence = mpMainSequence.get();

                        pEffectSequence->replace( pEffect, pDescriptor, fDuration );
                    }
                }
            }
            else
            {
                PathKind eKind = pDlg->getCreatePathKind();
                if( eKind != PathKind::NONE )
                    createPath( eKind, aTargets, fDuration );
            }
            mrBase.GetDocShell()->SetModified();
        }
    } // dispose pDlg
    mrBase.GetDocShell()->SetModified();

    updateControls();

    // stop running preview from dialog
    SlideShow::Stop( mrBase );
}

@@ -1987,17 +2080,9 @@ void CustomAnimationPane::onChangeSpeed()

        MainSequenceRebuildGuard aGuard( mpMainSequence );

        double fDuration;

        switch( mpCBSpeed->GetSelectEntryPos() )
        {
        case 0: fDuration = 5.0; break;
        case 1: fDuration = 3.0; break;
        case 2: fDuration = 2.0; break;
        case 3: fDuration = 1.0; break;
        case 4: fDuration = 0.5; break;
        default:
            return;
        double fDuration = getDuration();
        if(fDuration == 0) {
             return;
        }

        // change selected effect
@@ -2017,12 +2102,127 @@ void CustomAnimationPane::onChangeSpeed()
    }
}

float CustomAnimationPane::getDuration()
{
    sal_uInt16 nPos= mpCBSpeed->GetSelectEntryPos();
    float fDuration = 0;
    switch( nPos )
    {
    case 0: fDuration = 5.0; break;
    case 1: fDuration = 3.0; break;
    case 2: fDuration = 2.0; break;
    case 3: fDuration = 1.0; break;
    case 4: fDuration = 0.5; break;
    }
    return fDuration;
}

/// this link is called when the property box is modified by the user
IMPL_LINK_NOARG_TYPED(CustomAnimationPane, implPropertyHdl, LinkParamNone*, void)
{
    onChangeProperty();
}

IMPL_LINK_NOARG_TYPED(CustomAnimationPane, AnimationSelectHdl, ListBox&, void)
{
    CustomAnimationPresetPtr* pPreset = static_cast< CustomAnimationPresetPtr* >(mpLBAnimation->GetSelectEntryData());
    const double fDuration = (*pPreset)->getDuration();
    sal_uInt32 nPos = LISTBOX_ENTRY_NOTFOUND;
    if( fDuration == 5.0 )
        nPos = 0;
    else if( fDuration == 3.0 )
        nPos = 1;
    else if( fDuration == 2.0 )
        nPos = 2;
    else if( fDuration == 1.0 )
        nPos = 3;
    else if( fDuration == 0.5 )
        nPos = 4;
    mpCBSpeed->SelectEntryPos( nPos );
    bool bHasSpeed = (*pPreset)->getDuration() > 0.001;
    mpCBSpeed->Enable( bHasSpeed );
    mpFTSpeed->Enable( bHasSpeed );
    MainSequenceRebuildGuard aGuard( mpMainSequence );

    // get selected effect
    EffectSequence::iterator aIter( maListSelection.begin() );
    const EffectSequence::iterator aEnd( maListSelection.end() );
    while( aIter != aEnd )
    {
        CustomAnimationEffectPtr pEffect = (*aIter++);

        EffectSequenceHelper* pEffectSequence = pEffect->getEffectSequence();
        if( !pEffectSequence )
            pEffectSequence = mpMainSequence.get();

        pEffectSequence->replace( pEffect, *pPreset, fDuration );
    }
    onPreview(true);
}

IMPL_LINK_NOARG_TYPED(CustomAnimationPane, UpdateAnimationLB, ListBox&, void)
{
    fillAnimationLB();
}

void CustomAnimationPane::fillAnimationLB()
{
    PresetCategoryList rCategoryList;
    sal_uInt16 nPosition = mpLBCategory->GetSelectEntryPos();
    const CustomAnimationPresets& rPresets (getPresets());
    switch(nPosition)
    {
        case 0:rCategoryList = rPresets.getMotionPathsPresets();break;
        case 1:rCategoryList = rPresets.getEmphasisPresets();break;
        case 2:rCategoryList = rPresets.getEntrancePresets();break;
        case 3:rCategoryList = rPresets.getExitPresets();break;
        case 4:rCategoryList = rPresets.getMiscPresets();break;
    }

    sal_uInt32 nFirstEffect = LISTBOX_ENTRY_NOTFOUND;

    if(nPosition == 0)
    {
        OUString sMotionPathLabel( SD_RESSTR( STR_CUSTOMANIMATION_USERPATH ) );
        mpLBAnimation->InsertCategory( sMotionPathLabel );
        mnCurvePathPos = mpLBAnimation->InsertEntry( sdr::GetResourceString(STR_ObjNameSingulCOMBLINE) );
        mnPolygonPathPos = mpLBAnimation->InsertEntry( sdr::GetResourceString(STR_ObjNameSingulPOLY) );
        mnFreeformPathPos = mpLBAnimation->InsertEntry( sdr::GetResourceString(STR_ObjNameSingulFREELINE) );

    }
    PresetCategoryList::const_iterator aCategoryIter( rCategoryList.begin() );
    const PresetCategoryList::const_iterator aCategoryEnd( rCategoryList.end() );
    mpLBAnimation->Clear();
    while(aCategoryIter != aCategoryEnd)
    {
        PresetCategoryPtr pCategory( *aCategoryIter++ );
        if( pCategory.get() )
        {
            mpLBAnimation->InsertCategory( pCategory->maLabel );

            std::vector< CustomAnimationPresetPtr > aSortedVector(pCategory->maEffects.size());
            std::copy( pCategory->maEffects.begin(), pCategory->maEffects.end(), aSortedVector.begin() );

            std::vector< CustomAnimationPresetPtr >::const_iterator aIter( aSortedVector.begin() );
            const std::vector< CustomAnimationPresetPtr >::const_iterator aEnd( aSortedVector.end() );
            while( aIter != aEnd )
            {
                CustomAnimationPresetPtr pDescriptor = (*aIter++);
                if( pDescriptor.get() && !pDescriptor->isTextOnly() )
                {
                    sal_Int32 nPos = mpLBAnimation->InsertEntry( pDescriptor->getLabel() );
                    mpLBAnimation->SetEntryData( nPos, static_cast<void*>( new CustomAnimationPresetPtr( pDescriptor ) ) );

                    if( nFirstEffect == LISTBOX_ENTRY_NOTFOUND )
                        nFirstEffect = nPos;
                }
            }
        }
    }
    mpLBAnimation->SelectEntryPos(nFirstEffect);
}


IMPL_LINK_TYPED( CustomAnimationPane, implClickHdl, Button*, pBtn, void )
{
    implControlHdl(pBtn);
@@ -2036,9 +2236,10 @@ IMPL_LINK_TYPED( CustomAnimationPane, implControlListBoxHdl, ListBox&, rListBox,
void CustomAnimationPane::implControlHdl(Control* pControl )
{
    if( pControl == mpPBAddEffect )
        onChange(true);
    else if( pControl == mpPBChangeEffect )
        onChange(false);
    {
        onChange();
        onPreview(true);
    }
    else if( pControl == mpPBRemoveEffect )
        onRemove();
    else if( pControl == mpLBStart )
diff --git a/sd/source/ui/animations/CustomAnimationPane.hxx b/sd/source/ui/animations/CustomAnimationPane.hxx
index 6574807..a5b4c6e 100644
--- a/sd/source/ui/animations/CustomAnimationPane.hxx
+++ b/sd/source/ui/animations/CustomAnimationPane.hxx
@@ -28,11 +28,10 @@
#include <sfx2/sidebar/ControlFactory.hxx>
#include "CustomAnimationPreset.hxx"
#include "CustomAnimationList.hxx"
#include "CustomAnimationCreateDialog.hxx"

#include "CategoryListBox.hxx"
#include "motionpathtag.hxx"
#include "misc/scopelock.hxx"

#include "CustomAnimationPreset.hxx"
#include <vector>

class PushButton;
@@ -42,6 +41,8 @@ class ListBox;
class ComboBox;
class CheckBox;

enum class PathKind { NONE, CURVE, POLYGON, FREEFORM };

namespace com { namespace sun { namespace star { namespace animations {
    class XAnimationNode;
} } } }
@@ -69,7 +70,8 @@ public:
    // callbacks
    void onSelectionChanged();
    void onChangeCurrentPage();
    void onChange( bool bCreate );
    void onChange();
    void animationChange();
    void onRemove();
    void onChangeStart();
    void onChangeStart( sal_Int16 nNodeType );
@@ -80,6 +82,7 @@ public:
    void preview( const css::uno::Reference< css::animations::XAnimationNode >& xAnimationNode );
    void remove( CustomAnimationEffectPtr& pEffect );

    PathKind getCreatePathKind() const;
    // Control
    virtual void StateChanged( StateChangedType nStateChange ) override;
    virtual void KeyInput( const KeyEvent& rKEvt ) override;
@@ -94,6 +97,7 @@ public:

    void addUndo();

    float getDuration();
    void updatePathFromMotionPathTag( const rtl::Reference< MotionPathTag >& xTag );

private:
@@ -115,12 +119,15 @@ private:
    static css::uno::Any getProperty1Value( sal_Int32 nType, CustomAnimationEffectPtr pEffect );
    bool setProperty1Value( sal_Int32 nType, CustomAnimationEffectPtr pEffect, const css::uno::Any& rValue );
    void UpdateLook();
    void fillAnimationLB();

    DECL_LINK_TYPED( implControlListBoxHdl, ListBox&, void );
    DECL_LINK_TYPED( implClickHdl, Button*, void );
    DECL_LINK_TYPED( implPropertyHdl, LinkParamNone*, void );
    DECL_LINK_TYPED( EventMultiplexerListener, tools::EventMultiplexerEvent&, void );
    DECL_LINK_TYPED( lateInitCallback, Timer *, void );
    DECL_LINK_TYPED( UpdateAnimationLB, ListBox&, void );
    DECL_LINK_TYPED( AnimationSelectHdl, ListBox&, void );
    void implControlHdl(Control*);

private:
@@ -129,7 +136,6 @@ private:
    const CustomAnimationPresets* mpCustomAnimationPresets;

    VclPtr<PushButton> mpPBAddEffect;
    VclPtr<PushButton> mpPBChangeEffect;
    VclPtr<PushButton> mpPBRemoveEffect;
    VclPtr<FixedText>  mpFTEffect;
    VclPtr<FixedText>  mpFTStart;
@@ -145,11 +151,18 @@ private:
    VclPtr<PushButton> mpPBMoveDown;
    VclPtr<PushButton> mpPBPlay;
    VclPtr<CheckBox>   mpCBAutoPreview;
    VclPtr<FixedText> mpFTCategory;
    VclPtr<ListBox>    mpLBCategory;
    VclPtr<FixedText> mpFTAnimation;
    VclPtr<CategoryListBox> mpLBAnimation;

    OUString    maStrModify;
    OUString    maStrProperty;

    sal_Int32   mnPropertyType;
    sal_Int32   mnCurvePathPos;
    sal_Int32   mnPolygonPathPos;
    sal_Int32   mnFreeformPathPos;

    EffectSequence  maListSelection;
    css::uno::Any   maViewSelection;
diff --git a/sd/uiconfig/simpress/ui/customanimationcreatedialog.ui b/sd/uiconfig/simpress/ui/customanimationcreatedialog.ui
deleted file mode 100644
index 7c46c15e..0000000
--- a/sd/uiconfig/simpress/ui/customanimationcreatedialog.ui
+++ /dev/null
@@ -1,161 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
  <requires lib="gtk+" version="3.0"/>
  <object class="GtkDialog" id="CustomAnimationCreate">
    <property name="can_focus">False</property>
    <property name="border_width">6</property>
    <property name="type_hint">dialog</property>
    <child internal-child="vbox">
      <object class="GtkBox" id="dialog-vbox1">
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <property name="spacing">12</property>
        <child internal-child="action_area">
          <object class="GtkButtonBox" id="dialog-action_area1">
            <property name="can_focus">False</property>
            <property name="layout_style">end</property>
            <child>
              <object class="GtkButton" id="ok">
                <property name="label">gtk-ok</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="can_default">True</property>
                <property name="has_default">True</property>
                <property name="receives_default">True</property>
                <property name="use_stock">True</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="cancel">
                <property name="label">gtk-cancel</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="use_stock">True</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="help">
                <property name="label">gtk-help</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="use_stock">True</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">2</property>
                <property name="secondary">True</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="pack_type">end</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkNotebook" id="tabs">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="hexpand">True</property>
            <property name="vexpand">True</property>
            <child>
              <placeholder/>
            </child>
            <child type="tab">
              <object class="GtkLabel" id="entrance">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Entrance</property>
              </object>
              <packing>
                <property name="tab_fill">False</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
            <child type="tab">
              <object class="GtkLabel" id="emphasis">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Emphasis</property>
              </object>
              <packing>
                <property name="position">1</property>
                <property name="tab_fill">False</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
            <child type="tab">
              <object class="GtkLabel" id="exit">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Exit</property>
              </object>
              <packing>
                <property name="position">2</property>
                <property name="tab_fill">False</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
            <child type="tab">
              <object class="GtkLabel" id="motion_paths">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Motion Paths</property>
              </object>
              <packing>
                <property name="position">3</property>
                <property name="tab_fill">False</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
            <child type="tab">
              <object class="GtkLabel" id="misc_effects">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Misc Effects</property>
              </object>
              <packing>
                <property name="position">4</property>
                <property name="tab_fill">False</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
    </child>
    <action-widgets>
      <action-widget response="0">ok</action-widget>
      <action-widget response="0">cancel</action-widget>
      <action-widget response="0">help</action-widget>
    </action-widgets>
  </object>
</interface>
diff --git a/sd/uiconfig/simpress/ui/customanimationcreatetab.ui b/sd/uiconfig/simpress/ui/customanimationcreatetab.ui
deleted file mode 100644
index c51a926..0000000
--- a/sd/uiconfig/simpress/ui/customanimationcreatetab.ui
+++ /dev/null
@@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <!-- interface-requires gtk+ 3.0 -->
  <object class="GtkBox" id="CustomAnimationCreateTab">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="border_width">6</property>
    <property name="orientation">vertical</property>
    <property name="spacing">12</property>
    <child>
      <object class="sdlo-CategoryListBox" id="effect_list">
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="hexpand">True</property>
        <property name="vexpand">True</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">0</property>
      </packing>
    </child>
    <child>
      <object class="GtkBox" id="box3">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="halign">end</property>
        <property name="spacing">12</property>
        <child>
          <object class="GtkLabel" id="effect_speed_label">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="label" translatable="yes">_Speed:</property>
            <property name="use_underline">True</property>
            <property name="mnemonic_widget">effect_speed_list</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkComboBoxText" id="effect_speed_list">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">1</property>
      </packing>
    </child>
    <child>
      <object class="GtkCheckButton" id="auto_preview">
        <property name="label" translatable="yes">_Automatic preview</property>
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="receives_default">False</property>
        <property name="use_underline">True</property>
        <property name="xalign">0</property>
        <property name="draw_indicator">True</property>
      </object>
      <packing>
        <property name="expand">False</property>
        <property name="fill">True</property>
        <property name="position">2</property>
      </packing>
    </child>
  </object>
</interface>
diff --git a/sd/uiconfig/simpress/ui/customanimationspanel.ui b/sd/uiconfig/simpress/ui/customanimationspanel.ui
index 7dd91e4..0759195 100644
--- a/sd/uiconfig/simpress/ui/customanimationspanel.ui
+++ b/sd/uiconfig/simpress/ui/customanimationspanel.ui
@@ -3,18 +3,17 @@
<interface>
  <requires lib="gtk+" version="3.0"/>
  <requires lib="LibreOffice" version="1.0"/>
  <object class="GtkImage" id="image1">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="pixbuf">sfx2/res/symphony/sidebar-property-small.png</property>
  </object>
  <object class="GtkImage" id="image_add">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="pixbuf">svtools/res/list_add.png</property>
    <property name="icon_size">2</property>
  </object>
  <object class="GtkImage" id="image_change">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="pixbuf">cmd/sc_editdoc.png</property>
    <property name="icon_size">2</property>
  </object>
  <object class="GtkImage" id="image_down">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
@@ -70,6 +69,7 @@
          <object class="GtkBox" id="box2">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="halign">center</property>
            <child>
              <object class="GtkButton" id="add_effect">
                <property name="visible">True</property>
@@ -101,21 +101,6 @@
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="change_effect">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="receives_default">True</property>
                <property name="has_tooltip">True</property>
                <property name="tooltip_markup" translatable="yes">Modify Effect</property>
                <property name="image">image_change</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="move_up">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
@@ -145,19 +130,69 @@
                <property name="position">4</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <object class="GtkGrid" id="grid2">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="row_spacing">6</property>
            <property name="column_spacing">6</property>
            <child>
              <object class="GtkButton" id="play">
              <object class="GtkLabel" id="categorylabel">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="receives_default">True</property>
                <property name="has_tooltip">True</property>
                <property name="tooltip_text" translatable="yes">Preview Effect</property>
                <property name="image">image_play</property>
                <property name="label" translatable="yes">Category:</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">5</property>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="effectlabel">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Effect:</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkComboBoxText" id="categorylb">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="popup_fixed_width">False</property>
                <items>
                  <item translatable="yes">Motion Paths</item>
                  <item translatable="yes">Emphasis</item>
                  <item translatable="yes">Entrance</item>
                  <item translatable="yes">Exit</item>
                  <item translatable="yes">Misc Effects</item>
                </items>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="sdlo-CategoryListBox" id="effect_list">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="hexpand">True</property>
                <property name="vexpand">True</property>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
          </object>
@@ -261,11 +296,11 @@
                </child>
                <child>
                  <object class="GtkButton" id="more_properties">
                    <property name="label" translatable="yes">_Options...</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="use_underline">True</property>
                    <property name="image">image1</property>
                    <property name="always_show_image">True</property>
                  </object>
                  <packing>
                    <property name="left_attach">2</property>
@@ -293,7 +328,6 @@
            </child>
            <child type="label">
              <object class="GtkLabel" id="effect_label">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="hexpand">True</property>
                <property name="xalign">0</property>
@@ -311,14 +345,69 @@
          </packing>
        </child>
        <child>
          <object class="GtkCheckButton" id="auto_preview">
            <property name="label" translatable="yes">Automatic pre_view</property>
          <object class="GtkBox" id="box3">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="receives_default">False</property>
            <property name="use_underline">True</property>
            <property name="xalign">0</property>
            <property name="draw_indicator">True</property>
            <property name="can_focus">False</property>
            <property name="orientation">vertical</property>
            <child>
              <object class="GtkSeparator" id="separator1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkBox" id="box4">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="margin_left">6</property>
                <property name="margin_right">6</property>
                <property name="spacing">18</property>
                <child>
                  <object class="GtkCheckButton" id="auto_preview">
                    <property name="label" translatable="yes">Automatic Preview</property>
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">False</property>
                    <property name="use_underline">True</property>
                    <property name="xalign">0</property>
                    <property name="draw_indicator">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkButton" id="play">
                    <property name="label" translatable="yes">Play</property>
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="receives_default">True</property>
                    <property name="has_tooltip">True</property>
                    <property name="tooltip_text" translatable="yes">Preview Effect</property>
                    <property name="image">image_play</property>
                    <property name="image_position">right</property>
                    <property name="always_show_image">True</property>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>