[Libreoffice-commits] core.git: sd/inc sd/Library_sd.mk sd/source sd/uiconfig solenv/clang-format solenv/sanitizers

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Mon Apr 6 19:25:20 UTC 2020


 sd/Library_sd.mk                                    |    1 
 sd/inc/strings.hrc                                  |    1 
 sd/source/ui/animations/CategoryListBox.cxx         |   93 -
 sd/source/ui/animations/CategoryListBox.hxx         |   45 
 sd/source/ui/animations/CustomAnimationDialog.cxx   |    9 
 sd/source/ui/animations/CustomAnimationDialog.hxx   |    8 
 sd/source/ui/animations/CustomAnimationList.cxx     | 1116 ++++++++------------
 sd/source/ui/animations/CustomAnimationList.hxx     |   92 +
 sd/source/ui/animations/CustomAnimationPane.cxx     |  622 +++++------
 sd/source/ui/animations/CustomAnimationPane.hxx     |   67 -
 sd/uiconfig/simpress/ui/customanimationfragment.ui  |    6 
 sd/uiconfig/simpress/ui/customanimationspanel.ui    |  212 ++-
 sd/uiconfig/simpress/ui/customanimationtimingtab.ui |   14 
 sd/uiconfig/simpress/ui/effectmenu.ui               |   10 
 sd/uiconfig/simpress/ui/slidetransitionspanel.ui    |   38 
 solenv/clang-format/blacklist                       |    2 
 solenv/sanitizers/ui/modules/simpress.suppr         |    1 
 17 files changed, 1097 insertions(+), 1240 deletions(-)

New commits:
commit 21e8ce9ab9a522d25e95773af59b7ccccaee4e54
Author:     Caolán McNamara <caolanm at redhat.com>
AuthorDate: Tue Mar 24 11:44:16 2020 +0000
Commit:     Caolán McNamara <caolanm at redhat.com>
CommitDate: Mon Apr 6 21:24:40 2020 +0200

    weld custom animation panel
    
    and align animation panel and slide transitions panel padding/spacing
    
    Change-Id: I25a1d10894de635ebb9c8a1cba358940886125c2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91006
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sd/Library_sd.mk b/sd/Library_sd.mk
index 048a0c4f1edc..43b168be8d8c 100644
--- a/sd/Library_sd.mk
+++ b/sd/Library_sd.mk
@@ -183,7 +183,6 @@ $(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/CategoryListBox \
 	sd/source/ui/animations/CustomAnimationDialog \
 	sd/source/ui/animations/CustomAnimationList \
 	sd/source/ui/animations/CustomAnimationPane \
diff --git a/sd/inc/strings.hrc b/sd/inc/strings.hrc
index 26ec246e19b3..84cfea801a70 100644
--- a/sd/inc/strings.hrc
+++ b/sd/inc/strings.hrc
@@ -444,7 +444,6 @@
 #define STR_CUSTOMANIMATION_BROWSE_SOUND                NC_("STR_CUSTOMANIMATION_BROWSE_SOUND", "Other sound...")
 #define STR_CUSTOMANIMATION_SAMPLE                      NC_("STR_CUSTOMANIMATION_SAMPLE", "Sample")
 #define STR_CUSTOMANIMATION_TRIGGER                     NC_("STR_CUSTOMANIMATION_TRIGGER", "Trigger")
-#define STR_CUSTOMANIMATION_LIST_HELPTEXT               NC_("STR_CUSTOMANIMATION_LIST_HELPTEXT", "First select the slide element and then click 'Add...' to add an animation effect.")
 #define STR_CUSTOMANIMATION_USERPATH                    NC_("STR_CUSTOMANIMATION_USERPATH", "User paths")
 #define STR_CUSTOMANIMATION_ENTRANCE                    NC_("STR_CUSTOMANIMATION_ENTRANCE", "Entrance: %1")
 #define STR_CUSTOMANIMATION_EMPHASIS                    NC_("STR_CUSTOMANIMATION_EMPHASIS", "Emphasis: %1")
diff --git a/sd/source/ui/animations/CategoryListBox.cxx b/sd/source/ui/animations/CategoryListBox.cxx
deleted file mode 100644
index 054cb84acdcd..000000000000
--- a/sd/source/ui/animations/CategoryListBox.cxx
+++ /dev/null
@@ -1,93 +0,0 @@
-/* -*- 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 "CategoryListBox.hxx"
-#include <vcl/builderfactory.hxx>
-
-#include <vcl/event.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()
-{
-}
-
-void  CategoryListBox::InsertCategory( const OUString& rStr )
-{
-    sal_Int32  n = ListBox::InsertEntry( rStr );
-    if( n != LISTBOX_ENTRY_NOTFOUND )
-        ListBox::SetEntryFlags( n, ListBox::GetEntryFlags(n) | ListBoxEntryFlags::DisableSelection );
-}
-
-void CategoryListBox::UserDraw( const UserDrawEvent& rUDEvt )
-{
-    const sal_uInt16 nItem = rUDEvt.GetItemId();
-
-    if( ListBox::GetEntryFlags(nItem) & ListBoxEntryFlags::DisableSelection )
-    {
-        ::tools::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 );
-    }
-}
-
-IMPL_LINK_NOARG(CategoryListBox, implDoubleClickHdl, ListBox&, void)
-{
-    CaptureMouse();
-}
-
-void CategoryListBox::MouseButtonUp( const MouseEvent& rMEvt )
-{
-    ReleaseMouse();
-    if (!( rMEvt.IsLeft() && (rMEvt.GetClicks() == 2) ))
-    {
-        ListBox::MouseButtonUp( rMEvt );
-    }
-}
-
-}
diff --git a/sd/source/ui/animations/CategoryListBox.hxx b/sd/source/ui/animations/CategoryListBox.hxx
deleted file mode 100644
index 8ae5af8365eb..000000000000
--- a/sd/source/ui/animations/CategoryListBox.hxx
+++ /dev/null
@@ -1,45 +0,0 @@
-/* -*- 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 .
- */
-
-#ifndef INCLUDED_SD_SOURCE_UI_ANIMATIONS_CATEGORYLISTBOX_HXX
-#define INCLUDED_SD_SOURCE_UI_ANIMATIONS_CATEGORYLISTBOX_HXX
-
-#include <vcl/lstbox.hxx>
-
-namespace sd {
-
-class CategoryListBox : public ListBox
-{
-public:
-    explicit CategoryListBox( vcl::Window* pParent );
-    virtual ~CategoryListBox() override;
-
-    virtual void        MouseButtonUp( const MouseEvent& rMEvt ) override;
-
-    void                InsertCategory( const OUString& rStr );
-
-    DECL_LINK(implDoubleClickHdl, ListBox&, void);
-
-private:
-    virtual void    UserDraw( const UserDrawEvent& rUDEvt ) override;
-};
-
-}
-
-#endif // INCLUDED_SD_SOURCE_UI_ANIMATIONS_CATEGORYLISTBOX_HXX
diff --git a/sd/source/ui/animations/CustomAnimationDialog.cxx b/sd/source/ui/animations/CustomAnimationDialog.cxx
index 3c60f179b493..c62a7381f3bf 100644
--- a/sd/source/ui/animations/CustomAnimationDialog.cxx
+++ b/sd/source/ui/animations/CustomAnimationDialog.cxx
@@ -163,6 +163,13 @@ PresetPropertyBox::~PresetPropertyBox()
     mpControl.disposeAndClear();
 }
 
+SdPropertySubControl::SdPropertySubControl(weld::Container* pParent)
+    : mxBuilder(Application::CreateBuilder(pParent, "modules/simpress/ui/customanimationfragment.ui"))
+    , mxContainer(mxBuilder->weld_container("EffectFragment"))
+    , mpParent(pParent)
+{
+}
+
 Any PresetPropertyBox::getValue()
 {
     return makeAny( maPropertyValues[mpControl->GetSelectedEntryPos()] );
@@ -175,6 +182,7 @@ Control* PresetPropertyBox::getControl()
 
 SdPropertySubControl::~SdPropertySubControl()
 {
+    mpParent->move(mxContainer.get(), nullptr);
 }
 
 namespace {
@@ -221,6 +229,7 @@ void SdPresetPropertyBox::setValue( const Any& rValue, const OUString& rPresetId
 
     mxControl->freeze();
     mxControl->clear();
+    maPropertyValues.clear();
     int nPos = -1;
 
     const CustomAnimationPresets& rPresets = CustomAnimationPresets::getCustomAnimationPresets();
diff --git a/sd/source/ui/animations/CustomAnimationDialog.hxx b/sd/source/ui/animations/CustomAnimationDialog.hxx
index 46c81789deeb..1ed6972e76e4 100644
--- a/sd/source/ui/animations/CustomAnimationDialog.hxx
+++ b/sd/source/ui/animations/CustomAnimationDialog.hxx
@@ -116,12 +116,7 @@ private:
 class SdPropertySubControl
 {
 public:
-    explicit SdPropertySubControl(weld::Container* pParent)
-        : mxBuilder(Application::CreateBuilder(pParent, "modules/simpress/ui/customanimationfragment.ui"))
-        , mxContainer(mxBuilder->weld_container("EffectFragment"))
-    {
-    }
-
+    explicit SdPropertySubControl(weld::Container* pParent);
     virtual ~SdPropertySubControl();
 
     virtual             css::uno::Any getValue() = 0;
@@ -139,6 +134,7 @@ public:
 protected:
     std::unique_ptr<weld::Builder> mxBuilder;
     std::unique_ptr<weld::Container> mxContainer;
+    weld::Container* mpParent;
 };
 
 class PropertyControl : public ListBox
diff --git a/sd/source/ui/animations/CustomAnimationList.cxx b/sd/source/ui/animations/CustomAnimationList.cxx
index 4793d8aafcca..559ac92a6b5c 100644
--- a/sd/source/ui/animations/CustomAnimationList.cxx
+++ b/sd/source/ui/animations/CustomAnimationList.cxx
@@ -29,20 +29,18 @@
 #include <com/sun/star/drawing/XDrawPage.hpp>
 #include "CustomAnimationList.hxx"
 #include <CustomAnimationPreset.hxx>
-#include <vcl/settings.hxx>
-#include <vcl/builderfactory.hxx>
 #include <vcl/commandevent.hxx>
 #include <vcl/event.hxx>
+#include <vcl/image.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weldutils.hxx>
 #include <tools/debug.hxx>
+#include <tools/gen.hxx>
 #include <osl/diagnose.h>
 
 #include <sdresid.hxx>
 
-#include <vcl/svlbitm.hxx>
-#include <vcl/treelistentry.hxx>
-#include <vcl/viewdataentry.hxx>
-
-
 #include <strings.hrc>
 #include <bitmaps.hlst>
 
@@ -215,33 +213,35 @@ static OUString getDescription( const Any& rTarget, bool bWithText )
     return aDescription;
 }
 
-class CustomAnimationListEntryItem : public SvLBoxString
+class CustomAnimationListEntryItem
 {
 public:
     CustomAnimationListEntryItem(const OUString& aDescription,
-                                 const CustomAnimationEffectPtr& pEffect, CustomAnimationList* pParent);
-    void InitViewData(SvTreeListBox*,SvTreeListEntry*,SvViewDataItem* = nullptr) override;
-    virtual std::unique_ptr<SvLBoxItem> Clone(SvLBoxItem const * pSource) const override;
+                                 const CustomAnimationEffectPtr& pEffect);
+    const CustomAnimationEffectPtr& getEffect() const { return mpEffect; }
+
+    Size GetSize(vcl::RenderContext& rRenderContext);
+    void Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect, bool bSelected);
+    void PaintEffect(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect, bool bSelected);
+    void PaintTrigger(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect);
 
-    virtual void Paint(const Point&, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
-                       const SvViewDataEntry* pView,const SvTreeListEntry& rEntry) override;
 private:
-    VclPtr<CustomAnimationList> mpParent;
     OUString        msDescription;
     OUString        msEffectName;
     CustomAnimationEffectPtr mpEffect;
+
     static const long nIconWidth = 19;
     static const long nItemMinHeight = 38;
 };
 
