tdf#151980 sw content controls: fix RTL render of dropdowns

- check if this widget is meant to be RTL in
  SwSelPaintRects::HighlightContentControl()

- route RTLness to the underlying tree view / drop-down in
  SwDropDownContentControlButton::InitDropdown()

- fix up SwContentControlButton (positioning, rendering, hit testing) to
  assume the button on the left of the first text portion in the RTL
  case

Change-Id: I637ee8f08311e1273f8b19ddf3ab572af839760b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142577
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
diff --git a/sw/source/core/crsr/contentcontrolbutton.cxx b/sw/source/core/crsr/contentcontrolbutton.cxx
index cd3deb5..908d5f1 100644
--- a/sw/source/core/crsr/contentcontrolbutton.cxx
+++ b/sw/source/core/crsr/contentcontrolbutton.cxx
@@ -71,6 +71,10 @@ void SwContentControlButton::CalcPosAndSize(const SwRect& rPortionPaintArea)
    m_aFramePixel = tools::Rectangle(aBoxPos, aBoxSize);

    // Then extend the size with the button area
    if (m_bRTL)
    {
        aBoxPos.AdjustX(-GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height());
    }
    aBoxSize.AdjustWidth(GetParent()->LogicToPixel(rPortionPaintArea.SSize()).Height());

    if (aBoxPos != GetPosPixel() || aBoxSize != GetSizePixel())
@@ -112,7 +116,14 @@ void SwContentControlButton::Paint(vcl::RenderContext& rRenderContext, const too

    // Draw the button next to the frame
    Point aButtonPos(aFrameRect.TopLeft());
    aButtonPos.AdjustX(aFrameRect.GetSize().getWidth() - nPadding * 2);
    if (m_bRTL)
    {
        aButtonPos.AdjustX(nPadding * 2);
    }
    else
    {
        aButtonPos.AdjustX(aFrameRect.GetSize().getWidth() - nPadding * 2);
    }
    Size aButtonSize(aFrameRect.GetSize());
    aButtonSize.setWidth(GetSizePixel().getWidth() - aFrameRect.getOpenWidth() - nPadding);
    const tools::Rectangle aButtonRect(tools::Rectangle(aButtonPos, aButtonSize));
@@ -153,6 +164,11 @@ WindowHitTest SwContentControlButton::ImplHitTest(const Point& rFramePos)
        return aResult;
    else
    {
        if (m_bRTL)
        {
            return rFramePos.X() <= m_aFramePixel.Left() ? WindowHitTest::Inside
                                                         : WindowHitTest::Transparent;
        }
        return rFramePos.X() >= m_aFramePixel.Right() ? WindowHitTest::Inside
                                                      : WindowHitTest::Transparent;
    }
diff --git a/sw/source/core/crsr/dropdowncontentcontrolbutton.cxx b/sw/source/core/crsr/dropdowncontentcontrolbutton.cxx
index 14f1ba7..ba47c33 100644
--- a/sw/source/core/crsr/dropdowncontentcontrolbutton.cxx
+++ b/sw/source/core/crsr/dropdowncontentcontrolbutton.cxx
@@ -42,6 +42,7 @@ void SwDropDownContentControlButton::InitDropdown()
    tools::Long nMinListWidth = GetSizePixel().Width();
    aSize.setWidth(std::max(aSize.Width(), nMinListWidth));
    m_xTreeView->set_size_request(aSize.Width(), aSize.Height());
    m_xTreeView->set_direction(m_bRTL);
}

IMPL_LINK(SwDropDownContentControlButton, ListBoxHandler, weld::TreeView&, rBox, bool)
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
index 4d34e9b..dd4db78 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -637,6 +637,7 @@ void SwSelPaintRects::HighlightContentControl()
    std::vector<OString> aLOKRectangles;
    SwRect aFirstPortionPaintArea;
    SwRect aLastPortionPaintArea;
    bool bRTL = false;
    std::shared_ptr<SwContentControl> pContentControl;

    if (m_bShowContentControlOverlay)
@@ -683,6 +684,15 @@ void SwSelPaintRects::HighlightContentControl()
                aLastPortionPaintArea = (*pRects)[pRects->size() - 1];
            }
            pContentControl = pCurContentControlAtCursor->GetContentControl().GetContentControl();

            // The layout knows if the text node is RTL (either set directly, or inherited from the
            // environment).
            SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aFrames(*pTextNode);
            SwTextFrame* pFrame = aFrames.First();
            if (pFrame)
            {
                bRTL = pFrame->IsRightToLeft();
            }
        }
    }

@@ -756,7 +766,15 @@ void SwSelPaintRects::HighlightContentControl()
                    m_pContentControlButton = VclPtr<SwDropDownContentControlButton>::Create(
                        &rEditWin, pContentControl);
                }
                m_pContentControlButton->CalcPosAndSize(aLastPortionPaintArea);
                m_pContentControlButton->SetRTL(bRTL);
                if (bRTL)
                {
                    m_pContentControlButton->CalcPosAndSize(aFirstPortionPaintArea);
                }
                else
                {
                    m_pContentControlButton->CalcPosAndSize(aLastPortionPaintArea);
                }
                m_pContentControlButton->Show();
            }
        }
diff --git a/sw/source/core/inc/contentcontrolbutton.hxx b/sw/source/core/inc/contentcontrolbutton.hxx
index 37da5ec..28b9e49 100644
--- a/sw/source/core/inc/contentcontrolbutton.hxx
+++ b/sw/source/core/inc/contentcontrolbutton.hxx
@@ -25,6 +25,7 @@ public:
    virtual void dispose() override;

    void CalcPosAndSize(const SwRect& rPortionPaintArea);
    void SetRTL(bool bRTL) { m_bRTL = bRTL; }

    virtual void MouseButtonDown(const MouseEvent& rMEvt) override;
    DECL_LINK(PopupModeEndHdl, weld::Popover&, void);
@@ -46,6 +47,7 @@ protected:
    std::shared_ptr<SwContentControl> m_pContentControl;
    std::unique_ptr<weld::Builder> m_xPopupBuilder;
    std::unique_ptr<weld::Popover> m_xPopup;
    bool m_bRTL = false;
};

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */