summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2022-11-15 16:02:06 +0000
committerCaolán McNamara <caolanm@redhat.com>2022-11-15 20:34:51 +0100
commit701e8d06484fb8781e43017ccf4ac1a3d64ac9e8 (patch)
tree34001a0f4fdf15168ca8d8ccd08e9435d91b7c93 /sw
parent2550835bde036a2809d693d9633b8b736c035ecb (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.cxx4
-rw-r--r--sw/source/uibase/docvw/HeaderFooterWin.cxx138
-rw-r--r--sw/source/uibase/inc/HeaderFooterWin.hxx48
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);