-CustomAnimationListEntryItem::CustomAnimationListEntryItem( const OUString& aDescription, const CustomAnimationEffectPtr& pEffect, CustomAnimationList* pParent  )
-: SvLBoxString( aDescription )
-, mpParent( pParent )
-, msDescription( aDescription )
-, msEffectName( OUString() )
-, mpEffect(pEffect)
+CustomAnimationListEntryItem::CustomAnimationListEntryItem(const OUString& aDescription, const CustomAnimationEffectPtr& pEffect)
+    : msDescription(aDescription)
+    , msEffectName(OUString())
+    , mpEffect(pEffect)
 {
-    switch(mpEffect->getPresetClass())
+    if (!mpEffect)
+        return;
+    switch (mpEffect->getPresetClass())
     {
     case EffectPresetClass::ENTRANCE:
         msEffectName = SdResId(STR_CUSTOMANIMATION_ENTRANCE); break;
@@ -257,30 +257,85 @@ CustomAnimationListEntryItem::CustomAnimationListEntryItem( const OUString& aDes
     msEffectName = msEffectName.replaceFirst( "%1" , CustomAnimationPresets::getCustomAnimationPresets().getUINameForPresetId(mpEffect->getPresetId()));
 }
 
-void CustomAnimationListEntryItem::InitViewData( SvTreeListBox* pView, SvTreeListEntry* pEntry, SvViewDataItem* pViewData )
+IMPL_STATIC_LINK(CustomAnimationList, CustomRenderHdl, weld::TreeView::render_args, aPayload, void)
 {
-    if( !pViewData )
-        pViewData = pView->GetViewDataItem( pEntry, this );
-
-    long width = pView->GetTextWidth( msDescription ) + nIconWidth;
-    if( width < (pView->GetTextWidth( msEffectName ) + 2*nIconWidth))
-        width = pView->GetTextWidth( msEffectName ) + 2*nIconWidth;
-
-    Size aSize( width, pView->GetTextHeight() );
-    if( aSize.Height() < nItemMinHeight )
-        aSize.setHeight( nItemMinHeight );
-    pViewData->mnWidth = aSize.Width();
-    pViewData->mnHeight = aSize.Height();
+    vcl::RenderContext& rRenderContext = std::get<0>(aPayload);
+    const ::tools::Rectangle& rRect = std::get<1>(aPayload);
+    bool bSelected = std::get<2>(aPayload);
+    const OUString& rId = std::get<3>(aPayload);
+
+    CustomAnimationListEntryItem* pItem = reinterpret_cast<CustomAnimationListEntryItem*>(rId.toInt64());
+
+    pItem->Paint(rRenderContext, rRect, bSelected);
 }
 
-void CustomAnimationListEntryItem::Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
-                                         const SvViewDataEntry* /*pView*/, const SvTreeListEntry& rEntry)
+IMPL_STATIC_LINK(CustomAnimationList, CustomGetSizeHdl, weld::TreeView::get_size_args, aPayload, Size)
 {
+    vcl::RenderContext& rRenderContext = aPayload.first;
+    const OUString& rId = aPayload.second;
+
+    CustomAnimationListEntryItem* pItem = reinterpret_cast<CustomAnimationListEntryItem*>(rId.toInt64());
+    return pItem->GetSize(rRenderContext);
+}
+
+Size CustomAnimationListEntryItem::GetSize(vcl::RenderContext& rRenderContext)
+{
+    auto width = rRenderContext.GetTextWidth( msDescription ) + nIconWidth;
+    if (width < (rRenderContext.GetTextWidth( msEffectName ) + 2*nIconWidth))
+        width = rRenderContext.GetTextWidth( msEffectName ) + 2*nIconWidth;
+
+    Size aSize(width, rRenderContext.GetTextHeight());
+    if (aSize.Height() < nItemMinHeight)
+        aSize.setHeight(nItemMinHeight);
+    return aSize;
+}
+
+void CustomAnimationListEntryItem::PaintTrigger(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect)
+{
+    Size aSize(rRect.GetSize());
+
+    ::tools::Rectangle aOutRect(rRect);
+
+    // fill the background
+    Color aColor(rRenderContext.GetSettings().GetStyleSettings().GetDialogColor());
+
+    rRenderContext.Push();
+    rRenderContext.SetFillColor(aColor);
+    rRenderContext.SetLineColor();
+    rRenderContext.DrawRect(aOutRect);
+
+    // Erase the four corner pixels to make the rectangle appear rounded.
+    rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetWindowColor());
+    rRenderContext.DrawPixel(aOutRect.TopLeft());
+    rRenderContext.DrawPixel(Point(aOutRect.Right(), aOutRect.Top()));
+    rRenderContext.DrawPixel(Point(aOutRect.Left(), aOutRect.Bottom()));
+    rRenderContext.DrawPixel(Point(aOutRect.Right(), aOutRect.Bottom()));
+
+    // draw the category title
+
+    int nVertBorder = ((aSize.Height() - rRenderContext.GetTextHeight()) >> 1);
+    int nHorzBorder = rRenderContext.LogicToPixel(Size(3, 3), MapMode(MapUnit::MapAppFont)).Width();
+
+    aOutRect.AdjustLeft(nHorzBorder );
+    aOutRect.AdjustRight( -nHorzBorder );
+    aOutRect.AdjustTop( nVertBorder );
+    aOutRect.AdjustBottom( -nVertBorder );
 
-    const SvViewDataItem* pViewData = mpParent->GetViewDataItem(&rEntry, this);
+    rRenderContext.DrawText(aOutRect, rRenderContext.GetEllipsisString(msDescription, aOutRect.GetWidth()));
+    rRenderContext.Pop();
+}
 
-    Point aPos(rPos);
-    int nItemHeight = pViewData->mnHeight;
+void CustomAnimationListEntryItem::PaintEffect(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect, bool bSelected)
+{
+    rRenderContext.Push(PushFlags::TEXTCOLOR);
+    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+    if (bSelected)
+        rRenderContext.SetTextColor(rStyleSettings.GetHighlightTextColor());
+    else
+        rRenderContext.SetTextColor(rStyleSettings.GetDialogTextColor());
+
+    Point aPos(rRect.TopLeft());
+    int nItemHeight = rRect.GetHeight();
 
     sal_Int16 nNodeType = mpEffect->getNodeType();
     if (nNodeType == EffectNodeType::ON_CLICK )
@@ -296,12 +351,12 @@ void CustomAnimationListEntryItem::Paint(const Point& rPos, SvTreeListBox& rDev,
         //FIXME With previous image not defined in CustomAnimation.src
     }
 
-    aPos.AdjustX(nIconWidth );
-
+    aPos.AdjustX(nIconWidth);
 
-    rRenderContext.DrawText(aPos, rRenderContext.GetEllipsisString(msDescription, rDev.GetOutputSizePixel().Width() - aPos.X()));
+    //TODO, full width of widget ?
+    rRenderContext.DrawText(aPos, rRenderContext.GetEllipsisString(msDescription, rRect.GetWidth()));
 
-    aPos.AdjustY(nIconWidth );
+    aPos.AdjustY(nIconWidth);
 
     OUString sImage;
     switch (mpEffect->getPresetClass())
@@ -341,369 +396,129 @@ void CustomAnimationListEntryItem::Paint(const Point& rPos, SvTreeListBox& rDev,
     }
 
     aPos.AdjustX(nIconWidth );
-    aPos.AdjustY((nItemHeight/2 - rDev.GetTextHeight()) >> 1 );
-
-    rRenderContext.DrawText(aPos, rRenderContext.GetEllipsisString(msEffectName, rDev.GetOutputSizePixel().Width() - aPos.X()));
-}
-
-std::unique_ptr<SvLBoxItem> CustomAnimationListEntryItem::Clone(SvLBoxItem const *) const
-{
-    return nullptr;
-}
-
-namespace {
-
-class CustomAnimationListEntry : public SvTreeListEntry
-{
-public:
-    CustomAnimationListEntry();
-    explicit CustomAnimationListEntry(const CustomAnimationEffectPtr& pEffect);
-
-    const CustomAnimationEffectPtr& getEffect() const { return mpEffect; }
-
-private:
-    CustomAnimationEffectPtr mpEffect;
-};
+    aPos.AdjustY((nItemHeight/2 - rRenderContext.GetTextHeight()) >> 1 );
 
+    rRenderContext.DrawText(aPos, rRenderContext.GetEllipsisString(msEffectName, rRect.GetWidth()));
+    rRenderContext.Pop();
 }
 
-CustomAnimationListEntry::CustomAnimationListEntry()
-{
-}
-
-CustomAnimationListEntry::CustomAnimationListEntry(const CustomAnimationEffectPtr& pEffect)
-: mpEffect( pEffect )
-{
-}
-
-namespace {
-
-class CustomAnimationTriggerEntryItem : public SvLBoxString
+void CustomAnimationListEntryItem::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect, bool bSelected)
 {
-public:
-    explicit        CustomAnimationTriggerEntryItem( const OUString& aDescription );
-
-    void            InitViewData( SvTreeListBox*,SvTreeListEntry*,SvViewDataItem* = nullptr ) override;
-    virtual std::unique_ptr<SvLBoxItem> Clone(SvLBoxItem const * pSource) const override;
-    virtual void Paint(const Point& rPos, SvTreeListBox& rOutDev, vcl::RenderContext& rRenderContext,
-                       const SvViewDataEntry* pView, const SvTreeListEntry& rEntry) override;
-
-private:
-    OUString        msDescription;
-    static const long nIconWidth = 19;
-};
-
+    if (mpEffect)
+        PaintEffect(rRenderContext, rRect, bSelected);
+    else
+        PaintTrigger(rRenderContext, rRect);
 }
 
-CustomAnimationTriggerEntryItem::CustomAnimationTriggerEntryItem( const OUString& aDescription )
-: SvLBoxString( aDescription ), msDescription( aDescription )
+CustomAnimationList::CustomAnimationList(std::unique_ptr<weld::TreeView> xTreeView,
+                                         std::unique_ptr<weld::Label> xLabel,
+                                         std::unique_ptr<weld::Widget> xScrolledWindow)
+    : mxTreeView(std::move(xTreeView))
+    , maDropTargetHelper(*this)
+    , mxEmptyLabel(std::move(xLabel))
+    , mxEmptyLabelParent(std::move(xScrolledWindow))
+    , mbIgnorePaint(false)
+    , mpController(nullptr)
+    , mnLastGroupId(0)
+    , mnPostExpandEvent(nullptr)
+    , mnPostCollapseEvent(nullptr)
 {
+    mxEmptyLabel->set_stack_background();
+
+    mxTreeView->set_selection_mode(SelectionMode::Multiple);
+    mxTreeView->set_column_custom_renderer(0);
+    mxTreeView->connect_changed(LINK(this, CustomAnimationList, SelectHdl));
+    mxTreeView->connect_key_press(LINK(this, CustomAnimationList, KeyInputHdl));
+    mxTreeView->connect_popup_menu(LINK(this, CustomAnimationList, CommandHdl));
+    mxTreeView->connect_row_activated(LINK(this, CustomAnimationList, DoubleClickHdl));
+    mxTreeView->connect_expanding(LINK(this, CustomAnimationList, ExpandHdl));
+    mxTreeView->connect_collapsing(LINK(this, CustomAnimationList, CollapseHdl));
+    mxTreeView->connect_drag_begin(LINK(this, CustomAnimationList, DragBeginHdl));
+    mxTreeView->connect_custom_get_size(LINK(this, CustomAnimationList, CustomGetSizeHdl));
+    mxTreeView->connect_custom_render(LINK(this, CustomAnimationList, CustomRenderHdl));
 }
 
-void CustomAnimationTriggerEntryItem::InitViewData( SvTreeListBox* pView, SvTreeListEntry* pEntry, SvViewDataItem* pViewData )
+CustomAnimationListDropTarget::CustomAnimationListDropTarget(CustomAnimationList& rTreeView)
+    : DropTargetHelper(rTreeView.get_widget().get_drop_target())
+    , m_rTreeView(rTreeView)
 {
-    if( !pViewData )
-        pViewData = pView->GetViewDataItem( pEntry, this );
-
-    Size aSize(pView->GetTextWidth( msDescription ) + 2 * nIconWidth, pView->GetTextHeight() );
-    if( aSize.Height() < nIconWidth )
-        aSize.setHeight( nIconWidth );
-    pViewData->mnWidth = aSize.Width();
-    pViewData->mnHeight = aSize.Height();
 }
 
-void CustomAnimationTriggerEntryItem::Paint(const Point& rPos, SvTreeListBox& rDev, vcl::RenderContext& rRenderContext,
-                                            const SvViewDataEntry* /*pView*/, const SvTreeListEntry& /*rEntry*/)
+sal_Int8 CustomAnimationListDropTarget::AcceptDrop(const AcceptDropEvent& rEvt)
 {
-    Size aSize(rDev.GetOutputSizePixel().Width(), rDev.GetEntryHeight());
-
-    Point aPos(0, rPos.Y());
-
-    ::tools::Rectangle aOutRect(aPos, aSize);
-
-    // fill the background
-    Color aColor(rRenderContext.GetSettings().GetStyleSettings().GetDialogColor());
-
-    rRenderContext.Push();
-    rRenderContext.SetFillColor(aColor);
-    rRenderContext.SetLineColor();
-    rRenderContext.DrawRect(aOutRect);
-
-    // Erase the four corner pixels to make the rectangle appear rounded.
-    rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetWindowColor());
-    rRenderContext.DrawPixel(aOutRect.TopLeft());
-    rRenderContext.DrawPixel(Point(aOutRect.Right(), aOutRect.Top()));
-    rRenderContext.DrawPixel(Point(aOutRect.Left(), aOutRect.Bottom()));
-    rRenderContext.DrawPixel(Point(aOutRect.Right(), aOutRect.Bottom()));
-
-    // draw the category title
+    sal_Int8 nAccept = m_rTreeView.AcceptDrop(rEvt);
 
-    int nVertBorder = ((aSize.Height() - rDev.GetTextHeight()) >> 1);
-    int nHorzBorder = rRenderContext.LogicToPixel(Size(3, 3), MapMode(MapUnit::MapAppFont)).Width();
-
-    aOutRect.AdjustLeft(nHorzBorder );
-    aOutRect.AdjustRight( -nHorzBorder );
-    aOutRect.AdjustTop( nVertBorder );
-    aOutRect.AdjustBottom( -nVertBorder );
-
-    rRenderContext.DrawText(aOutRect, rRenderContext.GetEllipsisString(msDescription, aOutRect.GetWidth()));
-    rRenderContext.Pop();
-}
+    if (nAccept != DND_ACTION_NONE)
+    {
+        // to enable the autoscroll when we're close to the edges
+        weld::TreeView& rWidget = m_rTreeView.get_widget();
+        rWidget.get_dest_row_at_pos(rEvt.maPosPixel, nullptr);
+    }
 
