framework/inc/uielement/toolbarmanager.hxx | 2 framework/source/uielement/generictoolbarcontroller.cxx | 94 +++++++++++++++- framework/source/uielement/toolbarmanager.cxx | 10 + include/framework/generictoolbarcontroller.hxx | 24 +++- include/sfx2/weldutils.hxx | 1 sfx2/inc/sidebar/ControllerFactory.hxx | 4 sfx2/inc/sidebar/SidebarToolBox.hxx | 1 sfx2/source/sidebar/ControllerFactory.cxx | 12 ++ sfx2/source/sidebar/SidebarToolBox.cxx | 9 + sfx2/source/toolbox/weldutils.cxx | 5 vcl/source/window/toolbox2.cxx | 43 ++----- 11 files changed, 169 insertions(+), 36 deletions(-)
New commits: commit dbeb697d62250e9429462c7f61b859893262a651 Author: Maxim Monastirsky <momonas...@gmail.com> AuthorDate: Fri Jul 29 09:56:51 2022 +0300 Commit: Maxim Monastirsky <momonas...@gmail.com> CommitDate: Tue Aug 30 13:08:39 2022 +0200 tdf#149956 Rework toolbar image flipping An unified code, covering both vcl and weld cases. For SidebarToolBox, the controller is created before items are inserted, so we listen for item insert event to set initially correct state. Change-Id: I3841f21883104b4d3f8541c97ec7fa5fc0bec575 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139022 Tested-by: Jenkins Reviewed-by: Maxim Monastirsky <momonas...@gmail.com> diff --git a/framework/inc/uielement/toolbarmanager.hxx b/framework/inc/uielement/toolbarmanager.hxx index 865a1b54d5b4..debd898c9b45 100644 --- a/framework/inc/uielement/toolbarmanager.hxx +++ b/framework/inc/uielement/toolbarmanager.hxx @@ -55,6 +55,7 @@ class Menu; namespace framework { +class ImageOrientationController; class ToolBarManager; class ToolBarManagerImpl @@ -246,6 +247,7 @@ class ToolBarManager final : public ToolbarManager_Base OUString m_sIconTheme; rtl::Reference< ToolBarManager > m_aOverflowManager; + rtl::Reference< ImageOrientationController > m_aImageController; }; } diff --git a/framework/source/uielement/generictoolbarcontroller.cxx b/framework/source/uielement/generictoolbarcontroller.cxx index 312b5ed9e77f..f61a0d0150b9 100644 --- a/framework/source/uielement/generictoolbarcontroller.cxx +++ b/framework/source/uielement/generictoolbarcontroller.cxx @@ -30,9 +30,9 @@ #include <svl/imageitm.hxx> #include <vcl/commandinfoprovider.hxx> #include <vcl/svapp.hxx> -#include <vcl/toolbox.hxx> #include <vcl/weld.hxx> #include <tools/urlobj.hxx> +#include <toolkit/helper/vclunohelper.hxx> #include <strings.hrc> #include <classes/fwkresid.hxx> @@ -338,6 +338,98 @@ IMPL_STATIC_LINK( GenericToolbarController, ExecuteHdl_Impl, void*, p, void ) delete pExecuteInfo; } +ImageOrientationController::ImageOrientationController(const Reference<XComponentContext>& rContext, + const Reference<XFrame>& rFrame, + const Reference<css::awt::XWindow>& rParentWindow, + const OUString& rModuleName) + : ToolboxController(rContext, rFrame, ".uno:ImageOrientation") + , m_nRotationAngle(0_deg10) + , m_bMirrored(false) +{ + m_sModuleName = rModuleName; + m_xParentWindow = rParentWindow; + initialize({}); + if (!m_pToolbar) + VCLUnoHelper::GetWindow(getParent())->AddEventListener(LINK(this, ImageOrientationController, WindowEventListener)); +} + +void ImageOrientationController::dispose() +{ + ToolboxController::dispose(); + if (!m_pToolbar) + VCLUnoHelper::GetWindow(getParent())->RemoveEventListener(LINK(this, ImageOrientationController, WindowEventListener)); +} + +IMPL_LINK(ImageOrientationController, WindowEventListener, VclWindowEvent&, rWindowEvent, void) +{ + if (m_bDisposed || rWindowEvent.GetId() != VclEventId::ToolboxItemAdded) + return; + + ToolBox* pToolBox = static_cast<ToolBox*>(rWindowEvent.GetWindow()); + ToolBoxItemId nItemId = pToolBox->GetItemId(reinterpret_cast<sal_IntPtr>(rWindowEvent.GetData())); + OUString aCommand = pToolBox->GetItemCommand(nItemId); + + if (vcl::CommandInfoProvider::IsMirrored(aCommand, getModuleName())) + pToolBox->SetItemImageMirrorMode(nItemId, m_bMirrored); + if (vcl::CommandInfoProvider::IsRotated(aCommand, getModuleName())) + pToolBox->SetItemImageAngle(nItemId, m_nRotationAngle); +} + +void ImageOrientationController::statusChanged(const css::frame::FeatureStateEvent& rEvent) +{ + if (m_bDisposed) + throw DisposedException(); + + SfxImageItem aItem; + aItem.PutValue(rEvent.State, 0); + + if (m_bMirrored == aItem.IsMirrored() && m_nRotationAngle == aItem.GetRotation()) + return; + + m_bMirrored = aItem.IsMirrored(); + m_nRotationAngle = aItem.GetRotation(); + + if (m_pToolbar) + { + for (int i = 0, nCount = m_pToolbar->get_n_items(); i < nCount; ++i) + { + OString aCommand = m_pToolbar->get_item_ident(i); + if (vcl::CommandInfoProvider::IsMirrored(OUString::fromUtf8(aCommand), getModuleName())) + { + m_pToolbar->set_item_image_mirrored(aCommand, m_bMirrored); + auto xGraphic(vcl::CommandInfoProvider::GetXGraphicForCommand( + OUString::fromUtf8(aCommand), m_xFrame, m_pToolbar->get_icon_size())); + m_pToolbar->set_item_image(aCommand, xGraphic); + } + } + } + else + { + ToolBox* pToolBox = static_cast<ToolBox*>(VCLUnoHelper::GetWindow(getParent())); + for (ToolBox::ImplToolItems::size_type i = 0; i < pToolBox->GetItemCount(); ++i) + { + ToolBoxItemId nItemId = pToolBox->GetItemId(i); + OUString aCommand = pToolBox->GetItemCommand(nItemId); + bool bModified = false; + if (vcl::CommandInfoProvider::IsMirrored(aCommand, getModuleName())) + { + pToolBox->SetItemImageMirrorMode(nItemId, m_bMirrored); + bModified = true; + } + if (vcl::CommandInfoProvider::IsRotated(aCommand, getModuleName())) + { + pToolBox->SetItemImageAngle(nItemId, m_nRotationAngle); + bModified = true; + } + if (bModified) + { + Image aImage(vcl::CommandInfoProvider::GetImageForCommand(aCommand, m_xFrame, pToolBox->GetImageSize())); + pToolBox->SetItemImage(nItemId, aImage); + } + } + } +} + } // namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/uielement/toolbarmanager.cxx b/framework/source/uielement/toolbarmanager.cxx index d1251f96cb84..723afeb09977 100644 --- a/framework/source/uielement/toolbarmanager.cxx +++ b/framework/source/uielement/toolbarmanager.cxx @@ -766,6 +766,8 @@ void ToolBarManager::frameAction( const FrameActionEvent& Action ) SolarMutexGuard g; if ( Action.Action == FrameAction_CONTEXT_CHANGED && !m_bDisposed ) { + if (m_aImageController) + m_aImageController->update(); m_aAsyncUpdateControllersTimer.Start(); } } @@ -998,6 +1000,10 @@ void ToolBarManager::RemoveControllers() m_aSubToolBarControllerMap.clear(); + if (m_aImageController) + m_aImageController->dispose(); + m_aImageController.clear(); + // i90033 // Remove item window pointers from the toolbar. They were // destroyed by the dispose() at the XComponent. This is needed @@ -1662,6 +1668,10 @@ void ToolBarManager::RequestImages() ++pIter; ++i; } + + assert(!m_aImageController); // an existing one isn't disposed here + m_aImageController = new ImageOrientationController(m_xContext, m_xFrame, m_pImpl->GetInterface(), m_aModuleIdentifier); + m_aImageController->update(); } void ToolBarManager::notifyRegisteredControllers( const OUString& aUIElementName, const OUString& aCommand ) diff --git a/include/framework/generictoolbarcontroller.hxx b/include/framework/generictoolbarcontroller.hxx index 473941a7682a..17aab6338ee2 100644 --- a/include/framework/generictoolbarcontroller.hxx +++ b/include/framework/generictoolbarcontroller.hxx @@ -21,9 +21,7 @@ #include <framework/fwkdllapi.h> #include <svtools/toolboxcontroller.hxx> -#include <vcl/vclptr.hxx> - -class ToolBox; +#include <vcl/toolbox.hxx> namespace framework { @@ -69,6 +67,26 @@ class FWK_DLLPUBLIC GenericToolbarController final : public svt::ToolboxControll OUString m_aEnumCommand; }; +class FWK_DLLPUBLIC ImageOrientationController final : public svt::ToolboxController +{ +public: + ImageOrientationController(const css::uno::Reference<css::uno::XComponentContext>& rContext, + const css::uno::Reference<css::frame::XFrame>& rFrame, + const css::uno::Reference<css::awt::XWindow>& rParentWindow, + const OUString& rModuleName); + + // XComponent + void SAL_CALL dispose() override; + + // XStatusListener + void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& rEvent) override; + + DECL_LINK(WindowEventListener, VclWindowEvent&, void); +private: + Degree10 m_nRotationAngle; + bool m_bMirrored; +}; + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/sfx2/weldutils.hxx b/include/sfx2/weldutils.hxx index 8f230cee5283..503b9bee10f2 100644 --- a/include/sfx2/weldutils.hxx +++ b/include/sfx2/weldutils.hxx @@ -31,6 +31,7 @@ class SFX2_DLLPUBLIC ToolbarUnoDispatcher { private: css::uno::Reference<css::frame::XFrame> m_xFrame; + css::uno::Reference<css::lang::XComponent> m_xImageController; SvtMiscOptions m_aToolbarOptions; weld::Toolbar* m_pToolbar; weld::Builder* m_pBuilder; diff --git a/sfx2/inc/sidebar/ControllerFactory.hxx b/sfx2/inc/sidebar/ControllerFactory.hxx index 8d45a2e3b1ed..c30cec61425b 100644 --- a/sfx2/inc/sidebar/ControllerFactory.hxx +++ b/sfx2/inc/sidebar/ControllerFactory.hxx @@ -40,6 +40,10 @@ namespace sfx2::sidebar { class ControllerFactory { public: + static css::uno::Reference<css::lang::XComponent> CreateImageController( + const css::uno::Reference<css::frame::XFrame>& rxFrame, + const css::uno::Reference<css::awt::XWindow>& rxParentWindow); + static css::uno::Reference<css::frame::XToolbarController> CreateToolBoxController( ToolBox* pToolBox, const ToolBoxItemId nItemId, diff --git a/sfx2/inc/sidebar/SidebarToolBox.hxx b/sfx2/inc/sidebar/SidebarToolBox.hxx index acae7475e69a..f3c18c531455 100644 --- a/sfx2/inc/sidebar/SidebarToolBox.hxx +++ b/sfx2/inc/sidebar/SidebarToolBox.hxx @@ -54,6 +54,7 @@ public: void InitToolBox(VclBuilder::stringmap& rMap); protected: + css::uno::Reference<css::lang::XComponent> mxImageController; typedef std::map<ToolBoxItemId, css::uno::Reference<css::frame::XToolbarController>> ControllerContainer; ControllerContainer maControllers; bool mbAreHandlersRegistered; diff --git a/sfx2/source/sidebar/ControllerFactory.cxx b/sfx2/source/sidebar/ControllerFactory.cxx index d904b5260420..cc453c53cd7e 100644 --- a/sfx2/source/sidebar/ControllerFactory.cxx +++ b/sfx2/source/sidebar/ControllerFactory.cxx @@ -38,6 +38,18 @@ using namespace css::uno; namespace sfx2::sidebar { +Reference<lang::XComponent> ControllerFactory::CreateImageController( + const Reference<frame::XFrame>& rxFrame, + const Reference<awt::XWindow>& rxParentWindow) +{ + rtl::Reference xController(new framework::ImageOrientationController( + comphelper::getProcessComponentContext(), rxFrame, rxParentWindow, + vcl::CommandInfoProvider::GetModuleIdentifier(rxFrame))); + + xController->update(); + return xController; +} + Reference<frame::XToolbarController> ControllerFactory::CreateToolBoxController( ToolBox* pToolBox, const ToolBoxItemId nItemId, diff --git a/sfx2/source/sidebar/SidebarToolBox.cxx b/sfx2/source/sidebar/SidebarToolBox.cxx index bb89d007bbb0..936fdbdd4ddc 100644 --- a/sfx2/source/sidebar/SidebarToolBox.cxx +++ b/sfx2/source/sidebar/SidebarToolBox.cxx @@ -67,6 +67,12 @@ SidebarToolBox::SidebarToolBox (vcl::Window* pParentWindow) SetToolboxButtonSize(GetDefaultButtonSize()); SvtMiscOptions().AddListenerLink(LINK(this, SidebarToolBox, ChangedIconSizeHandler)); + if (SfxViewFrame::Current()) + { + auto xFrame(SfxViewFrame::Current()->GetFrame().GetFrameInterface()); + auto xWidget(VCLUnoHelper::GetInterface(this)); + mxImageController = sfx2::sidebar::ControllerFactory::CreateImageController(xFrame, xWidget); + } #ifdef DEBUG SetText(OUString("SidebarToolBox")); @@ -91,6 +97,9 @@ void SidebarToolBox::dispose() xComponent->dispose(); } + if (mxImageController) + mxImageController->dispose(); + if (mbAreHandlersRegistered) { SetDropdownClickHdl(Link<ToolBox *, void>()); diff --git a/sfx2/source/toolbox/weldutils.cxx b/sfx2/source/toolbox/weldutils.cxx index 25b173de633f..eff86b0b857f 100644 --- a/sfx2/source/toolbox/weldutils.cxx +++ b/sfx2/source/toolbox/weldutils.cxx @@ -13,7 +13,7 @@ #include <sfx2/weldutils.hxx> #include <vcl/commandinfoprovider.hxx> #include <vcl/settings.hxx> -#include <vcl/weld.hxx> +#include <vcl/weldutils.hxx> namespace { @@ -110,6 +110,8 @@ ToolbarUnoDispatcher::ToolbarUnoDispatcher(weld::Toolbar& rToolbar, weld::Builde CreateController(sCommand); } + rtl::Reference xWidget(new weld::TransportAsXWindow(m_pToolbar, m_pBuilder)); + m_xImageController = sfx2::sidebar::ControllerFactory::CreateImageController(m_xFrame, xWidget); m_aToolbarOptions.AddListenerLink(LINK(this, ToolbarUnoDispatcher, ChangedIconSizeHandler)); } @@ -194,6 +196,7 @@ void ToolbarUnoDispatcher::dispose() xComponent->dispose(); } + m_xImageController->dispose(); m_pToolbar->connect_clicked(Link<const OString&, void>()); m_pToolbar = nullptr; m_pBuilder = nullptr; diff --git a/vcl/source/window/toolbox2.cxx b/vcl/source/window/toolbox2.cxx index 701d77624d90..66e5637e6dff 100644 --- a/vcl/source/window/toolbox2.cxx +++ b/vcl/source/window/toolbox2.cxx @@ -954,6 +954,15 @@ static Image ImplMirrorImage( const Image& rImage ) return Image( aMirrBitmapEx ); } +static Image ImplRotImage( const Image& rImage, Degree10 nAngle10 ) +{ + BitmapEx aRotBitmapEx( rImage.GetBitmapEx() ); + + aRotBitmapEx.Rotate( nAngle10, COL_WHITE ); + + return Image( aRotBitmapEx ); +} + void ToolBox::SetItemImage( ToolBoxItemId nItemId, const Image& rImage ) { ImplToolItems::size_type nPos = GetItemPos( nItemId ); @@ -964,10 +973,9 @@ void ToolBox::SetItemImage( ToolBoxItemId nItemId, const Image& rImage ) ImplToolItem* pItem = &mpData->m_aItems[nPos]; Size aOldSize = pItem->maImage.GetSizePixel(); - if (pItem->mbMirrorMode) - pItem->maImage = ImplMirrorImage(rImage); - else - pItem->maImage = rImage; + pItem->maImage = pItem->mbMirrorMode ? ImplMirrorImage(rImage) : rImage; + if (pItem->mnImageAngle != 0_deg10) + pItem->maImage = ImplRotImage(pItem->maImage, pItem->mnImageAngle); // only once all is calculated, do extra work if (!mbCalc) @@ -979,15 +987,6 @@ void ToolBox::SetItemImage( ToolBoxItemId nItemId, const Image& rImage ) } } -static Image ImplRotImage( const Image& rImage, Degree10 nAngle10 ) -{ - BitmapEx aRotBitmapEx( rImage.GetBitmapEx() ); - - aRotBitmapEx.Rotate( nAngle10, COL_WHITE ); - - return Image( aRotBitmapEx ); -} - void ToolBox::SetItemImageAngle( ToolBoxItemId nItemId, Degree10 nAngle10 ) { ImplToolItems::size_type nPos = GetItemPos( nItemId ); @@ -996,25 +995,7 @@ void ToolBox::SetItemImageAngle( ToolBoxItemId nItemId, Degree10 nAngle10 ) return; ImplToolItem* pItem = &mpData->m_aItems[nPos]; - Size aOldSize = pItem->maImage.GetSizePixel(); - - Degree10 nDeltaAngle = (nAngle10 - pItem->mnImageAngle) % 3600_deg10; - while( nDeltaAngle < 0_deg10 ) - nDeltaAngle += 3600_deg10; - pItem->mnImageAngle = nAngle10; - if( nDeltaAngle && !!pItem->maImage ) - { - pItem->maImage = ImplRotImage( pItem->maImage, nDeltaAngle ); - } - - if (!mbCalc) - { - if (aOldSize != pItem->maImage.GetSizePixel()) - ImplInvalidate(true); - else - ImplUpdateItem(nPos); - } } void ToolBox::SetItemImageMirrorMode( ToolBoxItemId nItemId, bool bMirror )