diff options
author | Caolán McNamara <caolanm@redhat.com> | 2020-03-24 11:44:16 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2020-04-06 21:24:40 +0200 |
commit | 21e8ce9ab9a522d25e95773af59b7ccccaee4e54 (patch) | |
tree | 75e0730830aade810b84ccb3f51ba511faf03513 /sd/source/ui/animations | |
parent | 01546c005eaf6bce8fe4066dbec92c5655190a2a (diff) |
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@redhat.com>
Diffstat (limited to 'sd/source/ui/animations')
-rw-r--r-- | sd/source/ui/animations/CategoryListBox.cxx | 93 | ||||
-rw-r--r-- | sd/source/ui/animations/CategoryListBox.hxx | 45 | ||||
-rw-r--r-- | sd/source/ui/animations/CustomAnimationDialog.cxx | 9 | ||||
-rw-r--r-- | sd/source/ui/animations/CustomAnimationDialog.hxx | 8 | ||||
-rw-r--r-- | sd/source/ui/animations/CustomAnimationList.cxx | 1116 | ||||
-rw-r--r-- | sd/source/ui/animations/CustomAnimationList.hxx | 92 | ||||
-rw-r--r-- | sd/source/ui/animations/CustomAnimationPane.cxx | 622 | ||||
-rw-r--r-- | sd/source/ui/animations/CustomAnimationPane.hxx | 67 |
8 files changed, 899 insertions, 1153 deletions
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 + mxLBSubControl = SdPropertySubControl::create(nPropertyTypeDirection, mxFTProperty.get(), mxPlaceholderBox.get(), GetFrameWeld(), uno::Any(), OUString(), LINK(this, CustomAnimationPane, implPropertyHdl)); + mxPlaceholderBox->set_sensitive(false); + mxFTProperty->set_sensitive(false); + mxFTStartDelay->set_sensitive(false); + mxMFStartDelay->set_sensitive(false); + mxPBPropertyMore->set_sensitive(false); + mxFTDuration->set_sensitive(false); + mxCBXDuration->set_sensitive(false); + mxCBXDuration->set_text(OUString()); + mxFTEffect->set_label(maStrModify); } bool bEnableUp = true; @@ -715,7 +706,7 @@ void CustomAnimationPane::updateControls() { ++aIter; } - while( (aIter != mpMainSequence->getEnd()) && !(mpCustomAnimationList->isExpanded(*aIter) ) ); + while( (aIter != mpMainSequence->getEnd()) && !(mxCustomAnimationList->isExpanded(*aIter) ) ); if( aIter == mpMainSequence->getEnd() ) bEnableDown = false; @@ -748,11 +739,11 @@ void CustomAnimationPane::updateControls() } } - mpPBMoveUp->Enable(mxView.is() && bEnableUp); - mpPBMoveDown->Enable(mxView.is() && bEnableDown); + mxPBMoveUp->set_sensitive(mxView.is() && bEnableUp); + mxPBMoveDown->set_sensitive(mxView.is() && bEnableDown); SdOptions* pOptions = SD_MOD()->GetSdOptions(DocumentType::Impress); - mpCBAutoPreview->Check( pOptions->IsPreviewChangedEffects() ); + mxCBAutoPreview->set_active(pOptions->IsPreviewChangedEffects()); updateMotionPathTags(); } @@ -845,7 +836,7 @@ void CustomAnimationPane::onSelectionChanged() { Reference< XSelectionSupplier > xSel( mxView, UNO_QUERY_THROW ); maViewSelection = xSel->getSelection(); - mpCustomAnimationList->onSelectionChanged( maViewSelection ); + mxCustomAnimationList->onSelectionChanged( maViewSelection ); updateControls(); } catch( Exception& ) @@ -889,12 +880,6 @@ void CustomAnimationPane::UpdateLook() ::sfx2::sidebar::Theme::GetWallpaper( ::sfx2::sidebar::Theme::Paint_PanelBackground)); SetBackground(aBackground); - if (mpFTStart != nullptr) - mpFTStart->SetBackground(aBackground); - if (mpFTProperty != nullptr) - mpFTProperty->SetBackground(aBackground); - if (mpFTDuration != nullptr) - mpFTDuration->SetBackground(aBackground); } static void addValue( const std::unique_ptr<STLPropertySet>& pSet, sal_Int32 nHandle, const Any& rValue ) @@ -1663,7 +1648,7 @@ void CustomAnimationPane::onChangeCurrentPage() if( pPage ) { mpMainSequence = pPage->getMainSequence(); - mpCustomAnimationList->update( mpMainSequence ); + mxCustomAnimationList->update( mpMainSequence ); } updateControls(); } @@ -1797,44 +1782,44 @@ void CustomAnimationPane::onAdd() } CustomAnimationPresetPtr pDescriptor; - mpFTCategory->Enable(); - mpFTAnimation->Enable(); + mxFTCategory->set_sensitive(true); + mxFTAnimation->set_sensitive(true); bool bCategoryReset = false; - if (!mpLBCategory->IsEnabled() || - mpLBCategory->GetSelectedEntryPos() == LISTBOX_ENTRY_NOTFOUND) + if (!mxLBCategory->get_sensitive() || mxLBCategory->get_active() == -1) { - mpLBCategory->Enable(); - mpLBCategory->SelectEntryPos(0); + mxLBCategory->set_sensitive(true); + mxLBCategory->set_active(0); bCategoryReset = true; } - if (bCategoryReset || !mpLBAnimation->IsEnabled() || - mpLBAnimation->GetSelectedEntryPos() == LISTBOX_ENTRY_NOTFOUND) + if (bCategoryReset || !mxLBAnimation->get_sensitive() || + mxLBAnimation->get_selected_index() == -1) { - mpLBAnimation->Enable(); + mxLBAnimation->set_sensitive(true); - sal_uInt32 nFirstEffect = fillAnimationLB( bHasText ); - if(nFirstEffect == LISTBOX_ENTRY_NOTFOUND) + sal_Int32 nFirstEffect = fillAnimationLB(bHasText); + if (nFirstEffect == -1) return; - mpLBAnimation->SelectEntryPos(nFirstEffect); + mxLBAnimation->select(nFirstEffect); + mnLastSelectedAnimation = nFirstEffect; } - void* pEntryData = mpLBAnimation->GetSelectedEntryData(); - if( pEntryData ) - pDescriptor = *static_cast< CustomAnimationPresetPtr* >( pEntryData ); + auto nEntryData = mxLBAnimation->get_selected_id().toInt64(); + if (nEntryData) + pDescriptor = *reinterpret_cast<CustomAnimationPresetPtr*>(nEntryData); const double fDuration = pDescriptor->getDuration(); - mpCBXDuration->SetValue( fDuration*100.0 ); + mxCBXDuration->set_value(fDuration*100.0, FieldUnit::NONE); bool bHasSpeed = pDescriptor->getDuration() > 0.001; - mpCBXDuration->Enable( bHasSpeed ); - mpFTDuration->Enable( bHasSpeed ); + mxCBXDuration->set_sensitive( bHasSpeed ); + mxFTDuration->set_sensitive( bHasSpeed ); if( pDescriptor.get() ) { - mpCustomAnimationList->SelectAll( false ); + mxCustomAnimationList->unselect_all(); // gather shapes from the selection bool bFirst = true; @@ -1858,7 +1843,7 @@ void CustomAnimationPane::onAdd() pCreated->setNodeType( EffectNodeType::WITH_PREVIOUS ); if( pCreated.get() ) - mpCustomAnimationList->select( pCreated ); + mxCustomAnimationList->select( pCreated ); } } @@ -1902,11 +1887,8 @@ void CustomAnimationPane::remove( CustomAnimationEffectPtr const & pEffect ) void CustomAnimationPane::onChangeStart() { - if( mpLBStart->GetSelectedEntryCount() != 1 ) - return; - sal_Int16 nNodeType; - switch( mpLBStart->GetSelectedEntryPos() ) + switch( mxLBStart->get_active() ) { case 0: nNodeType = EffectNodeType::ON_CLICK; break; case 1: nNodeType = EffectNodeType::WITH_PREVIOUS; break; @@ -1971,10 +1953,9 @@ double CustomAnimationPane::getDuration() const { double fDuration = 0; - if(!(mpCBXDuration->GetText()).isEmpty()) - { - fDuration = static_cast<double>(mpCBXDuration->GetValue())/100.0; - } + if (!mxCBXDuration->get_text().isEmpty()) + fDuration = mxCBXDuration->get_value(FieldUnit::NONE) / 100.0; + return fDuration; } @@ -1982,10 +1963,10 @@ PathKind CustomAnimationPane::getCreatePathKind() const { PathKind eKind = PathKind::NONE; - if( ( mpLBAnimation->GetSelectedEntryCount() == 1 ) && - ( mpLBCategory->GetSelectedEntryPos() == gnMotionPathPos ) ) + if (mxLBAnimation->count_selected_rows() == 1 && + mxLBCategory->get_active() == gnMotionPathPos) { - const sal_Int32 nPos = mpLBAnimation->GetSelectedEntryPos(); + const sal_Int32 nPos = mxLBAnimation->get_selected_index(); if( nPos == mnCurvePathPos ) { eKind = PathKind::CURVE; @@ -2039,14 +2020,14 @@ void CustomAnimationPane::createPath( PathKind eKind, std::vector< Any >& rTarge /// this link is called when the property box is modified by the user IMPL_LINK_NOARG(CustomAnimationPane, implPropertyHdl, LinkParamNone*, void) { - if( !mpLBProperty->getSubControl() ) + if (!mxLBSubControl) return; addUndo(); MainSequenceRebuildGuard aGuard( mpMainSequence ); - const Any aValue( mpLBProperty->getSubControl()->getValue() ); + const Any aValue(mxLBSubControl->getValue()); bool bNeedUpdate = false; @@ -2067,14 +2048,14 @@ IMPL_LINK_NOARG(CustomAnimationPane, implPropertyHdl, LinkParamNone*, void) onPreview( false ); } -IMPL_LINK_NOARG(CustomAnimationPane, DelayModifiedHdl, Edit&, void) +IMPL_LINK_NOARG(CustomAnimationPane, DelayModifiedHdl, weld::MetricSpinButton&, void) { addUndo(); } -IMPL_LINK_NOARG(CustomAnimationPane, DelayLoseFocusHdl, Control&, void) +IMPL_LINK_NOARG(CustomAnimationPane, DelayLoseFocusHdl, weld::Widget&, void) { - double fBegin = mpMFStartDelay->GetValue(); + double fBegin = mxMFStartDelay->get_value(FieldUnit::NONE); //sequence rebuild only when the control loses focus MainSequenceRebuildGuard aGuard( mpMainSequence ); @@ -2090,19 +2071,28 @@ IMPL_LINK_NOARG(CustomAnimationPane, DelayLoseFocusHdl, Control&, void) mrBase.GetDocShell()->SetModified(); } -IMPL_LINK_NOARG(CustomAnimationPane, AnimationSelectHdl, ListBox&, void) +IMPL_LINK_NOARG(CustomAnimationPane, AnimationSelectHdl, weld::TreeView&, void) { + int nSelected = mxLBAnimation->get_selected_index(); + + // tdf#99137, the selected entry may also be a subcategory title, so not an effect + // just skip it and move to the next one in this case + if (mxLBAnimation->get_text_emphasis(nSelected, 0)) + { + if (nSelected == 0 || nSelected > mnLastSelectedAnimation) + mxLBAnimation->select(++nSelected); + else + mxLBAnimation->select(--nSelected); + } + + mnLastSelectedAnimation = nSelected; + if( maListSelection.size() != 1 ) return; - CustomAnimationPresetPtr* pPreset = static_cast< CustomAnimationPresetPtr* >(mpLBAnimation->GetSelectedEntryData()); + CustomAnimationPresetPtr* pPreset = reinterpret_cast<CustomAnimationPresetPtr*>(mxLBAnimation->get_id(nSelected).toInt64()); PathKind ePathKind = getCreatePathKind(); - // tdf#99137, the selected entry may also be a subcategory title, so not an effect - // just leave in this case - if ( !pPreset && ( ePathKind == PathKind::NONE ) ) - return; - if ( ePathKind != PathKind::NONE ) { std::vector< Any > aTargets; @@ -2153,30 +2143,41 @@ IMPL_LINK_NOARG(CustomAnimationPane, AnimationSelectHdl, ListBox&, void) onPreview(false); } -IMPL_LINK_NOARG(CustomAnimationPane, UpdateAnimationLB, ListBox&, void) +IMPL_LINK_NOARG(CustomAnimationPane, UpdateAnimationLB, weld::ComboBox&, void) { //FIXME: first effect only? what if there is more? CustomAnimationEffectPtr pEffect = maListSelection.front(); fillAnimationLB( pEffect->hasText() ); } -IMPL_LINK_NOARG(CustomAnimationPane, DurationModifiedHdl, Edit&, void) +IMPL_LINK_NOARG(CustomAnimationPane, DurationModifiedHdl, weld::MetricSpinButton&, void) { - if(!(mpCBXDuration->GetText()).isEmpty() ) + if (!mxCBXDuration->get_text().isEmpty()) { - double duration_value = static_cast<double>(mpCBXDuration->GetValue()); + double duration_value = static_cast<double>(mxCBXDuration->get_value(FieldUnit::NONE)); if(duration_value <= 0.0) { - mpCBXDuration->SetValue(1); + mxCBXDuration->set_value(1, FieldUnit::NONE); } onChangeSpeed(); } } -sal_uInt32 CustomAnimationPane::fillAnimationLB( bool bHasText ) +namespace +{ + void InsertCategory(weld::TreeView& rLBAnimation, const OUString& rMotionPathLabel) + { + int nRow = rLBAnimation.n_children(); + rLBAnimation.append_text(rMotionPathLabel); + rLBAnimation.set_text_emphasis(nRow, true, 0); + rLBAnimation.set_text_align(nRow, 0.5, 0); + } +} + +sal_Int32 CustomAnimationPane::fillAnimationLB( bool bHasText ) { PresetCategoryList rCategoryList; - sal_uInt16 nPosition = mpLBCategory->GetSelectedEntryPos(); + sal_uInt16 nPosition = mxLBCategory->get_active(); const CustomAnimationPresets& rPresets (CustomAnimationPresets::getCustomAnimationPresets()); switch(nPosition) { @@ -2187,24 +2188,37 @@ sal_uInt32 CustomAnimationPane::fillAnimationLB( bool bHasText ) case 4:rCategoryList = rPresets.getMiscPresets();break; } - sal_uInt32 nFirstEffect = LISTBOX_ENTRY_NOTFOUND; + sal_Int32 nFirstEffect = -1; - mpLBAnimation->Clear(); + int nOldEntryCount = mxLBAnimation->n_children(); + int nOldScrollPos = mxLBAnimation->vadjustment_get_value(); - if(nPosition == gnMotionPathPos) + mxLBAnimation->freeze(); + mxLBAnimation->clear(); + mnLastSelectedAnimation = -1; + + if (nPosition == gnMotionPathPos) { OUString sMotionPathLabel( SdResId( STR_CUSTOMANIMATION_USERPATH ) ); - mpLBAnimation->InsertCategory( sMotionPathLabel ); - mnCurvePathPos = mpLBAnimation->InsertEntry( SvxResId(STR_ObjNameSingulCOMBLINE) ); - mnPolygonPathPos = mpLBAnimation->InsertEntry( SvxResId(STR_ObjNameSingulPOLY) ); - mnFreeformPathPos = mpLBAnimation->InsertEntry( SvxResId(STR_ObjNameSingulFREELINE) ); + InsertCategory(*mxLBAnimation, sMotionPathLabel); + mnCurvePathPos = mxLBAnimation->n_children(); + mxLBAnimation->append_text( SvxResId(STR_ObjNameSingulCOMBLINE) ); + mxLBAnimation->set_text_emphasis(mnCurvePathPos, false, 0); + mnPolygonPathPos = mnCurvePathPos + 1; + mxLBAnimation->append_text( SvxResId(STR_ObjNameSingulPOLY) ); + mxLBAnimation->set_text_emphasis(mnPolygonPathPos, false, 0); + mnFreeformPathPos = mnPolygonPathPos + 1; + mxLBAnimation->append_text( SvxResId(STR_ObjNameSingulFREELINE) ); + mxLBAnimation->set_text_emphasis(mnFreeformPathPos, false, 0); } for (PresetCategoryPtr& pCategory : rCategoryList) { if( pCategory.get() ) { - mpLBAnimation->InsertCategory( pCategory->maLabel ); + InsertCategory(*mxLBAnimation, pCategory->maLabel); + + int nPos = mxLBAnimation->n_children(); std::vector< CustomAnimationPresetPtr > aSortedVector(pCategory->maEffects.size()); std::copy( pCategory->maEffects.begin(), pCategory->maEffects.end(), aSortedVector.begin() ); @@ -2214,49 +2228,59 @@ sal_uInt32 CustomAnimationPane::fillAnimationLB( bool bHasText ) // ( !isTextOnly || ( isTextOnly && bHasText ) ) <=> !isTextOnly || bHasText if( pDescriptor.get() && ( !pDescriptor->isTextOnly() || bHasText ) ) { - sal_Int32 nPos = mpLBAnimation->InsertEntry( pDescriptor->getLabel() ); - mpLBAnimation->SetEntryData(nPos, new CustomAnimationPresetPtr(pDescriptor)); + auto pCustomPtr = new CustomAnimationPresetPtr(pDescriptor); + OUString sId = OUString::number(reinterpret_cast<sal_Int64>(pCustomPtr)); + mxLBAnimation->append(sId, pDescriptor->getLabel()); + mxLBAnimation->set_text_emphasis(nPos, false, 0); - if( nFirstEffect == LISTBOX_ENTRY_NOTFOUND ) + if (nFirstEffect == -1) nFirstEffect = nPos; + + ++nPos; } } } } + + mxLBAnimation->thaw(); + + if (mxLBAnimation->n_children() == nOldEntryCount) + mxLBAnimation->vadjustment_set_value(nOldScrollPos); + return nFirstEffect; } - -IMPL_LINK( CustomAnimationPane, implClickHdl, Button*, pBtn, void ) +IMPL_LINK(CustomAnimationPane, implClickHdl, weld::Button&, rBtn, void) { - implControlHdl(pBtn); + implControlHdl(&rBtn); } -IMPL_LINK( CustomAnimationPane, implControlListBoxHdl, ListBox&, rListBox, void ) + +IMPL_LINK( CustomAnimationPane, implControlListBoxHdl, weld::ComboBox&, rListBox, void ) { implControlHdl(&rListBox); } /// this link is called when one of the controls is modified -void CustomAnimationPane::implControlHdl(Control const * pControl ) +void CustomAnimationPane::implControlHdl(const weld::Widget* pControl) { - if( pControl == mpPBAddEffect ) + if (pControl == mxPBAddEffect.get()) onAdd(); - else if( pControl == mpPBRemoveEffect ) + else if (pControl == mxPBRemoveEffect.get()) onRemove(); - else if( pControl == mpLBStart ) + else if (pControl == mxLBStart.get()) onChangeStart(); - else if( pControl == mpPBPropertyMore ) + else if (pControl == mxPBPropertyMore.get()) showOptions(); - else if( pControl == mpPBMoveUp ) + else if (pControl == mxPBMoveUp.get()) moveSelection( true ); - else if( pControl == mpPBMoveDown ) + else if (pControl == mxPBMoveDown.get()) moveSelection( false ); - else if( pControl == mpPBPlay ) + else if (pControl == mxPBPlay.get()) onPreview( true ); - else if( pControl == mpCBAutoPreview ) + else if (pControl == mxCBAutoPreview.get()) { SdOptions* pOptions = SD_MOD()->GetSdOptions(DocumentType::Impress); - pOptions->SetPreviewChangedEffects( mpCBAutoPreview->IsChecked() ); + pOptions->SetPreviewChangedEffects(mxCBAutoPreview->get_active()); } } @@ -2299,9 +2323,8 @@ void CustomAnimationPane::moveSelection( bool bUp ) if( aInsertPos != rEffectSequence.begin() ) { --aInsertPos; - while( (aInsertPos != rEffectSequence.begin()) && !mpCustomAnimationList->isExpanded(*aInsertPos)) + while( (aInsertPos != rEffectSequence.begin()) && !mxCustomAnimationList->isExpanded(*aInsertPos)) --aInsertPos; - rEffectSequence.insert( aInsertPos, pEffect ); } else @@ -2332,12 +2355,11 @@ void CustomAnimationPane::moveSelection( bool bUp ) ++aInsertPos; // Advance over rolled-up (un-expanded) items, unless we just moved it there. while( (aInsertPos != rEffectSequence.end()) - && !mpCustomAnimationList->isExpanded(*aInsertPos) + && !mxCustomAnimationList->isExpanded(*aInsertPos) && (std::find(maListSelection.begin(), maListSelection.end(), *aInsertPos) == maListSelection.end()) ) ++aInsertPos; - rEffectSequence.insert( aInsertPos, pEffect ); } else @@ -2359,7 +2381,7 @@ void CustomAnimationPane::moveSelection( bool bUp ) void CustomAnimationPane::onPreview( bool bForcePreview ) { - if( !bForcePreview && !mpCBAutoPreview->IsChecked() ) + if (!bForcePreview && !mxCBAutoPreview->get_active()) return; // No preview in LOK. @@ -2416,7 +2438,7 @@ void CustomAnimationPane::preview( const Reference< XAnimationNode >& xAnimation // ICustomAnimationListController void CustomAnimationPane::onSelect() { - maListSelection = mpCustomAnimationList->getSelection(); + maListSelection = mxCustomAnimationList->getSelection(); updateControls(); // mark shapes from selected effects @@ -2466,20 +2488,16 @@ void CustomAnimationPane::onDragNDropComplete(std::vector< CustomAnimationEffect // Update model with new location (function triggers a rebuild) // target may be null, which will insert at the end. mpMainSequence->moveToBeforeEffect( pEffect, pEffectInsertBefore ); - // Done moving effect and its hidden sub-effects when *next* effect is visible. - if (aIter != aEnd && mpCustomAnimationList->isVisible(*aIter)) + if (aIter != aEnd && mxCustomAnimationList->isVisible(*aIter)) break; } - } - updateControls(); mrBase.GetDocShell()->SetModified(); } - void CustomAnimationPane::updatePathFromMotionPathTag( const rtl::Reference< MotionPathTag >& xTag ) { MainSequenceRebuildGuard aGuard( mpMainSequence ); diff --git a/sd/source/ui/animations/CustomAnimationPane.hxx b/sd/source/ui/animations/CustomAnimationPane.hxx index 7aa293172646..472a4df03679 100644 --- a/sd/source/ui/animations/CustomAnimationPane.hxx +++ b/sd/source/ui/animations/CustomAnimationPane.hxx @@ -20,13 +20,9 @@ #ifndef INCLUDED_SD_SOURCE_UI_ANIMATIONS_CUSTOMANIMATIONPANE_HXX #define INCLUDED_SD_SOURCE_UI_ANIMATIONS_CUSTOMANIMATIONPANE_HXX -#include <vcl/button.hxx> -#include <vcl/field.hxx> -#include <vcl/fixed.hxx> #include <svx/sidebar/PanelLayout.hxx> #include "CustomAnimationDialog.hxx" #include "CustomAnimationList.hxx" -#include "CategoryListBox.hxx" #include "motionpathtag.hxx" #include <misc/scopelock.hxx> @@ -110,52 +106,53 @@ private: static css::uno::Any getProperty1Value( sal_Int32 nType, const CustomAnimationEffectPtr& pEffect ); static bool setProperty1Value( sal_Int32 nType, const CustomAnimationEffectPtr& pEffect, const css::uno::Any& rValue ); void UpdateLook(); - sal_uInt32 fillAnimationLB( bool bHasText ); + sal_Int32 fillAnimationLB( bool bHasText ); PathKind getCreatePathKind() const; void createPath( PathKind eKind, std::vector< ::com::sun::star::uno::Any >& rTargets, double fDuration ); - DECL_LINK( implControlListBoxHdl, ListBox&, void ); - DECL_LINK( implClickHdl, Button*, void ); + DECL_LINK( implControlListBoxHdl, weld::ComboBox&, void ); + DECL_LINK( implClickHdl, weld::Button&, void ); DECL_LINK( implPropertyHdl, LinkParamNone*, void ); DECL_LINK( EventMultiplexerListener, tools::EventMultiplexerEvent&, void ); DECL_LINK( lateInitCallback, Timer *, void ); - DECL_LINK( DurationModifiedHdl, Edit&, void ); - DECL_LINK( DelayModifiedHdl, Edit&, void ); - DECL_LINK( DelayLoseFocusHdl, Control&, void ); - DECL_LINK( UpdateAnimationLB, ListBox&, void ); - DECL_LINK( AnimationSelectHdl, ListBox&, void ); - void implControlHdl(Control const *); + DECL_LINK( DurationModifiedHdl, weld::MetricSpinButton&, void ); + DECL_LINK( DelayModifiedHdl, weld::MetricSpinButton&, void ); + DECL_LINK( DelayLoseFocusHdl, weld::Widget&, void ); + DECL_LINK( UpdateAnimationLB, weld::ComboBox&, void ); + DECL_LINK( AnimationSelectHdl, weld::TreeView&, void ); + void implControlHdl(const weld::Widget* pControl); private: ViewShellBase& mrBase; // UI Elements - VclPtr<FixedText> mpFTAnimation; - VclPtr<CustomAnimationList> mpCustomAnimationList; - VclPtr<PushButton> mpPBAddEffect; - VclPtr<PushButton> mpPBRemoveEffect; - VclPtr<PushButton> mpPBMoveUp; - VclPtr<PushButton> mpPBMoveDown; - VclPtr<FixedText> mpFTCategory; - VclPtr<ListBox> mpLBCategory; - VclPtr<FixedText> mpFTEffect; - VclPtr<CategoryListBox> mpLBAnimation; - VclPtr<FixedText> mpFTStart; - VclPtr<ListBox> mpLBStart; - VclPtr<FixedText> mpFTProperty; - VclPtr<PropertyControl> mpLBProperty; - VclPtr<vcl::Window> mpPlaceholderBox; - VclPtr<PushButton> mpPBPropertyMore; - VclPtr<FixedText> mpFTDuration; - VclPtr<MetricBox> mpCBXDuration; - VclPtr<FixedText> mpFTStartDelay; - VclPtr<MetricField> mpMFStartDelay; - VclPtr<CheckBox> mpCBAutoPreview; - VclPtr<PushButton> mpPBPlay; + std::unique_ptr<weld::Label> mxFTAnimation; + std::unique_ptr<CustomAnimationList> mxCustomAnimationList; + std::unique_ptr<weld::Button> mxPBAddEffect; + std::unique_ptr<weld::Button> mxPBRemoveEffect; + std::unique_ptr<weld::Button> mxPBMoveUp; + std::unique_ptr<weld::Button> mxPBMoveDown; + std::unique_ptr<weld::Label> mxFTCategory; + std::unique_ptr<weld::ComboBox> mxLBCategory; + std::unique_ptr<weld::Label> mxFTEffect; + std::unique_ptr<weld::TreeView> mxLBAnimation; + std::unique_ptr<weld::Label> mxFTStart; + std::unique_ptr<weld::ComboBox> mxLBStart; + std::unique_ptr<weld::Label> mxFTProperty; + std::unique_ptr<SdPropertySubControl> mxLBSubControl; + std::unique_ptr<weld::Container> mxPlaceholderBox; + std::unique_ptr<weld::Button> mxPBPropertyMore; + std::unique_ptr<weld::Label> mxFTDuration; + std::unique_ptr<weld::MetricSpinButton> mxCBXDuration; + std::unique_ptr<weld::Label> mxFTStartDelay; + std::unique_ptr<weld::MetricSpinButton> mxMFStartDelay; + std::unique_ptr<weld::CheckButton> mxCBAutoPreview; + std::unique_ptr<weld::Button> mxPBPlay; OUString maStrModify; OUString maStrProperty; + sal_Int32 mnLastSelectedAnimation; sal_Int32 mnPropertyType; static sal_Int32 const gnMotionPathPos = 3; sal_Int32 mnCurvePathPos; |