-std::unique_ptr<SvLBoxItem> CustomAnimationTriggerEntryItem::Clone(SvLBoxItem const *) const
-{
-    return nullptr;
+    return nAccept;
 }
 
-CustomAnimationList::CustomAnimationList( vcl::Window* pParent )
-    : SvTreeListBox( pParent, WB_TABSTOP | WB_BORDER | WB_HASLINES | WB_HASBUTTONS | WB_HASBUTTONSATROOT )
-    , mbIgnorePaint(false)
-    , mpController(nullptr)
-    , mnLastGroupId(0)
-    , mpLastParentEntry(nullptr)
-    , mpDndEffectDragging(nullptr)
-    , mpDndEffectInsertBefore(nullptr)
+sal_Int8 CustomAnimationListDropTarget::ExecuteDrop(const ExecuteDropEvent& rEvt)
 {
-    EnableContextMenuHandling();
-    SetSelectionMode( SelectionMode::Multiple );
-    SetOptimalImageIndent();
-    SetNodeDefaultImages();
-
-    SetDragDropMode(DragDropMode::CTRL_MOVE);
+    return m_rTreeView.ExecuteDrop(rEvt);
 }
 
 // D'n'D #1: Record selected effects for drag'n'drop.
-void CustomAnimationList::StartDrag( sal_Int8 nAction, const Point& rPosPixel )
+IMPL_LINK(CustomAnimationList, DragBeginHdl, bool&, rUnsetDragIcon, bool)
 {
+    rUnsetDragIcon = false;
+
     // Record which effects are selected:
     // Since NextSelected(..) iterates through the selected items in the order they
     // were selected, create a sorted list for simpler drag'n'drop algorithms.
     mDndEffectsSelected.clear();
-    for( SvTreeListEntry* pEntry = First(); pEntry; pEntry = Next(pEntry) )
-    {
-        if( IsSelected(pEntry) )
-        {
-            mDndEffectsSelected.push_back( pEntry );
-        }
-    }
-
-    // Allow normal processing; this calls our NotifyStartDrag().
-    SvTreeListBox::StartDrag( nAction, rPosPixel );
-}
-
-// D'n'D #2: Prepare selected element for moving.
-DragDropMode CustomAnimationList::NotifyStartDrag( TransferDataContainer& /*rData*/, SvTreeListEntry* pEntry )
-{
-    // Restore selection for multiple selected effects.
-    // Do it here to remove a flicker on the UI with effects being unselected and reselected.
-    for( auto &pEffect : mDndEffectsSelected )
-        SelectListEntry( pEffect, true);
+    mxTreeView->selected_foreach([this](weld::TreeIter& rEntry){
+        mDndEffectsSelected.emplace_back(mxTreeView->make_iterator(&rEntry));
+        return false;
+    });
 
     // Note: pEntry is the effect with focus (if multiple effects are selected)
-    mpDndEffectDragging = pEntry;
-    mpDndEffectInsertBefore = pEntry;
+    mxDndEffectDragging = mxTreeView->make_iterator();
+    mxTreeView->get_cursor(mxDndEffectDragging.get());
+    mxDndEffectInsertBefore = mxTreeView->make_iterator(mxDndEffectDragging.get());
 
-    return DragDropMode::CTRL_MOVE;
+    // Allow normal processing.
+    return false;
 }
 
 // D'n'D #3: Called each time mouse moves during drag
 sal_Int8 CustomAnimationList::AcceptDrop( const AcceptDropEvent& rEvt )
 {
-    /*
-        Don't call SvTreeListBox::AcceptDrop because it puts an unnecessary
-        highlight via ImplShowTargetEmphasis()
-    */
-
     sal_Int8 ret = DND_ACTION_NONE;
 
-    const bool bIsMove = ( DND_ACTION_MOVE == rEvt.mnAction );
-    if( mpDndEffectDragging && !rEvt.mbLeaving && bIsMove )
-    {
-        SvTreeListEntry* pEntry = GetDropTarget( rEvt.maPosPixel );
-
-        const bool bOverASelectedEffect =
-            std::find( mDndEffectsSelected.begin(), mDndEffectsSelected.end(), pEntry ) != mDndEffectsSelected.end();
-        if( pEntry && !bOverASelectedEffect )
-        {
-            ReparentChildrenDuringDrag();
-
-            ReorderEffectsInUiDuringDragOver( pEntry );
-        }
-
-        // Return DND_ACTION_MOVE on internal drag'n'drops so that ExecuteDrop() is called.
-        // Return MOVE even if we are over other dragged effect because dragged effect moves.
+    const bool bIsMove = DND_ACTION_MOVE == rEvt.mnAction;
+    if (mxDndEffectDragging && !rEvt.mbLeaving && bIsMove)
         ret = DND_ACTION_MOVE;
-    }
-
     return ret;
 }
 
-// D'n'D: For each dragged effect, re-parent (only in the UI) non-selected
-//        visible children so they are not dragged with the parent.
-void CustomAnimationList::ReparentChildrenDuringDrag()
-{
-    /*
-        Re-parent (only in the UI!):
-          a) the dragged effect's first non-selected child to the root, and
-          b) the remaining non-selected children to that re-parented 1st child.
-    */
-    for( auto &pEffect : mDndEffectsSelected )
-    {
-        const bool bExpandedWithChildren = GetVisibleChildCount( pEffect ) > 0;
-        if( bExpandedWithChildren )
-        {
-            SvTreeListEntry* pEntryParent = GetParent( pEffect );
-
-            SvTreeListEntry* pFirstNonSelectedChild = nullptr;
-            sal_uLong nInsertNextChildPos = 0;
-
-            // Process all children of this effect
-            SvTreeListEntry* pChild = FirstChild( pEffect );
-            while( pChild && ( GetParent( pChild ) == pEffect ) )
-            {
-                // Start by finding next child because if pChild moves, we cannot then
-                // ask it what the next child is because it's no longer with its siblings.
-                SvTreeListEntry* pNextChild = Next( pChild );
-
-                // Skip selected effects: they stay with their previous parent to be moved.
-                // During drag, the IsSelected() set changes, so use mDndEffectsSelected instead
-                const bool bIsSelected = std::find( mDndEffectsSelected.begin(), mDndEffectsSelected.end(), pChild ) != mDndEffectsSelected.end();
-                if( !bIsSelected )
-                {
-                    // Re-parent 1st non-selected child to root, below all the other children.
-                    if( !pFirstNonSelectedChild )
-                    {
-                        pFirstNonSelectedChild = pChild;
-                        sal_uLong nInsertAfterPos = SvTreeList::GetRelPos( pEffect ) + 1;
-                        pModel->Move( pFirstNonSelectedChild, pEntryParent, nInsertAfterPos );
-                    }
-                    else
-                    {
-                        // Re-parent remaining non-selected children to 1st child
-                        ++nInsertNextChildPos;
-                        pModel->Move( pChild, pFirstNonSelectedChild, nInsertNextChildPos );
-                    }
-                }
-
-                pChild = pNextChild;
-            }
-
-            // Expand all children (they were previously visible)
-            if( pFirstNonSelectedChild )
-                Expand( pFirstNonSelectedChild );
-
-        }
-    }
-}
-
-// D'n'D: Update UI to show where dragged event will appear if dropped now.
-void CustomAnimationList::ReorderEffectsInUiDuringDragOver( SvTreeListEntry* pOverEntry )
-{
-    /*
-        Update the order of effects in *just the UI* while the user is dragging.
-        The model (MainSequence) will only be changed after the user drops
-        the effect so that there is minimal work to do if the drag is canceled.
-        Plus only one undo record should be created per drag, and changing
-        the model recreates all effects (on a background timer) which invalidates
-        all effect pointers.
-    */
-
-    // Compute new location in *UI*
-    SvTreeListEntry* pNewParent = nullptr;
-    sal_uLong nInsertAfterPos = 0;
-
-    Point aPosOverEffect( GetEntryPosition(pOverEntry) );
-    Point aPosDraggedEffect( GetEntryPosition(mpDndEffectDragging) );
-    const bool bDraggingUp = (aPosDraggedEffect.Y() - aPosOverEffect.Y()) > 0;
-
-    if( bDraggingUp )
-    {
-        // Drag up   --> place above the element we are over
-        pNewParent = GetParent( pOverEntry );
-        nInsertAfterPos = SvTreeList::GetRelPos( pOverEntry );
-        mpDndEffectInsertBefore = pOverEntry;
-    }
-    else
-    {
-        // Drag down -->  place below the element we are over
-        SvTreeListEntry* pNextVisBelowTarget = NextVisible( pOverEntry );
-        if( pNextVisBelowTarget )
-        {
-            // Match parent of NEXT visible effect (works for sub-items too)
-            pNewParent = GetParent( pNextVisBelowTarget );
-            nInsertAfterPos = SvTreeList::GetRelPos( pNextVisBelowTarget );
-            mpDndEffectInsertBefore = pNextVisBelowTarget;
-        }
-        else
-        {
-            // Over the last element: no next to work with
-            pNewParent = GetParent( pOverEntry );
-            nInsertAfterPos = SvTreeList::GetRelPos( pOverEntry ) + 1;
-            mpDndEffectInsertBefore = nullptr;
-        }
-    }
-
-    // Move each selected effect in *just* the UI to show where it would be if dropped.
-    // This leaves the exist parent relationships in the non-dragged elements so that
-    // the list does not seem to change structure during drag. Parent relationships will
-    // be correctly recreated on drop.
-    for( auto aItr = mDndEffectsSelected.rbegin();
-         aItr != mDndEffectsSelected.rend();
-         ++aItr)
-    {
-        SvTreeListEntry* pEffect = *aItr;
-
-        // Move only effects whose parents is not selected because
-        // they will automatically move when their parent is moved.
-        const bool bParentIsSelected =
-            std::find(mDndEffectsSelected.begin(), mDndEffectsSelected.end(), GetParent(pEffect)) != mDndEffectsSelected.end();
-
-        if( !bParentIsSelected )
-        {
-            // If the current effect is being moved down, the insert position must be decremented
-            // after move if it will have the same parent as it currently does because it moves
-            // from above the insertion point to below it, hence changing its index.
-            // Must decide move-up vs move-down for each effect being dragged because we may be
-            // processing a discontinuous set of selected effects (some below, some above insertion point)
-            Point aCurPosOverEffect( GetEntryPosition( pOverEntry ) );
-            Point aCurPosMovedEffect( GetEntryPosition( pEffect ) );
-            const bool bCurDraggingDown = ( aCurPosMovedEffect.Y() - aCurPosOverEffect.Y() ) < 0;
-            const bool bWillHaveSameParent = ( pNewParent == GetParent(pEffect) );
-
-            pModel->Move( pEffect, pNewParent, nInsertAfterPos );
-
-            if( bCurDraggingDown && bWillHaveSameParent )
-                --nInsertAfterPos;
-        }
-    }
-
-    // Restore selection (calling Select() is slow; SelectListEntry() is faster)
-    for( auto &pEffect : mDndEffectsSelected )
-        SelectListEntry( pEffect, true);
-}
-
 // D'n'D #5: Tell model to update effect order.
-sal_Int8 CustomAnimationList::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ )
+sal_Int8 CustomAnimationList::ExecuteDrop(const ExecuteDropEvent& rEvt)
 {
-    // NOTE: We cannot just override NotifyMoving() because it's not called
-    //       since we dynamically reorder effects during drag.
-
-    sal_Int8 ret = DND_ACTION_NONE;
+    if (!mxTreeView->get_dest_row_at_pos(rEvt.maPosPixel, mxDndEffectInsertBefore.get()))
+        mxDndEffectInsertBefore.reset();
 
-    const bool bMovingEffect = ( mpDndEffectDragging != nullptr );
-    const bool bMoveNotSelf  = ( mpDndEffectInsertBefore != mpDndEffectDragging );
+    const bool bMovingEffect = ( mxDndEffectDragging != nullptr );
+    const bool bMoveNotSelf  = !mxDndEffectInsertBefore || (mxDndEffectDragging && mxTreeView->iter_compare(*mxDndEffectInsertBefore, *mxDndEffectDragging) != 0);
     const bool bHaveSequence = ( mpMainSequence.get() != nullptr );
 
     if( bMovingEffect && bMoveNotSelf && bHaveSequence )
     {
-        CustomAnimationListEntry*  pTarget = static_cast< CustomAnimationListEntry* >( mpDndEffectInsertBefore );
+        CustomAnimationListEntryItem* pTarget = mxDndEffectInsertBefore ?
+                                                    reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(*mxDndEffectInsertBefore).toInt64()) :
+                                                    nullptr;
 
         // Build list of effects
         std::vector< CustomAnimationEffectPtr > aEffects;
         for( const auto &pEntry : mDndEffectsSelected )
         {
-            CustomAnimationListEntry* pCustomAnimationEffect = static_cast< CustomAnimationListEntry* >( pEntry );
-            aEffects.push_back( pCustomAnimationEffect->getEffect() );
+            CustomAnimationListEntryItem* pCustomAnimationEffect = reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(*pEntry).toInt64());
+            aEffects.push_back(pCustomAnimationEffect->getEffect());
         }
 
         // Callback to observer to have it update the model.
@@ -713,90 +528,82 @@ sal_Int8 CustomAnimationList::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ )
             pTarget ? pTarget->getEffect() : nullptr );
 
         // Reset selection
-        Select( mpDndEffectDragging );
-
-        ret = DND_ACTION_MOVE;
+        mxTreeView->select(*mxDndEffectDragging);
+        Select();
     }
 
