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 )

Reply via email to