diff options
author | Caolán McNamara <caolanm@redhat.com> | 2022-11-15 16:02:06 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2022-11-15 20:34:51 +0100 |
commit | 701e8d06484fb8781e43017ccf4ac1a3d64ac9e8 (patch) | |
tree | 34001a0f4fdf15168ca8d8ccd08e9435d91b7c93 /sw | |
parent | 2550835bde036a2809d693d9633b8b736c035ecb (diff) |
Resolves: tdf#147802 don't create a header/footer control for every page
just create a cheaper SwHeaderFooterDashedLine and only create the
"expensive" control on-demand if it becomes visible on-screen and
destroy it immediately if it goes off-screen.
Change-Id: Id876145130d394f55f54790d5e8399dca4f8c03e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142742
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'sw')
-rw-r--r-- | sw/source/uibase/docvw/FrameControlsManager.cxx | 4 | ||||
-rw-r--r-- | sw/source/uibase/docvw/HeaderFooterWin.cxx | 138 | ||||
-rw-r--r-- | sw/source/uibase/inc/HeaderFooterWin.hxx | 48 |
3 files changed, 133 insertions, 57 deletions
diff --git a/sw/source/uibase/docvw/FrameControlsManager.cxx b/sw/source/uibase/docvw/FrameControlsManager.cxx index 93254830a2f1..e5c0c202a4eb 100644 --- a/sw/source/uibase/docvw/FrameControlsManager.cxx +++ b/sw/source/uibase/docvw/FrameControlsManager.cxx @@ -94,7 +94,7 @@ void SwFrameControlsManager::SetHeaderFooterControl( const SwPageFrame* pPageFra else { SwFrameControlPtr pNewControl = - std::make_shared<SwFrameControl>( VclPtr<SwHeaderFooterWin>::Create( + std::make_shared<SwFrameControl>( VclPtr<SwHeaderFooterDashedLine>::Create( m_pEditWin, pPageFrame, bHeader ).get() ); const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions(); pNewControl->SetReadonly( pViewOpt->IsReadonly() ); @@ -104,7 +104,7 @@ void SwFrameControlsManager::SetHeaderFooterControl( const SwPageFrame* pPageFra tools::Rectangle aPageRect = m_pEditWin->LogicToPixel( pPageFrame->getFrameArea().SVRect() ); - SwHeaderFooterWin* pWin = dynamic_cast<SwHeaderFooterWin *>(pControl->GetWindow()); + SwHeaderFooterDashedLine* pWin = dynamic_cast<SwHeaderFooterDashedLine*>(pControl->GetWindow()); assert( pWin != nullptr) ; assert( pWin->IsHeader() == bHeader ); pWin->SetOffset( aOffset, aPageRect.Left(), aPageRect.Right() ); diff --git a/sw/source/uibase/docvw/HeaderFooterWin.cxx b/sw/source/uibase/docvw/HeaderFooterWin.cxx index 81f9121892f1..0e79e1481012 100644 --- a/sw/source/uibase/docvw/HeaderFooterWin.cxx +++ b/sw/source/uibase/docvw/HeaderFooterWin.cxx @@ -160,26 +160,89 @@ void SwFrameButtonPainter::PaintButton(drawinglayer::primitive2d::Primitive2DCon new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(std::move(aPolygon), aLineColor))); } -SwHeaderFooterWin::SwHeaderFooterWin( SwEditWin* pEditWin, const SwFrame *pFrame, bool bHeader ) : - SwFrameMenuButtonBase(pEditWin, pFrame, "modules/swriter/ui/hfmenubutton.ui", "HFMenuButton"), +SwHeaderFooterDashedLine::SwHeaderFooterDashedLine(SwEditWin* pEditWin, const SwFrame *pFrame, bool bHeader) + : SwDashedLine(pEditWin, &SwViewOption::GetHeaderFooterMarkColor) + , m_pEditWin(pEditWin) + , m_pFrame(pFrame) + , m_bIsHeader(bHeader) +{ +} + +bool SwHeaderFooterDashedLine::IsOnScreen() +{ + tools::Rectangle aBounds(GetPosPixel(), GetSizePixel()); + tools::Rectangle aVisArea = GetEditWin()->LogicToPixel(GetEditWin()->GetView().GetVisArea()); + return aBounds.Overlaps(aVisArea); +} + +void SwHeaderFooterDashedLine::EnsureWin() +{ + if (!m_pWin) + { + m_pWin = VclPtr<SwHeaderFooterWin>::Create(m_pEditWin, m_pFrame, m_bIsHeader); + m_pWin->SetZOrder(this, ZOrderFlags::Before); + } +} + +void SwHeaderFooterDashedLine::ShowAll(bool bShow) +{ + Show(bShow); + if (!m_pWin && IsOnScreen()) + EnsureWin(); + if (m_pWin) + m_pWin->ShowAll(bShow); +} + +void SwHeaderFooterDashedLine::SetReadonly(bool bReadonly) +{ + ShowAll(!bReadonly); +} + +bool SwHeaderFooterDashedLine::Contains(const Point &rDocPt) const +{ + if (m_pWin && m_pWin->Contains(rDocPt)) + return true; + + ::tools::Rectangle aLineRect(GetPosPixel(), GetSizePixel()); + return aLineRect.Contains(rDocPt); +} + +void SwHeaderFooterDashedLine::SetOffset(Point aOffset, tools::Long nXLineStart, tools::Long nXLineEnd) +{ + Point aLinePos(nXLineStart, aOffset.Y()); + Size aLineSize(nXLineEnd - nXLineStart, 1); + SetPosSizePixel(aLinePos, aLineSize); + + bool bOnScreen = IsOnScreen(); + if (!m_pWin && bOnScreen) + { + EnsureWin(); + m_pWin->ShowAll(true); + } + else if (m_pWin && !bOnScreen) + m_pWin.disposeAndClear(); + + if (m_pWin) + m_pWin->SetOffset(aOffset); +} + +SwHeaderFooterWin::SwHeaderFooterWin(SwEditWin* pEditWin, const SwFrame *pFrame, bool bHeader ) : + InterimItemWindow(pEditWin, "modules/swriter/ui/hfmenubutton.ui", "HFMenuButton"), m_xMenuButton(m_xBuilder->weld_menu_button("menubutton")), m_xPushButton(m_xBuilder->weld_button("button")), + m_pEditWin(pEditWin), + m_pFrame(pFrame), m_bIsHeader( bHeader ), - m_pLine( nullptr ), m_bIsAppearing( false ), m_nFadeRate( 100 ), m_aFadeTimer("SwHeaderFooterWin m_aFadeTimer") { m_xVirDev = m_xMenuButton->create_virtual_device(); - SetVirDevFont(); + SwFrameMenuButtonBase::SetVirDevFont(*m_xVirDev); m_xPushButton->connect_clicked(LINK(this, SwHeaderFooterWin, ClickHdl)); m_xMenuButton->connect_selected(LINK(this, SwHeaderFooterWin, SelectHdl)); - // Create the line control - m_pLine = VclPtr<SwDashedLine>::Create(GetEditWin(), &SwViewOption::GetHeaderFooterMarkColor); - m_pLine->SetZOrder(this, ZOrderFlags::Before); - // set the PopupMenu // Rewrite the menu entries' text if (m_bIsHeader) @@ -204,20 +267,21 @@ SwHeaderFooterWin::~SwHeaderFooterWin( ) void SwHeaderFooterWin::dispose() { - m_pLine.disposeAndClear(); m_xPushButton.reset(); m_xMenuButton.reset(); + m_pEditWin.clear(); m_xVirDev.disposeAndClear(); - SwFrameMenuButtonBase::dispose(); + InterimItemWindow::dispose(); } -void SwHeaderFooterWin::SetOffset(Point aOffset, tools::Long nXLineStart, tools::Long nXLineEnd) +void SwHeaderFooterWin::SetOffset(Point aOffset) { // Compute the text to show - const SwPageDesc* pDesc = GetPageFrame()->GetPageDesc(); - bool bIsFirst = !pDesc->IsFirstShared() && GetPageFrame()->OnFirstPage(); - bool bIsLeft = !pDesc->IsHeaderShared() && !GetPageFrame()->OnRightPage(); - bool bIsRight = !pDesc->IsHeaderShared() && GetPageFrame()->OnRightPage(); + const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame); + const SwPageDesc* pDesc = pPageFrame->GetPageDesc(); + bool bIsFirst = !pDesc->IsFirstShared() && pPageFrame->OnFirstPage(); + bool bIsLeft = !pDesc->IsHeaderShared() && !pPageFrame->OnRightPage(); + bool bIsRight = !pDesc->IsHeaderShared() && pPageFrame->OnRightPage(); m_sLabel = SwResId(STR_HEADER_TITLE); if (!m_bIsHeader) m_sLabel = bIsFirst ? SwResId(STR_FIRST_FOOTER_TITLE) @@ -259,13 +323,6 @@ void SwHeaderFooterWin::SetOffset(Point aOffset, tools::Long nXLineStart, tools: m_xVirDev->SetOutputSizePixel(aBoxSize); PaintButton(); - - double nYLinePos = aBoxPos.Y(); - if (!m_bIsHeader) - nYLinePos += aBoxSize.Height(); - Point aLinePos(nXLineStart, nYLinePos); - Size aLineSize(nXLineEnd - nXLineStart, 1); - m_pLine->SetPosSizePixel(aLinePos, aLineSize); } void SwHeaderFooterWin::ShowAll(bool bShow) @@ -274,9 +331,6 @@ void SwHeaderFooterWin::ShowAll(bool bShow) m_xMenuButton->set_visible(!bIsEmptyHeaderFooter); m_xPushButton->set_visible(bIsEmptyHeaderFooter); - if (m_bIsAppearing == bShow) - return; - m_bIsAppearing = bShow; if (m_aFadeTimer.IsActive()) @@ -287,11 +341,7 @@ void SwHeaderFooterWin::ShowAll(bool bShow) bool SwHeaderFooterWin::Contains( const Point &rDocPt ) const { ::tools::Rectangle aRect(GetPosPixel(), GetSizePixel()); - if (aRect.Contains(rDocPt)) - return true; - - ::tools::Rectangle aLineRect(m_pLine->GetPosPixel(), m_pLine->GetSizePixel()); - return aLineRect.Contains(rDocPt); + return aRect.Contains(rDocPt); } void SwHeaderFooterWin::PaintButton() @@ -402,16 +452,17 @@ bool SwHeaderFooterWin::IsEmptyHeaderFooter( ) const { bool bResult = true; - if (!GetPageFrame()) + const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame); + if (!pPageFrame) { return bResult; } // Actually check it - const SwPageDesc* pDesc = GetPageFrame()->GetPageDesc(); + const SwPageDesc* pDesc = pPageFrame->GetPageDesc(); - bool const bFirst(GetPageFrame()->OnFirstPage()); - const SwFrameFormat *const pFormat = (GetPageFrame()->OnRightPage()) + bool const bFirst(pPageFrame->OnFirstPage()); + const SwFrameFormat *const pFormat = (pPageFrame->OnRightPage()) ? pDesc->GetRightFormat(bFirst) : pDesc->GetLeftFormat(bFirst); @@ -428,10 +479,11 @@ bool SwHeaderFooterWin::IsEmptyHeaderFooter( ) const void SwHeaderFooterWin::ExecuteCommand(std::string_view rIdent) { - SwView& rView = GetEditWin()->GetView(); + SwView& rView = m_pEditWin->GetView(); SwWrtShell& rSh = rView.GetWrtShell(); - const OUString& rStyleName = GetPageFrame()->GetPageDesc()->GetName(); + const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame); + const OUString& rStyleName = pPageFrame->GetPageDesc()->GetName(); if (rIdent == "edit") { OString sPageId = m_bIsHeader ? OString("header") : OString("footer"); @@ -439,7 +491,7 @@ void SwHeaderFooterWin::ExecuteCommand(std::string_view rIdent) } else if (rIdent == "borderback") { - const SwPageDesc* pDesc = GetPageFrame()->GetPageDesc(); + const SwPageDesc* pDesc = pPageFrame->GetPageDesc(); const SwFrameFormat& rMaster = pDesc->GetMaster(); SwFrameFormat* pHFFormat = const_cast< SwFrameFormat* >( rMaster.GetFooter().GetFooterFormat() ); if ( m_bIsHeader ) @@ -490,17 +542,13 @@ void SwHeaderFooterWin::ExecuteCommand(std::string_view rIdent) } } -void SwHeaderFooterWin::SetReadonly( bool bReadonly ) -{ - ShowAll( !bReadonly ); -} - IMPL_LINK_NOARG(SwHeaderFooterWin, ClickHdl, weld::Button&, void) { - SwView& rView = GetEditWin()->GetView(); + SwView& rView = m_pEditWin->GetView(); SwWrtShell& rSh = rView.GetWrtShell(); - const OUString& rStyleName = GetPageFrame()->GetPageDesc()->GetName(); + const SwPageFrame* pPageFrame = SwFrameMenuButtonBase::GetPageFrame(m_pFrame); + const OUString& rStyleName = pPageFrame->GetPageDesc()->GetName(); rSh.ChangeHeaderOrFooter( rStyleName, m_bIsHeader, true, false ); m_xPushButton->hide(); @@ -523,12 +571,10 @@ IMPL_LINK_NOARG(SwHeaderFooterWin, FadeHandler, Timer *, void) if (m_nFadeRate != 100 && !IsVisible()) { Show(); - m_pLine->Show(); } else if (m_nFadeRate == 100 && IsVisible()) { Show(false); - m_pLine->Show(false); } else PaintButton(); diff --git a/sw/source/uibase/inc/HeaderFooterWin.hxx b/sw/source/uibase/inc/HeaderFooterWin.hxx index d91f35edcc74..54d8136f69fe 100644 --- a/sw/source/uibase/inc/HeaderFooterWin.hxx +++ b/sw/source/uibase/inc/HeaderFooterWin.hxx @@ -10,6 +10,7 @@ #define INCLUDED_SW_SOURCE_UIBASE_INC_HEADERFOOTERWIN_HXX #include "edtwin.hxx" +#include "DashedLine.hxx" #include "FrameControl.hxx" #include <vcl/timer.hxx> #include <drawinglayer/primitive2d/Primitive2DContainer.hxx> @@ -26,39 +27,68 @@ public: const tools::Rectangle& rRect, bool bOnTop); }; +class SwHeaderFooterWin; + /** Class for the header and footer separator control window. This control is showing the header / footer style name and provides a few useful actions to the user. */ -class SwHeaderFooterWin final : public SwFrameMenuButtonBase +class SwHeaderFooterDashedLine : public SwDashedLine, public ISwFrameControl +{ +private: + VclPtr<SwHeaderFooterWin> m_pWin; + VclPtr<SwEditWin> m_pEditWin; + const SwFrame* m_pFrame; + bool m_bIsHeader; + + void EnsureWin(); + + bool IsOnScreen(); + +public: + SwHeaderFooterDashedLine(SwEditWin* pEditWin, const SwFrame *pFrame, bool bIsHeader); + + virtual ~SwHeaderFooterDashedLine() override { disposeOnce(); } + virtual void dispose() override { m_pWin.disposeAndClear(); m_pEditWin.clear(); SwDashedLine::dispose(); } + + virtual const SwFrame* GetFrame() override { return m_pFrame; } + virtual SwEditWin* GetEditWin() override { return m_pEditWin; } + virtual void ShowAll(bool bShow) override; + virtual bool Contains(const Point &rDocPt) const override; + virtual void SetReadonly(bool bReadonly) override; + + void SetOffset( Point aOffset, tools::Long nXLineStart, tools::Long nXLineEnd ); + bool IsHeader() const { return m_bIsHeader; }; +}; + +class SwHeaderFooterWin final : public InterimItemWindow { std::unique_ptr<weld::MenuButton> m_xMenuButton; std::unique_ptr<weld::Button> m_xPushButton; + VclPtr<SwEditWin> m_pEditWin; + VclPtr<VirtualDevice> m_xVirDev; + const SwFrame* m_pFrame; OUString m_sLabel; bool m_bIsHeader; - VclPtr<vcl::Window> m_pLine; bool m_bIsAppearing; int m_nFadeRate; Timer m_aFadeTimer; public: - SwHeaderFooterWin( SwEditWin *pEditWin, const SwFrame *pFrame, bool bHeader ); + SwHeaderFooterWin(SwEditWin *pEditWin, const SwFrame *pFrame, bool bHeader); virtual ~SwHeaderFooterWin( ) override; virtual void dispose() override; - void SetOffset( Point aOffset, tools::Long nXLineStart, tools::Long nXLineEnd ); - - virtual void ShowAll( bool bShow ) override; - virtual bool Contains( const Point &rDocPt ) const override; + void SetOffset(Point aOffset); + void ShowAll(bool bShow); + bool Contains(const Point &rDocPt) const; bool IsHeader() const { return m_bIsHeader; }; bool IsEmptyHeaderFooter( ) const; void ExecuteCommand(std::string_view rIdent); - void SetReadonly( bool bReadonly ) override; - private: DECL_LINK(FadeHandler, Timer *, void); DECL_LINK(ClickHdl, weld::Button&, void); |