-    // NOTE: Don't call SvTreeListBox::ExecuteDrop(...) because all required
+    // NOTE: Don't call default handler because all required
     //       move operations have been completed here to update the model.
-    return ret;
-}
-
-// D'n'D #6: Cleanup (regardless of if we were target of drop or not)
-void CustomAnimationList::DragFinished( sal_Int8 /*nDropAction*/ )
-{
-    mpDndEffectDragging = nullptr;
-    mpDndEffectInsertBefore = nullptr;
-    mDndEffectsSelected.clear();
-
-    // Rebuild because we may have re-parented the dragged effect's first child.
-    // Can hit this without running ExecuteDrop(...) when drag canceled.
-    mpMainSequence->rebuild();
-
-    // Note: Don't call SvTreeListBox::DragFinished(...) because we don't call
-    //       SvTreeListBox::ExecuteDrop(...) which sets variables that are
-    //       needed in its DragFinished(...) method.
+    return DND_ACTION_NONE;
 }
 
-VCL_BUILDER_FACTORY(CustomAnimationList)
-
 CustomAnimationList::~CustomAnimationList()
 {
-    disposeOnce();
-}
+    if (mnPostExpandEvent)
+    {
+        Application::RemoveUserEvent(mnPostExpandEvent);
+        mnPostExpandEvent = nullptr;
+    }
+
+    if (mnPostCollapseEvent)
+    {
+        Application::RemoveUserEvent(mnPostCollapseEvent);
+        mnPostCollapseEvent = nullptr;
+    }
 
-void CustomAnimationList::dispose()
-{
     if( mpMainSequence.get() )
         mpMainSequence->removeListener( this );
 
     clear();
-
-    mxMenu.disposeAndClear();
-    mxBuilder.reset();
-
-    SvTreeListBox::dispose();
 }
 
-void CustomAnimationList::KeyInput( const KeyEvent& rKEvt )
+IMPL_LINK(CustomAnimationList, KeyInputHdl, const KeyEvent&, rKEvt, bool)
 {
     const int nKeyCode = rKEvt.GetKeyCode().GetCode();
-    switch( nKeyCode )
+    switch (nKeyCode)
     {
         case KEY_DELETE:
             mpController->onContextMenu("remove");
-            return;
+            return true;
         case KEY_INSERT:
             mpController->onContextMenu("create");
-            return;
+            return true;
         case KEY_SPACE:
+        {
+            std::unique_ptr<weld::TreeIter> xEntry = mxTreeView->make_iterator();
+            if (mxTreeView->get_cursor(xEntry.get()))
             {
-                const Point aPos;
-                const CommandEvent aCEvt( aPos, CommandEventId::ContextMenu );
-                Command( aCEvt );
-                return;
+                auto aRect = mxTreeView->get_row_area(*xEntry);
+                const Point aPos(aRect.getWidth() / 2, aRect.getHeight() / 2);
+                const CommandEvent aCEvt(aPos, CommandEventId::ContextMenu);
+                CommandHdl(aCEvt);
+                return true;
             }
-
+        }
     }
-
-    ::SvTreeListBox::KeyInput( rKEvt );
+    return false;
 }
 
 /** selects or deselects the given effect.
     Selections of other effects are not changed */
 void CustomAnimationList::select( const CustomAnimationEffectPtr& pEffect )
 {
-    CustomAnimationListEntry* pEntry = static_cast< CustomAnimationListEntry* >(First());
-    while( pEntry )
+    CustomAnimationListEntryItem* pEntry = nullptr;
+
+    std::unique_ptr<weld::TreeIter> xEntry = mxTreeView->make_iterator();
+    if (mxTreeView->get_iter_first(*xEntry))
     {
-        if( pEntry->getEffect() == pEffect )
+        do
         {
-            Select( pEntry );
-            MakeVisible( pEntry );
-            break;
-        }
-        pEntry = static_cast< CustomAnimationListEntry* >(Next( pEntry ));
+            CustomAnimationListEntryItem* pTestEntry = reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(*xEntry).toInt64());
+            if (pTestEntry->getEffect() == pEffect)
+            {
+                mxTreeView->select(*xEntry);
+                mxTreeView->scroll_to_row(*xEntry);
+                pEntry = pTestEntry;
+                break;
+            }
+        } while (mxTreeView->iter_next(*xEntry));
     }
 
     if( !pEntry )
@@ -808,9 +615,13 @@ void CustomAnimationList::select( const CustomAnimationEffectPtr& pEffect )
 
 void CustomAnimationList::clear()
 {
-    Clear();
+    mxEntries.clear();
+    mxTreeView->clear();
 
-    mpLastParentEntry = nullptr;
+    mxEmptyLabelParent->show();
+    mxTreeView->hide();
+
+    mxLastParentEntry.reset();
     mxLastTargetShape = nullptr;
 }
 
@@ -841,9 +652,6 @@ void stl_append_effect_func::operator()(const CustomAnimationEffectPtr& pEffect)
 void CustomAnimationList::update()
 {
     mbIgnorePaint = true;
-    SetUpdateMode( false );
-
-    CustomAnimationListEntry* pEntry = nullptr;
 
     std::vector< CustomAnimationEffectPtr > aVisible;
     std::vector< CustomAnimationEffectPtr > aSelected;
@@ -856,62 +664,77 @@ void CustomAnimationList::update()
     long nFirstSelOld = -1;
     long nLastSelOld = -1;
 
+    std::unique_ptr<weld::TreeIter> xEntry = mxTreeView->make_iterator();
+
     if( mpMainSequence.get() )
     {
-        // save scroll position
-        pEntry = static_cast<CustomAnimationListEntry*>(GetFirstEntryInView());
-        if( pEntry )
-            nFirstVis = GetAbsPos( pEntry );
+        std::unique_ptr<weld::TreeIter> xLastSelectedEntry;
+        std::unique_ptr<weld::TreeIter> xLastVisibleEntry;
 
-        pEntry = static_cast<CustomAnimationListEntry*>(GetLastEntryInView());
-        if( pEntry )
-            nLastVis = GetAbsPos( pEntry );
+        // save selection, current, and expand (visible) states
+        mxTreeView->all_foreach([this, &aVisible, &nFirstVis, &xLastVisibleEntry,
+                                 &aSelected, &nFirstSelOld, &pFirstSelEffect, &xLastSelectedEntry](weld::TreeIter& rEntry){
+            CustomAnimationListEntryItem* pEntry = reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(rEntry).toInt64());
+            CustomAnimationEffectPtr pEffect(pEntry->getEffect());
+            if (pEffect.get())
+            {
+                if (weld::IsEntryVisible(*mxTreeView, rEntry))
+                {
+                    aVisible.push_back(pEffect);
+                    // save scroll position
+                    if (nFirstVis == -1)
+                        nFirstVis = weld::GetAbsPos(*mxTreeView, rEntry);
+                    if (!xLastVisibleEntry)
+                        xLastVisibleEntry = mxTreeView->make_iterator(&rEntry);
+                    else
+                        mxTreeView->copy_iterator(rEntry, *xLastVisibleEntry);
+                }
 
-        pEntry = static_cast<CustomAnimationListEntry*>(FirstSelected());
-        if( pEntry )
-        {
-            pFirstSelEffect = pEntry->getEffect();
-            nFirstSelOld = GetAbsPos( pEntry );
-        }
+                if (mxTreeView->is_selected(rEntry))
+                {
+                    aSelected.push_back(pEffect);
+                    if (nFirstSelOld == -1)
+                    {
+                        pFirstSelEffect = pEffect;
+                        nFirstSelOld = weld::GetAbsPos(*mxTreeView, rEntry);
+                    }
+                    if (!xLastSelectedEntry)
+                        xLastSelectedEntry = mxTreeView->make_iterator(&rEntry);
+                    else
+                        mxTreeView->copy_iterator(rEntry, *xLastSelectedEntry);
+                }
+            }
+
+            return false;
+        });
 
-        pEntry = static_cast<CustomAnimationListEntry*>(LastSelected());
-        if( pEntry )
+        if (xLastSelectedEntry)
         {
+            CustomAnimationListEntryItem* pEntry = reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(*xLastSelectedEntry).toInt64());
             pLastSelEffect = pEntry->getEffect();
-            nLastSelOld = GetAbsPos( pEntry );
+            nLastSelOld = weld::GetAbsPos(*mxTreeView, *xLastSelectedEntry);
         }
 
-        // save selection, current, and expand (visible) states
-        pEntry = static_cast<CustomAnimationListEntry*>(First());
+        if (xLastVisibleEntry)
+            nLastVis = weld::GetAbsPos(*mxTreeView, *xLastVisibleEntry);
 
-        while( pEntry )
+        if (mxTreeView->get_cursor(xEntry.get()))
         {
-            CustomAnimationEffectPtr pEffect( pEntry->getEffect() );
-            if( pEffect.get() )
-            {
-                if( IsEntryVisible( pEntry ) )
-                    aVisible.push_back( pEffect );
-
-                if( IsSelected( pEntry ) )
-                    aSelected.push_back( pEffect );
-            }
-
-            pEntry = static_cast<CustomAnimationListEntry*>(Next( pEntry ));
-        }
-
-        pEntry = static_cast<CustomAnimationListEntry*>(GetCurEntry());
-        if( pEntry )
+            CustomAnimationListEntryItem* pEntry = reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(*xEntry).toInt64());
             aCurrent = pEntry->getEffect();
+        }
     }
 
     // rebuild list
+
+    mxTreeView->freeze();
+
     clear();
-    if( mpMainSequence.get() )
+
+    if (mpMainSequence.get())
     {
-        long nFirstSelNew = -1;
-        long nLastSelNew = -1;
         std::for_each( mpMainSequence->getBegin(), mpMainSequence->getEnd(), stl_append_effect_func( *this ) );
-        mpLastParentEntry = nullptr;
+        mxLastParentEntry.reset();
 
         auto rInteractiveSequenceVector = mpMainSequence->getInteractiveSequenceVector();
 
@@ -920,54 +743,76 @@ void CustomAnimationList::update()
             Reference< XShape > xShape( pIS->getTriggerShape() );
             if( xShape.is() )
             {
-                SvTreeListEntry* pLBoxEntry = new CustomAnimationListEntry;
-                pLBoxEntry->AddItem(std::make_unique<SvLBoxContextBmp>(Image(), Image(), false));
                 OUString aDescription = SdResId(STR_CUSTOMANIMATION_TRIGGER) + ": " +
                     getShapeDescription( xShape, false );
-                pLBoxEntry->AddItem(std::make_unique<CustomAnimationTriggerEntryItem>(aDescription));
-                Insert( pLBoxEntry );
-                SvViewDataEntry* pViewData = GetViewData( pLBoxEntry );
-                if( pViewData )
-                    pViewData->SetSelectable(false);
 
+                mxEntries.emplace_back(std::make_unique<CustomAnimationListEntryItem>(aDescription, nullptr));
+
+                OUString sId(OUString::number(reinterpret_cast<sal_Int64>(mxEntries.back().get())));
+                mxTreeView->insert(nullptr, -1, &aDescription, &sId, nullptr, nullptr, nullptr, false, nullptr);
                 std::for_each( pIS->getBegin(), pIS->getEnd(), stl_append_effect_func( *this ) );
-                mpLastParentEntry = nullptr;
+                mxLastParentEntry.reset();
             }
         }
+    }
 
-        // restore selection state, expand state, and current-entry (under cursor)
-        pEntry = static_cast<CustomAnimationListEntry*>(First());
+    mxTreeView->thaw();
 
-        while( pEntry )
+    if (mxTreeView->n_children())
+    {
+        mxEmptyLabelParent->hide();
+        mxTreeView->show();
+    }
+
+    if (mpMainSequence.get())
+    {
+        long nFirstSelNew = -1;
+        long nLastSelNew = -1;
+
+        std::vector<std::unique_ptr<weld::TreeIter>> aNewSelection;
+
+        // restore selection state, expand state, and current-entry (under cursor)
+        if (mxTreeView->get_iter_first(*xEntry))
         {
-            CustomAnimationEffectPtr pEffect( pEntry->getEffect() );
-            if( pEffect.get() )
+            do
             {
-                // Any effects that were visible should still be visible, so expand their parents.
-                // (a previously expanded parent may have moved leaving a child to now be the new parent to expand)
-                if( std::find( aVisible.begin(), aVisible.end(), pEffect ) != aVisible.end() )
-                {
-                    if( GetParent(pEntry) )
-                        Expand( GetParent(pEntry) );
-                }
+                CustomAnimationListEntryItem* pEntry = reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(*xEntry).toInt64());
 
-                if( std::find( aSelected.begin(), aSelected.end(), pEffect ) != aSelected.end() )
-                    Select( pEntry );
+                CustomAnimationEffectPtr pEffect( pEntry->getEffect() );
+                if (pEffect.get())
+                {
+                    // Any effects that were visible should still be visible, so expand their parents.
+                    // (a previously expanded parent may have moved leaving a child to now be the new parent to expand)
+                    if( std::find( aVisible.begin(), aVisible.end(), pEffect ) != aVisible.end() )
+                    {
+                        if (mxTreeView->get_iter_depth(*xEntry))
+                        {
+                            std::unique_ptr<weld::TreeIter> xParentEntry = mxTreeView->make_iterator(xEntry.get());
+                            mxTreeView->iter_parent(*xParentEntry);
+                            mxTreeView->expand_row(*xParentEntry);
+                        }
+                    }
 
-                // Restore the cursor; don't use SetCurEntry() as it may deselect other effects
-                if( pEffect == aCurrent )
-                    SetCursor( pEntry );
+                    if( std::find( aSelected.begin(), aSelected.end(), pEffect ) != aSelected.end() )
+                        aNewSelection.emplace_back(mxTreeView->make_iterator(xEntry.get()));
 
-                if( pEffect == pFirstSelEffect )
-                    nFirstSelNew = GetAbsPos( pEntry );
+                    // Restore the cursor, as it may deselect other effects wait until
+                    // after the loop to reset the selection
+                    if( pEffect == aCurrent )
+                        mxTreeView->set_cursor(*xEntry);
 
-                if( pEffect == pLastSelEffect )
-                    nLastSelNew = GetAbsPos( pEntry );
-            }
+                    if (pEffect == pFirstSelEffect)
+                        nFirstSelNew = weld::GetAbsPos(*mxTreeView, *xEntry);
 
-            pEntry = static_cast<CustomAnimationListEntry*>(Next( pEntry ));
+                    if (pEffect == pLastSelEffect)
+                        nLastSelNew = weld::GetAbsPos(*mxTreeView, *xEntry);
+                }
+            } while (mxTreeView->iter_next(*xEntry));
         }
 
+        for (const auto& rEntry : aNewSelection)
+            mxTreeView->select(*rEntry);
+
         // Scroll to a selected entry, depending on where the selection moved.
         const bool bMoved = nFirstSelNew != nFirstSelOld;
         const bool bMovedUp = nFirstSelNew < nFirstSelOld;
@@ -981,103 +826,104 @@ void CustomAnimationList::update()
             {
                 // The entries in the selection range can't fit in view.
                 // Scroll so the last selected entry is last in view.
-                ScrollToAbsPos( nLastSelNew - (nLastVis - nFirstVis) );
+                mxTreeView->vadjustment_set_value(nLastSelNew - (nLastVis - nFirstVis));
             }
             else
-                ScrollToAbsPos( nFirstSelNew );
+                mxTreeView->vadjustment_set_value(nFirstSelNew);
         }
         else if( bMoved && nFirstSelOld > nLastVis && nFirstSelNew > nLastVis )
         {
             // The selection is below the visible area.
             // Scroll down to the first few selected entries.
-            ScrollToAbsPos( nFirstSelNew );
+            mxTreeView->vadjustment_set_value(nFirstSelNew);
         }
         else if( bMovedUp && nFirstSelOld <= nFirstVis )
         {
             // A visible entry has moved up out of view; scroll up one.
-            ScrollToAbsPos( nFirstVis - 1 );
+            mxTreeView->vadjustment_set_value(nFirstVis - 1);
         }
         else if( bMovedDown && nLastSelOld >= nLastVis )
         {
             // An entry has moved down out of view; scroll down one.
-            ScrollToAbsPos( nFirstVis + 1 );
+            mxTreeView->vadjustment_set_value(nFirstVis + 1);
         }
         else if ( nFirstVis != -1 )
         {
             // The selection is still in view, or it hasn't moved.
-            ScrollToAbsPos( nFirstVis );
+            mxTreeView->vadjustment_set_value(nFirstVis);
         }
     }
 
     mbIgnorePaint = false;
-    SetUpdateMode( true );
-    Invalidate();
+
+    Select();
 }
 
 void CustomAnimationList::append( CustomAnimationEffectPtr pEffect )
 {
-    // create a ui description
-    OUString aDescription;
-
     Any aTarget( pEffect->getTarget() );
     if( !aTarget.hasValue() )
         return;
 
     try
     {
-        aDescription = getDescription( aTarget, pEffect->getTargetSubItem() != ShapeAnimationSubType::ONLY_BACKGROUND );
+        // create a ui description
+        OUString aDescription = getDescription(aTarget, pEffect->getTargetSubItem() != ShapeAnimationSubType::ONLY_BACKGROUND);
 
-        SvTreeListEntry* pParentEntry = nullptr;
+        std::unique_ptr<weld::TreeIter> xParentEntry;
 
         Reference< XShape > xTargetShape( pEffect->getTargetShape() );
         sal_Int32 nGroupId = pEffect->getGroupId();
 
         // if this effect has the same target and group-id as the last root effect,
         // the last root effect is also this effects parent
-        if( mpLastParentEntry && (nGroupId != -1) && (mxLastTargetShape == xTargetShape) && (mnLastGroupId == nGroupId) )
-            pParentEntry = mpLastParentEntry;
+        if (mxLastParentEntry && nGroupId != -1 && mxLastTargetShape == xTargetShape && mnLastGroupId == nGroupId)
+            xParentEntry = mxTreeView->make_iterator(mxLastParentEntry.get());
 
         // create an entry for the effect
-        SvTreeListEntry* pEntry = new CustomAnimationListEntry( pEffect );
+        std::unique_ptr<weld::TreeIter> xEntry = mxTreeView->make_iterator();
+
+        mxEntries.emplace_back(std::make_unique<CustomAnimationListEntryItem>(aDescription, pEffect));
 
-        pEntry->AddItem(std::make_unique<SvLBoxContextBmp>(Image(), Image(), false));
-        pEntry->AddItem(std::make_unique<CustomAnimationListEntryItem>(aDescription, pEffect, this));
+        OUString sId(OUString::number(reinterpret_cast<sal_Int64>(mxEntries.back().get())));
 
-        if( pParentEntry )
+        if (xParentEntry)
         {
             // add a subentry
-            Insert( pEntry, pParentEntry );
+            mxTreeView->insert(xParentEntry.get(), -1, &aDescription, &sId, nullptr, nullptr, nullptr, false, xEntry.get());
         }
         else
         {
             // add a root entry
-            Insert( pEntry );
+            mxTreeView->insert(nullptr, -1, &aDescription, &sId, nullptr, nullptr, nullptr, false, xEntry.get());
 
             // and the new root entry becomes the possible next group header
             mxLastTargetShape = xTargetShape;
             mnLastGroupId = nGroupId;
-            mpLastParentEntry = pEntry;
+            mxLastParentEntry = std::move(xEntry);
         }
     }
-    catch( Exception& )
+    catch (const Exception&)
     {
         OSL_FAIL("sd::CustomAnimationList::append(), exception caught!" );
     }
 }
 
-static void selectShape( SvTreeListBox* pTreeList, const Reference< XShape >& xShape )
+static void selectShape(weld::TreeView* pTreeList, const Reference< XShape >& xShape )
 {
-    CustomAnimationListEntry* pEntry = static_cast< CustomAnimationListEntry* >(pTreeList->First());
-    while( pEntry )
+    std::unique_ptr<weld::TreeIter> xEntry = pTreeList->make_iterator();
+    if (pTreeList->get_iter_first(*xEntry))
     {
-        CustomAnimationEffectPtr pEffect( pEntry->getEffect() );
-        if( pEffect.get() )
+        do
         {
-            if( pEffect->getTarget() == xShape )
-                pTreeList->Select( pEntry );
-        }
-
-        pEntry = static_cast< CustomAnimationListEntry* >(pTreeList->Next( pEntry ));
+            CustomAnimationListEntryItem* pEntry = reinterpret_cast<CustomAnimationListEntryItem*>(pTreeList->get_id(*xEntry).toInt64());
+            CustomAnimationEffectPtr pEffect(pEntry->getEffect());
+            if (pEffect)
+            {
+                if (pEffect->getTarget() == xShape)
+                    pTreeList->select(*xEntry);
+            }
+        } while (pTreeList->iter_next(*xEntry));
     }
 }
 
@@ -1085,7 +931,7 @@ void CustomAnimationList::onSelectionChanged(const Any& rSelection)
 {
     try
     {
-        SelectAll(false);
+        mxTreeView->unselect_all();
 
         if (rSelection.hasValue())
         {
@@ -1098,18 +944,18 @@ void CustomAnimationList::onSelectionChanged(const Any& rSelection)
                 {
                     Reference< XShape > xShape( xShapes->getByIndex( nIndex ), UNO_QUERY );
                     if( xShape.is() )
-                        selectShape( this, xShape );
+                        selectShape(mxTreeView.get(), xShape);
                 }
             }
             else
             {
                 Reference< XShape > xShape(rSelection, UNO_QUERY);
                 if( xShape.is() )
-                    selectShape( this, xShape );
+                    selectShape(mxTreeView.get(), xShape);
             }
         }
 
-        SelectHdl();
+        Select();
     }
     catch( Exception& )
     {
@@ -1117,170 +963,186 @@ void CustomAnimationList::onSelectionChanged(const Any& rSelection)
     }
 }
 
-// Notify controller to refresh UI when we are notified of selection change from base class
-void CustomAnimationList::SelectHdl()
+IMPL_LINK_NOARG(CustomAnimationList, SelectHdl, weld::TreeView&, void)
 {
-    if( mbIgnorePaint )
-        return;
-    SvTreeListBox::SelectHdl();
-    mpController->onSelect();
+    Select();
 }
 
 // Notify controller to refresh UI when we are notified of selection change from base class
-void CustomAnimationList::DeselectHdl()
+void CustomAnimationList::Select()
 {
     if( mbIgnorePaint )
         return;
-    SvTreeListBox::DeselectHdl();
     mpController->onSelect();
 }
 
-
-bool CustomAnimationList::Expand( SvTreeListEntry* pParent )
+IMPL_LINK_NOARG(CustomAnimationList, PostExpandHdl, void*, void)
 {
-    bool result = SvTreeListBox::Expand( pParent );
-
-    // If expanded entry is selected, then select its children too.
-    if( IsSelected( pParent )) {
-        for( auto pChild = FirstChild( pParent ); pChild; pChild = pChild->NextSibling() )
+    std::unique_ptr<weld::TreeIter> xEntry = mxTreeView->make_iterator();
+    if (mxTreeView->get_selected(xEntry.get()))
+    {
+        for (bool bChild = mxTreeView->iter_children(*xEntry); bChild; bChild = mxTreeView->iter_next_sibling(*xEntry))
         {
-            if( !IsSelected( pChild ) )
-            {
-                SelectListEntry( pChild, true );
-            }
+            if (!mxTreeView->is_selected(*xEntry))
+                mxTreeView->select(*xEntry);
         }
     }
 
     // Notify controller that selection has changed (it should update the UI)
     mpController->onSelect();
 
-    return result;
+    mnPostExpandEvent = nullptr;
 }
 
-bool CustomAnimationList::Collapse( SvTreeListEntry* pParent )
+IMPL_LINK(CustomAnimationList, ExpandHdl, const weld::TreeIter&, rParent, bool)
 {
-    // SvTreeListBox::Collapse(..) discards multi-selection state
-    // of list entries, so first save current selection state
-    std::vector< SvTreeListEntry* > selectedEntries;
-    for( auto pEntry = FirstSelected(); pEntry; pEntry = NextSelected( pEntry ))
-    {
-        selectedEntries.push_back( pEntry );
+    // If expanded entry is selected, then select its children too afterwards.
+    if (mxTreeView->is_selected(rParent) && !mnPostExpandEvent) {
+        mnPostExpandEvent = Application::PostUserEvent(LINK(this, CustomAnimationList, PostExpandHdl));
     }
 
-    // Execute collapse on base class
-    bool result = SvTreeListBox::Collapse( pParent );
+    return true;
+}
 
+IMPL_LINK_NOARG(CustomAnimationList, PostCollapseHdl, void*, void)
+{
     // Deselect all entries as SvTreeListBox::Collapse selects the last
     // entry to have focus (or its parent), which is not desired
-    for( auto pEntry = FirstSelected(); pEntry; pEntry = NextSelected( pEntry ))
-    {
-        SelectListEntry( pEntry, false );
-    }
+    mxTreeView->unselect_all();
 
     // Restore selection state for entries which are still visible
-    for( auto &pEntry : selectedEntries )
+    for (auto &pEntry : lastSelectedEntries)
     {
-        if( IsEntryVisible( pEntry ))
-        {
-            SelectListEntry( pEntry, true );
-        }
+        if (weld::IsEntryVisible(*mxTreeView, *pEntry))
+            mxTreeView->select(*pEntry);
     }
 
+    lastSelectedEntries.clear();
+
     // Notify controller that selection has changed (it should update the UI)
     mpController->onSelect();
 
-    return result;
+    mnPostCollapseEvent = nullptr;
 }
 
-bool CustomAnimationList::isExpanded( const CustomAnimationEffectPtr& pEffect ) const
+IMPL_LINK_NOARG(CustomAnimationList, CollapseHdl, const weld::TreeIter&, bool)
 {
-    CustomAnimationListEntry* pEntry = static_cast<CustomAnimationListEntry*>(First());
-
-    while( pEntry )
+    if (!mnPostCollapseEvent)
     {
-        if( pEntry->getEffect() == pEffect )
-            break;
-
-        pEntry = static_cast<CustomAnimationListEntry*>(Next( pEntry ));
+        // weld::TreeView::collapse() discards multi-selection state
+        // of list entries, so first save current selection state
+        mxTreeView->selected_foreach([this](weld::TreeIter& rEntry){
+            lastSelectedEntries.emplace_back(mxTreeView->make_iterator(&rEntry));
+            return false;
+        });
+
+        mnPostCollapseEvent = Application::PostUserEvent(LINK(this, CustomAnimationList, PostCollapseHdl));
     }
 
-    if( pEntry )
-        pEntry = static_cast<CustomAnimationListEntry*>(GetParent( pEntry ));
-
-    return (pEntry == nullptr) || IsExpanded( pEntry );
+    // Execute collapse on base class
+    return true;
 }
 
-bool CustomAnimationList::isVisible( const CustomAnimationEffectPtr& pEffect ) const
+bool CustomAnimationList::isExpanded( const CustomAnimationEffectPtr& pEffect ) const
 {
-    CustomAnimationListEntry* pEntry = static_cast<CustomAnimationListEntry*>(First());
+    bool bExpanded = true; // we assume expanded by default
 
-    while( pEntry )
+    std::unique_ptr<weld::TreeIter> xEntry = mxTreeView->make_iterator();
+    if (mxTreeView->get_iter_first(*xEntry))
     {
-        if( pEntry->getEffect() == pEffect )
-            break;
-
-        pEntry = static_cast<CustomAnimationListEntry*>(Next( pEntry ));
+        do
+        {
+            CustomAnimationListEntryItem* pEntry =
+                reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(*xEntry).toInt64());
+            if (pEntry->getEffect() == pEffect)
+            {
+                if (mxTreeView->get_iter_depth(*xEntry)) // no parent, keep expanded default of true
+                {
+                    std::unique_ptr<weld::TreeIter> xParentEntry = mxTreeView->make_iterator(xEntry.get());
+                    if (mxTreeView->iter_parent(*xParentEntry))
+                        bExpanded = mxTreeView->get_row_expanded(*xParentEntry);
+                }
+                break;
+            }
+        } while (mxTreeView->iter_next(*xEntry));
     }
 
-    return (pEntry == nullptr) || IsEntryVisible( pEntry );
+    return bExpanded;
+}
+
+bool CustomAnimationList::isVisible(const CustomAnimationEffectPtr& pEffect) const
+{
+    std::unique_ptr<weld::TreeIter> xEntry = mxTreeView->make_iterator();
+    if (mxTreeView->get_iter_first(*xEntry))
+    {
+        do
+        {
+            CustomAnimationListEntryItem* pTestEntry = reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(*xEntry).toInt64());
+            if (pTestEntry->getEffect() == pEffect)
+                return weld::IsEntryVisible(*mxTreeView, *xEntry);
+        } while (mxTreeView->iter_next(*xEntry));
+    }
+    return true;
 }
 
 EffectSequence CustomAnimationList::getSelection() const
 {
     EffectSequence aSelection;
 
-    CustomAnimationListEntry* pEntry = dynamic_cast< CustomAnimationListEntry* >(FirstSelected());
-    while( pEntry )
-    {
-        CustomAnimationEffectPtr pEffect( pEntry->getEffect() );
-        if( pEffect.get() )
-            aSelection.push_back( pEffect );
+    mxTreeView->selected_foreach([this, &aSelection](weld::TreeIter& rEntry){
+        CustomAnimationListEntryItem* pEntry = reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(rEntry).toInt64());
+        CustomAnimationEffectPtr pEffect(pEntry->getEffect());
+        if (pEffect)
+            aSelection.push_back(pEffect);
 
         // if the selected effect is not expanded and has children
         // we say that the children are automatically selected
-        if( !IsExpanded( pEntry ) )
+        if (!mxTreeView->get_row_expanded(rEntry) && mxTreeView->iter_has_child(rEntry))
         {
-            CustomAnimationListEntry* pChild = dynamic_cast< CustomAnimationListEntry* >( FirstChild( pEntry ) );
-            while( pChild )
+            std::unique_ptr<weld::TreeIter> xChild = mxTreeView->make_iterator(&rEntry);
+            mxTreeView->iter_children(*xChild);
+
+            do
             {
-                if( !IsSelected( pChild ) )
+                if (!mxTreeView->is_selected(*xChild))
                 {
+                    CustomAnimationListEntryItem* pChild = reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(*xChild).toInt64());
                     const CustomAnimationEffectPtr& pChildEffect( pChild->getEffect() );
                     if( pChildEffect.get() )
                         aSelection.push_back( pChildEffect );
                 }
-
-                pChild = dynamic_cast< CustomAnimationListEntry* >(  pChild->NextSibling() );
-            }
+            } while (mxTreeView->iter_next_sibling(*xChild));
         }
 
-        pEntry = static_cast< CustomAnimationListEntry* >(NextSelected( pEntry ));
-    }
+        return false;
+    });
 
     return aSelection;
 }
 
-bool CustomAnimationList::DoubleClickHdl()
+IMPL_LINK_NOARG(CustomAnimationList, DoubleClickHdl, weld::TreeView&, bool)
 {
     mpController->onDoubleClick();
     return false;
 }
 
-VclPtr<PopupMenu> CustomAnimationList::CreateContextMenu()
+IMPL_LINK(CustomAnimationList, CommandHdl, const CommandEvent&, rCEvt, bool)
 {
-    mxMenu.disposeAndClear();
-    mxBuilder.reset(new VclBuilder(nullptr, VclBuilderContainer::getUIRootDir(), "modules/simpress/ui/effectmenu.ui", ""));
-    mxMenu.set(mxBuilder->get_menu("menu"));
+    if (rCEvt.GetCommand() != CommandEventId::ContextMenu)
+        return false;
+
+    std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(mxTreeView.get(), "modules/simpress/ui/effectmenu.ui"));
+    std::unique_ptr<weld::Menu> xMenu = xBuilder->weld_menu("menu");
 
     sal_Int16 nNodeType = -1;
     sal_Int16 nEntries = 0;
 
-    CustomAnimationListEntry* pEntry = static_cast< CustomAnimationListEntry* >(FirstSelected());
-    while( pEntry )
-    {
+    mxTreeView->selected_foreach([this, &nNodeType, &nEntries](weld::TreeIter& rEntry){
+        CustomAnimationListEntryItem* pEntry = reinterpret_cast<CustomAnimationListEntryItem*>(mxTreeView->get_id(rEntry).toInt64());
+        CustomAnimationEffectPtr pEffect(pEntry->getEffect());
+
         nEntries++;
-        CustomAnimationEffectPtr pEffect( pEntry->getEffect() );
-        if( pEffect.get() )
+        if (pEffect.get())
         {
             if( nNodeType == -1 )
             {
@@ -1291,26 +1153,30 @@ VclPtr<PopupMenu> CustomAnimationList::CreateContextMenu()
                 if( nNodeType != pEffect->getNodeType() )
                 {
                     nNodeType = -1;
-                    break;
+                    return true;
                 }
             }
         }
 
-        pEntry = static_cast< CustomAnimationListEntry* >(NextSelected( pEntry ));
-    }
+        return false;
+    });
+
+    xMenu->set_active("onclick", nNodeType == EffectNodeType::ON_CLICK);
+    xMenu->set_active("withprev", nNodeType == EffectNodeType::WITH_PREVIOUS);
+    xMenu->set_active("afterprev", nNodeType == EffectNodeType::AFTER_PREVIOUS);
+    xMenu->set_sensitive("options", nEntries == 1);
+    xMenu->set_sensitive("timing", nEntries == 1);
 
-    mxMenu->CheckItem("onclick", nNodeType == EffectNodeType::ON_CLICK);
-    mxMenu->CheckItem("withprev", nNodeType == EffectNodeType::WITH_PREVIOUS);
-    mxMenu->CheckItem("afterprev", nNodeType == EffectNodeType::AFTER_PREVIOUS);
-    mxMenu->EnableItem(mxMenu->GetItemId("options"), nEntries == 1);
-    mxMenu->EnableItem(mxMenu->GetItemId("timing"), nEntries == 1);
+    OString sCommand = xMenu->popup_at_rect(mxTreeView.get(), ::tools::Rectangle(rCEvt.GetMousePosPixel(), Size(1,1)));
+    if (!sCommand.isEmpty())
+        ExecuteContextMenuAction(sCommand);
 
-    return mxMenu;
+    return true;
 }
 
-void CustomAnimationList::ExecuteContextMenuAction( sal_uInt16 nSelectedPopupEntry )
+void CustomAnimationList::ExecuteContextMenuAction(const OString& rIdent)
 {
-    mpController->onContextMenu(mxMenu->GetItemIdent(nSelectedPopupEntry));
+    mpController->onContextMenu(rIdent);
 }
 
 void CustomAnimationList::notify_change()
@@ -1319,34 +1185,6 @@ void CustomAnimationList::notify_change()
     mpController->onSelect();
 }
 
-void CustomAnimationList::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect)
-{
-    if( mbIgnorePaint )
-        return;
-
-    SvTreeListBox::Paint(rRenderContext, rRect);
-
-    // draw help text if list box is still empty
-    if( First() != nullptr )
-        return;
-
-    Color aOldColor(rRenderContext.GetTextColor());
-    rRenderContext.SetTextColor(rRenderContext.GetSettings().GetStyleSettings().GetDisableColor());
-    ::Point aOffset(rRenderContext.LogicToPixel(Point(6, 6), MapMode(MapUnit::MapAppFont)));
-
-    ::tools::Rectangle aRect(Point(0,0), GetOutputSizePixel());
-
-    aRect.AdjustLeft(aOffset.X() );
-    aRect.AdjustTop(aOffset.Y() );
-    aRect.AdjustRight( -(aOffset.X()) );
-    aRect.AdjustBottom( -(aOffset.Y()) );
-
-    rRenderContext.DrawText(aRect, SdResId(STR_CUSTOMANIMATION_LIST_HELPTEXT),
-                            DrawTextFlags::MultiLine | DrawTextFlags::WordBreak | DrawTextFlags::Center | DrawTextFlags::VCenter );
-
-    rRenderContext.SetTextColor(aOldColor);
-}
-
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/source/ui/animations/CustomAnimationList.hxx b/sd/source/ui/animations/CustomAnimationList.hxx
index 9b738188c962..398793840187 100644
--- a/sd/source/ui/animations/CustomAnimationList.hxx
+++ b/sd/source/ui/animations/CustomAnimationList.hxx
@@ -24,7 +24,8 @@
 
 #include <memory>
 
-#include <vcl/treelistbox.hxx>
+#include <vcl/transfer.hxx>
+#include <vcl/weld.hxx>
 #include <CustomAnimationEffect.hxx>
 
 namespace com { namespace sun { namespace star { namespace drawing { class XShape; } } } }
@@ -45,15 +46,31 @@ public:
     virtual ~ICustomAnimationListController() {}
 };
 
-class CustomAnimationList : public SvTreeListBox, public ISequenceListener
+class CustomAnimationList;
+class CustomAnimationListEntryItem;
+
+class CustomAnimationListDropTarget : public DropTargetHelper
+{
+private:
+    CustomAnimationList& m_rTreeView;
+
+    virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt ) override;
+    virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt ) override;
+
+public:
+    CustomAnimationListDropTarget(CustomAnimationList& rTreeView);
+};
+
+class CustomAnimationList : public ISequenceListener
 {
     friend class CustomAnimationListEntryItem;
     friend struct stl_append_effect_func;
 
 public:
-    explicit CustomAnimationList( vcl::Window* pParent );
-    virtual ~CustomAnimationList() override;
-    virtual void dispose() override;
+    explicit CustomAnimationList(std::unique_ptr<weld::TreeView> xTreeView,
+                                 std::unique_ptr<weld::Label> xLabel,
+                                 std::unique_ptr<weld::Widget> xScrolledWindow);
+    virtual ~CustomAnimationList();
 
     // methods
 
@@ -71,22 +88,10 @@ public:
     // events
     void onSelectionChanged(const css::uno::Any& rSelection);
 
-    // overrides
-    virtual void    SelectHdl() override;
-    virtual void    DeselectHdl() override;
-    virtual bool    DoubleClickHdl() override;
-
-    virtual void    Paint( vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect ) override;
-
-    virtual VclPtr<PopupMenu> CreateContextMenu() override;
-    virtual void    ExecuteContextMenuAction( sal_uInt16 nSelectedPopupEntry ) override;
-
-    virtual void KeyInput( const KeyEvent& rKEvt ) override;
+    void Select();
 
     virtual void notify_change() override;
 
-    virtual bool Expand( SvTreeListEntry* pParent ) override;
-    virtual bool Collapse( SvTreeListEntry* pParent ) override;
     bool isExpanded( const CustomAnimationEffectPtr& pEffect ) const;
     bool isVisible( const CustomAnimationEffectPtr& pEffect ) const;
 
@@ -98,23 +103,41 @@ public:
         mpController = pController;
     };
 
+    sal_Int8     AcceptDrop(const AcceptDropEvent& rEvt);
+    sal_Int8     ExecuteDrop(const ExecuteDropEvent& rEvt);
 
-protected:
-    // drag & drop
-    virtual void         StartDrag( sal_Int8 nAction, const Point& rPosPixel ) override;
-    virtual DragDropMode NotifyStartDrag( TransferDataContainer& rData, SvTreeListEntry* pEntry ) override;
-    virtual sal_Int8     AcceptDrop( const AcceptDropEvent& rEvt ) override;
-            void         ReparentChildrenDuringDrag();
-            void         ReorderEffectsInUiDuringDragOver( SvTreeListEntry* pOverEntry);
-    virtual sal_Int8     ExecuteDrop( const ExecuteDropEvent& rEvt ) override;
-    virtual void         DragFinished( sal_Int8 nDropAction ) override;
+    void set_sensitive(bool bSensitive) { mxTreeView->set_sensitive(bSensitive); }
+    int get_height_rows(int nRows) { return mxTreeView->get_height_rows(nRows); }
+    int get_approximate_digit_width() const { return mxTreeView->get_approximate_digit_width(); }
+    void set_size_request(int nWidth, int nHeight) { mxTreeView->set_size_request(nWidth, nHeight); }
+    void unselect_all() { mxTreeView->unselect_all(); }
+    weld::TreeView& get_widget() { return *mxTreeView; }
+
+    DECL_LINK(KeyInputHdl, const KeyEvent&, bool);
+    DECL_LINK(ExpandHdl, const weld::TreeIter&, bool);
+    DECL_LINK(PostExpandHdl, void*, void);
+    DECL_LINK(CollapseHdl, const weld::TreeIter&, bool);
+    DECL_LINK(PostCollapseHdl, void*, void);
 
 private:
-    std::unique_ptr<VclBuilder> mxBuilder;
-    VclPtr<PopupMenu> mxMenu;
+    std::unique_ptr<weld::TreeView> mxTreeView;
+    CustomAnimationListDropTarget maDropTargetHelper;
+    std::unique_ptr<weld::Label> mxEmptyLabel;
+    std::unique_ptr<weld::Widget> mxEmptyLabelParent;
+    std::vector<std::unique_ptr<CustomAnimationListEntryItem>> mxEntries;
+    std::vector<std::unique_ptr<weld::TreeIter>> lastSelectedEntries;
 
     bool    mbIgnorePaint;
 
+    DECL_LINK(SelectHdl, weld::TreeView&, void);
+    DECL_LINK(CommandHdl, const CommandEvent&, bool);
+    DECL_LINK(DoubleClickHdl, weld::TreeView&, bool);
+    DECL_LINK(DragBeginHdl, bool&, bool);
+    DECL_STATIC_LINK(CustomAnimationList, CustomRenderHdl, weld::TreeView::render_args, void);
+    DECL_STATIC_LINK(CustomAnimationList, CustomGetSizeHdl, weld::TreeView::get_size_args, Size);
+
+    void ExecuteContextMenuAction(const OString& rSelectedPopupEntry);
+
     /** appends the given effect to the list*/
     void append( CustomAnimationEffectPtr pEffect );
 
@@ -124,12 +147,15 @@ private:
 
     css::uno::Reference< css::drawing::XShape > mxLastTargetShape;
     sal_Int32 mnLastGroupId;
-    SvTreeListEntry* mpLastParentEntry;
+    ImplSVEvent* mnPostExpandEvent;
+    ImplSVEvent* mnPostCollapseEvent;
+
+    std::unique_ptr<weld::TreeIter> mxLastParentEntry;
 
     // drag & drop
-    SvTreeListEntry* mpDndEffectDragging;
-    SvTreeListEntry* mpDndEffectInsertBefore;
-    std::vector< SvTreeListEntry* > mDndEffectsSelected;
+    std::unique_ptr<weld::TreeIter> mxDndEffectDragging;
+    std::unique_ptr<weld::TreeIter> mxDndEffectInsertBefore;
+    std::vector<std::unique_ptr<weld::TreeIter>> mDndEffectsSelected;
 };
 
 OUString getPropertyName( sal_Int32 nPropertyType );
diff --git a/sd/source/ui/animations/CustomAnimationPane.cxx b/sd/source/ui/animations/CustomAnimationPane.cxx
index 5b4ff943ec2e..15dde73e15ab 100644
--- a/sd/source/ui/animations/CustomAnimationPane.cxx
+++ b/sd/source/ui/animations/CustomAnimationPane.cxx
@@ -46,10 +46,6 @@
 #include "motionpathtag.hxx"
 #include <CustomAnimationPreset.hxx>
 #include <createcustomanimationpanel.hxx>
-#include <vcl/lstbox.hxx>
-#include <vcl/fixed.hxx>
-
-#include <vcl/button.hxx>
 
 #include <comphelper/lok.hxx>
 #include <comphelper/sequence.hxx>
@@ -123,81 +119,68 @@ void fillRepeatComboBox(weld::ComboBox& rBox)
 
 CustomAnimationPane::CustomAnimationPane( Window* pParent, ViewShellBase& rBase,
                                           const css::uno::Reference<css::frame::XFrame>& rxFrame )
-:   PanelLayout( pParent, "CustomAnimationsPanel", "modules/simpress/ui/customanimationspanel.ui", rxFrame ),
-    mrBase( rBase ),
-    mnPropertyType( nPropertyTypeNone ),
-    mnCurvePathPos( LISTBOX_ENTRY_NOTFOUND ),
-    mnPolygonPathPos( LISTBOX_ENTRY_NOTFOUND ),
-    mnFreeformPathPos( LISTBOX_ENTRY_NOTFOUND ),
-    maLateInitTimer()
+    : PanelLayout(pParent, "CustomAnimationsPanel", "modules/simpress/ui/customanimationspanel.ui", rxFrame, true)
+    , mrBase(rBase)
+    // load resources
+    , mxFTAnimation(m_xBuilder->weld_label("effectlabel"))
+    , mxCustomAnimationList(new CustomAnimationList(m_xBuilder->weld_tree_view("custom_animation_list"),
+                                                    m_xBuilder->weld_label("custom_animation_label"),
+                                                    m_xBuilder->weld_widget("custom_animation_label_parent")))
+    , mxPBAddEffect(m_xBuilder->weld_button("add_effect"))
+    , mxPBRemoveEffect(m_xBuilder->weld_button("remove_effect"))
+    , mxPBMoveUp(m_xBuilder->weld_button("move_up"))
+    , mxPBMoveDown(m_xBuilder->weld_button("move_down"))
+    , mxFTCategory(m_xBuilder->weld_label("categorylabel"))
+    , mxLBCategory(m_xBuilder->weld_combo_box("categorylb"))
+    , mxFTEffect(m_xBuilder->weld_label("effect_label"))
+    , mxLBAnimation(m_xBuilder->weld_tree_view("effect_list"))
+    , mxFTStart(m_xBuilder->weld_label("start_effect"))
+    , mxLBStart(m_xBuilder->weld_combo_box("start_effect_list"))
+    , mxFTProperty(m_xBuilder->weld_label("effect_property"))
+    , mxPlaceholderBox(m_xBuilder->weld_container("placeholder"))
+    , mxPBPropertyMore(m_xBuilder->weld_button("more_properties"))
+    , mxFTDuration(m_xBuilder->weld_label("effect_duration"))
+    , mxCBXDuration(m_xBuilder->weld_metric_spin_button("anim_duration", FieldUnit::SECOND))
+    , mxFTStartDelay(m_xBuilder->weld_label("delay_label"))
+    , mxMFStartDelay(m_xBuilder->weld_metric_spin_button("delay_value", FieldUnit::SECOND))
+    , mxCBAutoPreview(m_xBuilder->weld_check_button("auto_preview"))
+    , mxPBPlay(m_xBuilder->weld_button("play"))
+    , mnLastSelectedAnimation(-1)
+    , mnPropertyType(nPropertyTypeNone)
+    , mnCurvePathPos(-1)
+    , mnPolygonPathPos(-1)
+    , mnFreeformPathPos(-1)
+    , maLateInitTimer()
 {
     initialize();
 }
 
 void CustomAnimationPane::initialize()
 {
-    // load resources
-    get(mpPBAddEffect, "add_effect");
-    get(mpPBRemoveEffect, "remove_effect");
-
-    get(mpFTEffect, "effect_label");
-
-    get(mpFTStart, "start_effect");
-    get(mpLBStart, "start_effect_list");
-    get(mpFTProperty, "effect_property");
-    get(mpPlaceholderBox, "placeholder");
-    get(mpLBProperty, "effect_property_list");
-    get(mpPBPropertyMore, "more_properties");
-
-    get(mpFTDuration, "effect_duration");
-    get(mpCBXDuration, "anim_duration");
-    get(mpFTCategory, "categorylabel");
-    get(mpLBCategory, "categorylb");
-    get(mpFTAnimation, "effectlabel");
-    get(mpLBAnimation, "effect_list");
-    get(mpFTStartDelay, "delay_label");
-    get(mpMFStartDelay, "delay_value");
-
-    mpLBAnimation->SetSelectHdl(LINK(this, CustomAnimationPane, AnimationSelectHdl));
-    get(mpCustomAnimationList, "custom_animation_list");
-    mpCustomAnimationList->setController( dynamic_cast<ICustomAnimationListController*> ( this ) );
-    mpCustomAnimationList->set_width_request(mpCustomAnimationList->approximate_digit_width() * 15);
-    mpCustomAnimationList->set_height_request(mpCustomAnimationList->GetTextHeight() * 8);
-
-    mpLBAnimation->set_width_request(mpLBAnimation->approximate_digit_width() * 15);
-    mpLBAnimation->set_height_request(mpLBAnimation->GetTextHeight() * 8);
-
-    get(mpPBMoveUp, "move_up");
-    get(mpPBMoveDown, "move_down");
-    get(mpPBPlay, "play");
-    get(mpCBAutoPreview,"auto_preview");
-
-    maStrProperty = mpFTProperty->GetText();
-
-    //fillDurationMetricComboBox
-    mpCBXDuration->InsertValue(50, FieldUnit::CUSTOM);
-    mpCBXDuration->InsertValue(100, FieldUnit::CUSTOM);
-    mpCBXDuration->InsertValue(200, FieldUnit::CUSTOM);
-    mpCBXDuration->InsertValue(300, FieldUnit::CUSTOM);
-    mpCBXDuration->InsertValue(500, FieldUnit::CUSTOM);
-    mpCBXDuration->AdaptDropDownLineCountToMaximum();
-
-
-    mpPBAddEffect->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
-    mpPBRemoveEffect->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
-    mpLBStart->SetSelectHdl( LINK( this, CustomAnimationPane, implControlListBoxHdl ) );
-    mpCBXDuration->SetModifyHdl(LINK( this, CustomAnimationPane, DurationModifiedHdl));
-    mpPBPropertyMore->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
-    mpPBMoveUp->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
-    mpPBMoveDown->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
-    mpPBPlay->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
-    mpCBAutoPreview->SetClickHdl( LINK( this, CustomAnimationPane, implClickHdl ) );
-    mpLBCategory->SetSelectHdl( LINK(this, CustomAnimationPane, UpdateAnimationLB) );
-    mpMFStartDelay->SetModifyHdl( LINK(this, CustomAnimationPane, DelayModifiedHdl) );
-    mpMFStartDelay->SetLoseFocusHdl(LINK( this, CustomAnimationPane, DelayLoseFocusHdl));
-
-
-    maStrModify = mpFTEffect->GetText();
+    mxLBAnimation->connect_changed(LINK(this, CustomAnimationPane, AnimationSelectHdl));
+    mxCustomAnimationList->setController( dynamic_cast<ICustomAnimationListController*> ( this ) );
+    mxCustomAnimationList->set_size_request(mxCustomAnimationList->get_approximate_digit_width() * 15,
+                                            mxCustomAnimationList->get_height_rows(8));
+
+    mxLBAnimation->set_size_request(mxLBAnimation->get_approximate_digit_width() * 15,
+                                    mxLBAnimation->get_height_rows(8));
+
+    maStrProperty = mxFTProperty->get_label();
+
+    mxPBAddEffect->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
+    mxPBRemoveEffect->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
+    mxLBStart->connect_changed( LINK( this, CustomAnimationPane, implControlListBoxHdl ) );
+    mxCBXDuration->connect_value_changed(LINK( this, CustomAnimationPane, DurationModifiedHdl));
+    mxPBPropertyMore->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
+    mxPBMoveUp->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
+    mxPBMoveDown->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
+    mxPBPlay->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
+    mxCBAutoPreview->connect_clicked( LINK( this, CustomAnimationPane, implClickHdl ) );
+    mxLBCategory->connect_changed( LINK(this, CustomAnimationPane, UpdateAnimationLB) );
+    mxMFStartDelay->connect_value_changed( LINK(this, CustomAnimationPane, DelayModifiedHdl) );
+    mxMFStartDelay->connect_focus_out(LINK( this, CustomAnimationPane, DelayLoseFocusHdl));
+
+    maStrModify = mxFTEffect->get_label();
 
     // get current controller and initialize listeners
     try
@@ -237,28 +220,28 @@ void CustomAnimationPane::dispose()
     for (auto const& tag : aTags)
         tag->Dispose();
 
-    mpPBAddEffect.clear();
-    mpPBRemoveEffect.clear();
-    mpFTEffect.clear();
-    mpFTStart.clear();
-    mpLBStart.clear();
-    mpFTProperty.clear();
-    mpPlaceholderBox.clear();
-    mpLBProperty.clear();
-    mpPBPropertyMore.clear();
-    mpFTDuration.clear();
-    mpCBXDuration.clear();
-    mpFTStartDelay.clear();
-    mpMFStartDelay.clear();
-    mpCustomAnimationList.clear();
-    mpPBMoveUp.clear();
-    mpPBMoveDown.clear();
-    mpPBPlay.clear();
-    mpCBAutoPreview.clear();
-    mpFTCategory.clear();
-    mpLBCategory.clear();
-    mpFTAnimation.clear();
-    mpLBAnimation.clear();
+    mxPBAddEffect.reset();
+    mxPBRemoveEffect.reset();
+    mxFTEffect.reset();
+    mxFTStart.reset();
+    mxLBStart.reset();
+    mxLBSubControl.reset();
+    mxFTProperty.reset();
+    mxPlaceholderBox.reset();
+    mxPBPropertyMore.reset();
+    mxFTDuration.reset();
+    mxCBXDuration.reset();
+    mxFTStartDelay.reset();
+    mxMFStartDelay.reset();
+    mxCustomAnimationList.reset();
+    mxPBMoveUp.reset();
+    mxPBMoveDown.reset();
+    mxPBPlay.reset();
+    mxCBAutoPreview.reset();
+    mxFTCategory.reset();
+    mxLBCategory.reset();
+    mxFTAnimation.reset();
+    mxLBAnimation.reset();
 
     PanelLayout::dispose();
 }
@@ -284,8 +267,8 @@ void CustomAnimationPane::StateChanged( StateChangedType nStateChange )
 
 void CustomAnimationPane::KeyInput( const KeyEvent& rKEvt )
 {
-    if( mpCustomAnimationList )
-        mpCustomAnimationList->KeyInput( rKEvt );
+    if (mxCustomAnimationList)
+        mxCustomAnimationList->KeyInputHdl(rKEvt);
 }
 
 void CustomAnimationPane::addListener()
@@ -340,8 +323,8 @@ IMPL_LINK(CustomAnimationPane,EventMultiplexerListener,
             onChangeCurrentPage();
             break;
         case EventMultiplexerEventId::EndTextEdit:
-            if( mpMainSequence.get() && rEvent.mpUserData )
-                mpCustomAnimationList->update( mpMainSequence );
+            if (mpMainSequence.get() && rEvent.mpUserData)
+                mxCustomAnimationList->update( mpMainSequence );
             break;
         default: break;
     }
@@ -470,70 +453,74 @@ OUString getPropertyName( sal_Int32 nPropertyType )
 
 void CustomAnimationPane::updateControls()
 {
-    mpFTDuration->Enable( mxView.is() );
-    mpCBXDuration->Enable( mxView.is() );
-    mpCustomAnimationList->Enable( mxView.is() );
+    mxFTDuration->set_sensitive(mxView.is());
+    mxCBXDuration->set_sensitive(mxView.is());
+    mxCustomAnimationList->set_sensitive(mxView.is());
     if (comphelper::LibreOfficeKit::isActive())
     {
-        mpPBPlay->Hide();
-        mpCBAutoPreview->Check(false);
-        mpCBAutoPreview->Hide();
+        mxPBPlay->hide();
+        mxCBAutoPreview->set_active(false);
+        mxCBAutoPreview->hide();
     }
     else
     {
-        mpPBPlay->Enable( mxView.is() );
-        mpCBAutoPreview->Enable( mxView.is() );
-    }
-
-    if( !mxView.is() )
-    {
-        mpPBAddEffect->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();
-        mpFTStartDelay->Disable();
-        mpMFStartDelay->Disable();
-        mpLBAnimation->Clear();
-        mpCustomAnimationList->clear();
+        mxPBPlay->set_sensitive(mxView.is());
+        mxCBAutoPreview->set_sensitive(mxView.is());
+    }
+
+    if (!mxView.is())
+    {
+        mxPBAddEffect->set_sensitive(false);
+        mxPBRemoveEffect->set_sensitive(false);
+        mxFTStart->set_sensitive(false);
+        mxLBStart->set_sensitive(false);
+        mxPBPropertyMore->set_sensitive(false);
+        mxPlaceholderBox->set_sensitive(false);
+        mxFTProperty->set_sensitive(false);
+        mxFTCategory->set_sensitive(false);
+        mxLBCategory->set_sensitive(false);
+        mxFTAnimation->set_sensitive(false);
+        mxLBAnimation->set_sensitive(false);
+        mxFTStartDelay->set_sensitive(false);
+        mxMFStartDelay->set_sensitive(false);
+        mxLBAnimation->clear();
+        mnLastSelectedAnimation = -1;
+        mxCustomAnimationList->clear();
         return;
     }
 
     const int nSelectionCount = maListSelection.size();
 
-    mpPBAddEffect->Enable( maViewSelection.hasValue() );
-    mpPBRemoveEffect->Enable(nSelectionCount != 0);
+    mxPBAddEffect->set_sensitive( maViewSelection.hasValue() );
+    mxPBRemoveEffect->set_sensitive(nSelectionCount != 0);
     bool bIsSelected = (nSelectionCount == 1);
 
     if(bIsSelected)
     {
-        mpFTAnimation->Enable();
-        mpLBAnimation->Enable();
+        mxFTAnimation->set_sensitive(true);
+        mxLBAnimation->set_sensitive(true);
     }
     else
     {
-        mpFTAnimation->Disable();
-        mpLBAnimation->Disable();
-        mpLBAnimation->Clear();
+        mxFTAnimation->set_sensitive(false);
+        mxLBAnimation->set_sensitive(false);
+        mxLBAnimation->clear();
+        mnLastSelectedAnimation = -1;
     }
 
-    mpLBCategory->Enable(bIsSelected);
-    mpFTCategory->Enable(bIsSelected);
+    mxLBCategory->set_sensitive(bIsSelected);
+    mxFTCategory->set_sensitive(bIsSelected);
 
-    mpFTStart->Enable(nSelectionCount > 0);
-    mpLBStart->Enable(nSelectionCount > 0);
-    mpLBProperty->Enable(nSelectionCount > 0);
-    mpPBPropertyMore->Enable(nSelectionCount > 0);
-    mpFTStartDelay->Enable(nSelectionCount > 0);
-    mpMFStartDelay->Enable(nSelectionCount > 0);
+    mxFTStart->set_sensitive(nSelectionCount > 0);
+    mxLBStart->set_sensitive(nSelectionCount > 0);
+    mxPlaceholderBox->set_sensitive(nSelectionCount > 0);
+    mxPBPropertyMore->set_sensitive(nSelectionCount > 0);
+    mxFTStartDelay->set_sensitive(nSelectionCount > 0);
+    mxMFStartDelay->set_sensitive(nSelectionCount > 0);
 
-    mpFTProperty->SetText( maStrProperty );
+    mxFTProperty->set_label(maStrProperty);
+
+    sal_Int32 nOldPropertyType = mnPropertyType;
 
     mnPropertyType = nPropertyTypeNone;
 
@@ -548,59 +535,50 @@ void CustomAnimationPane::updateControls()
         if( !aUIName.isEmpty() )
         {
             aTemp += " " + aUIName;
-            mpFTEffect->SetText( aTemp );
+            mxFTEffect->set_label( aTemp );
         }
 
+        Any aValue;
         CustomAnimationPresetPtr pDescriptor = CustomAnimationPresets::getCustomAnimationPresets().getEffectDescriptor( pEffect->getPresetId() );
-        if( pDescriptor.get() )
+        if (pDescriptor.get())
         {
-            PropertySubControl* pSubControl = nullptr;
-
-            Any aValue;
-
             std::vector<OUString> aProperties( pDescriptor->getProperties() );
             if( !aProperties.empty() )
             {
                 mnPropertyType = getPropertyType( aProperties.front() );
 
-                mpFTProperty->SetText( getPropertyName( mnPropertyType )  );
+                mxFTProperty->set_label( getPropertyName( mnPropertyType )  );
 
                 aValue = getProperty1Value( mnPropertyType, pEffect );
             }
+        }
 
-            if( aValue.hasValue() )
-            {
-                pSubControl = mpLBProperty->getSubControl();
-                if( !pSubControl || (pSubControl->getControlType() != mnPropertyType) )
-                {
-                    auto pNewControl = PropertySubControl::create( mnPropertyType, mpPlaceholderBox, aValue, pEffect->getPresetId(), LINK( this, CustomAnimationPane, implPropertyHdl ) );
-                    pSubControl = pNewControl.get();
-                    mpLBProperty->setSubControl( std::move(pNewControl) );
-                }
-                else
-                {
-                    pSubControl->setValue( aValue, pEffect->getPresetId() );
-                }
-            }
-            else
-            {
-                mpLBProperty->setSubControl( nullptr );
-            }
+        sal_Int32 nNewPropertyType = mnPropertyType;
+        // if there is no value, then the control will be disabled, just show a disabled Direction box in that
+        // case to have something to fill the space
+        if (!aValue.hasValue())
+            nNewPropertyType = nPropertyTypeDirection;
 
-            bool bEnable = (pSubControl != nullptr) && (pSubControl->getControl()->IsEnabled());
-            mpLBProperty->Enable( bEnable );
-            mpFTProperty->Enable( bEnable );
+        if (!mxLBSubControl || nOldPropertyType != nNewPropertyType)
+        {
+            mxLBSubControl = SdPropertySubControl::create(nNewPropertyType, mxFTProperty.get(), mxPlaceholderBox.get(), GetFrameWeld(), aValue, pEffect->getPresetId(), LINK(this, CustomAnimationPane, implPropertyHdl));
         }
         else
         {
-            mpLBProperty->setSubControl( nullptr );
-            mpFTProperty->Enable( false );
-            mpLBProperty->Enable( false );
-            mpPBPropertyMore->Enable( false );
-            mpFTStartDelay->Enable( false );
-            mpMFStartDelay->Enable( false );
+            mxLBSubControl->setValue(aValue, pEffect->getPresetId());
+        }
+
+        bool bEnable = aValue.hasValue();
+        mxPlaceholderBox->set_sensitive( bEnable );
+        mxFTProperty->set_sensitive( bEnable );
+
+        if (!pDescriptor.get())
+        {
+            mxPBPropertyMore->set_sensitive( false );
+            mxFTStartDelay->set_sensitive( false );
+            mxMFStartDelay->set_sensitive( false );
         }
-        sal_uInt32 nCategoryPos = LISTBOX_ENTRY_NOTFOUND;
+        sal_Int32 nCategoryPos = -1;
         switch(pEffect->getPresetClass())
         {
             case EffectPresetClass::ENTRANCE: nCategoryPos = 0; break;
@@ -619,19 +597,22 @@ void CustomAnimationPane::updateControls()
             default:
             break;
         }
-        mpLBCategory->SelectEntryPos(nCategoryPos);
+        mxLBCategory->set_active(nCategoryPos);
+
         fillAnimationLB( pEffect->hasText() );
+
         OUString rsPresetId = pEffect->getPresetId();
-        sal_Int32 nAnimationPos = mpLBAnimation->GetEntryCount();
+        sal_Int32 nAnimationPos = mxLBAnimation->n_children();
         while( nAnimationPos-- )
         {
-            void* pEntryData = mpLBAnimation->GetEntryData( nAnimationPos );
-            if( pEntryData )
+            auto nEntryData = mxLBAnimation->get_id(nAnimationPos).toInt64();
+            if (nEntryData)
             {
-                CustomAnimationPresetPtr& pPtr = *static_cast< CustomAnimationPresetPtr* >(pEntryData);
+                CustomAnimationPresetPtr& pPtr = *reinterpret_cast<CustomAnimationPresetPtr*>(nEntryData);
                 if( pPtr.get() && pPtr->getPresetId() == rsPresetId )
                 {
-                    mpLBAnimation->SelectEntryPos( nAnimationPos );
+                    mxLBAnimation->select( nAnimationPos );
+                    mnLastSelectedAnimation = nAnimationPos;
                     break;
                 }
             }
@@ -641,11 +622,20 @@ void CustomAnimationPane::updateControls()
         if (nAnimationPos < 0 && nCategoryPos == 3)
         {
             if (rsPresetId == "libo-motionpath-curve")
-                mpLBAnimation->SelectEntryPos(mnCurvePathPos);
+            {
+                mxLBAnimation->select(mnCurvePathPos);
+                mnLastSelectedAnimation = mnCurvePathPos;
+            }
             else if (rsPresetId == "libo-motionpath-polygon")
-                mpLBAnimation->SelectEntryPos(mnPolygonPathPos);
+            {
+                mxLBAnimation->select(mnPolygonPathPos);
+                mnLastSelectedAnimation = mnPolygonPathPos;
+            }
             else if (rsPresetId == "libo-motionpath-freeform-line")
-                mpLBAnimation->SelectEntryPos(mnFreeformPathPos);
+            {
+                mxLBAnimation->select(mnFreeformPathPos);
+                mnLastSelectedAnimation = mnFreeformPathPos;
+            }
         }
 
         sal_uInt16 nPos = 0xffff;
@@ -658,38 +648,39 @@ void CustomAnimationPane::updateControls()
         case EffectNodeType::AFTER_PREVIOUS:    nPos = 2; break;
         }
 
-        mpLBStart->SelectEntryPos( nPos );
+        mxLBStart->set_active( nPos );
 
         double fDuration = pEffect->getDuration();
         const bool bHasSpeed = fDuration > 0.001;
 
-        mpFTDuration->Enable(bHasSpeed);
-        mpCBXDuration->Enable(bHasSpeed);
+        mxFTDuration->set_sensitive(bHasSpeed);
+        mxCBXDuration->set_sensitive(bHasSpeed);
 
         if( bHasSpeed )
         {
-            mpCBXDuration->SetValue( fDuration*100.0 );
+            mxCBXDuration->set_value(fDuration*100.0, FieldUnit::NONE);
         }
 
-        mpPBPropertyMore->Enable();
+        mxPBPropertyMore->set_sensitive(true);
 
-        mpFTStartDelay->Enable();
-        mpMFStartDelay->Enable();
+        mxFTStartDelay->set_sensitive(true);
+        mxMFStartDelay->set_sensitive(true);
         double fBegin = pEffect->getBegin();
-        mpMFStartDelay->SetValue(fBegin*10.0);
+        mxMFStartDelay->set_value(fBegin*10.0, FieldUnit::NONE);
     }
     else
     {
-        mpLBProperty->setSubControl( nullptr );
-        mpFTProperty->Enable( false );
-        mpLBProperty->Enable( false );
-        mpFTStartDelay->Enable( false );
-        mpMFStartDelay->Enable( false );
-        mpPBPropertyMore->Enable( false );
-        mpFTDuration->Enable(false);
-        mpCBXDuration->Enable(false);
-        mpCBXDuration->SetNoSelection();
-        mpFTEffect->SetText( maStrModify );
+        // use an empty direction box to fill the space

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list