summaryrefslogtreecommitdiffstats
path: root/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx')
-rw-r--r--sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx252
1 files changed, 252 insertions, 0 deletions
diff --git a/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx b/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx
new file mode 100644
index 0000000000..9985485502
--- /dev/null
+++ b/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <edtwin.hxx>
+#include <OutlineContentVisibilityWin.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+
+#include <IDocumentOutlineNodes.hxx>
+#include <txtfrm.hxx>
+#include <ndtxt.hxx>
+#include <vcl/InterimItemWindow.hxx>
+#include <vcl/event.hxx>
+#include <vcl/svapp.hxx>
+#include <strings.hrc>
+
+#include <viewopt.hxx>
+
+#include <FrameControlsManager.hxx>
+
+SwOutlineContentVisibilityWin::SwOutlineContentVisibilityWin(SwEditWin* pEditWin,
+ const SwFrame* pFrame)
+ : InterimItemWindow(pEditWin, "modules/swriter/ui/outlinebutton.ui", "OutlineButton")
+ , m_xShowBtn(m_xBuilder->weld_button("show"))
+ , m_xHideBtn(m_xBuilder->weld_button("hide"))
+ , m_pEditWin(pEditWin)
+ , m_pFrame(pFrame)
+ , m_nDelayAppearing(0)
+ , m_aDelayTimer("SwOutlineContentVisibilityWin m_aDelayTimer")
+ , m_bDestroyed(false)
+ , m_nOutlinePos(SwOutlineNodes::npos)
+{
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ SetPaintTransparent(false);
+ SetBackground(rStyleSettings.GetFaceColor());
+
+ Size aBtnsSize(m_xShowBtn->get_preferred_size());
+ auto nDim = std::max(aBtnsSize.Width(), aBtnsSize.Height());
+ m_xShowBtn->set_size_request(nDim, nDim);
+ m_xHideBtn->set_size_request(nDim, nDim);
+
+ SetSizePixel(get_preferred_size());
+ SetSymbol(ButtonSymbol::NONE);
+
+ m_xShowBtn->connect_mouse_press(LINK(this, SwOutlineContentVisibilityWin, MousePressHdl));
+ m_xHideBtn->connect_mouse_press(LINK(this, SwOutlineContentVisibilityWin, MousePressHdl));
+
+ m_aDelayTimer.SetTimeout(25);
+ m_aDelayTimer.SetInvokeHandler(LINK(this, SwOutlineContentVisibilityWin, DelayAppearHandler));
+}
+
+void SwOutlineContentVisibilityWin::dispose()
+{
+ m_bDestroyed = true;
+ m_aDelayTimer.Stop();
+
+ m_pEditWin.clear();
+ m_pFrame = nullptr;
+
+ m_xHideBtn.reset();
+ m_xShowBtn.reset();
+
+ InterimItemWindow::dispose();
+}
+
+ButtonSymbol SwOutlineContentVisibilityWin::GetSymbol() const
+{
+ if (m_xShowBtn->get_visible())
+ return ButtonSymbol::SHOW;
+ if (m_xHideBtn->get_visible())
+ return ButtonSymbol::HIDE;
+ return ButtonSymbol::NONE;
+}
+
+void SwOutlineContentVisibilityWin::SetSymbol(ButtonSymbol eStyle)
+{
+ if (GetSymbol() == eStyle)
+ return;
+
+ bool bShow = eStyle == ButtonSymbol::SHOW;
+ bool bHide = eStyle == ButtonSymbol::HIDE;
+
+ // disable mouse move for the hidden button so we don't get mouse
+ // leave events we don't care about when we swap buttons
+ m_xShowBtn->connect_mouse_move(Link<const MouseEvent&, bool>());
+ m_xHideBtn->connect_mouse_move(Link<const MouseEvent&, bool>());
+
+ m_xShowBtn->set_visible(bShow);
+ m_xHideBtn->set_visible(bHide);
+
+ weld::Button* pButton = nullptr;
+ if (bShow)
+ pButton = m_xShowBtn.get();
+ else if (bHide)
+ pButton = m_xHideBtn.get();
+ InitControlBase(pButton);
+ if (pButton)
+ pButton->connect_mouse_move(LINK(this, SwOutlineContentVisibilityWin, MouseMoveHdl));
+}
+
+void SwOutlineContentVisibilityWin::Set()
+{
+ const SwTextFrame* pTextFrame = static_cast<const SwTextFrame*>(GetFrame());
+ const SwTextNode* pTextNode = pTextFrame->GetTextNodeFirst();
+ SwWrtShell& rSh = GetEditWin()->GetView().GetWrtShell();
+ const SwOutlineNodes& rOutlineNodes = rSh.GetNodes().GetOutLineNds();
+
+ (void)rOutlineNodes.Seek_Entry(static_cast<SwNode*>(const_cast<SwTextNode*>(pTextNode)),
+ &m_nOutlinePos);
+
+ // set symbol displayed on button
+ bool bVisible = true;
+ const_cast<SwTextNode*>(pTextNode)->GetAttrOutlineContentVisible(bVisible);
+ SetSymbol(bVisible ? ButtonSymbol::HIDE : ButtonSymbol::SHOW);
+
+ // set quick help
+ SwOutlineNodes::size_type nOutlineNodesCount
+ = rSh.getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
+ int nLevel = rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(m_nOutlinePos);
+ OUString sQuickHelp(SwResId(STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY));
+ if (!rSh.GetViewOptions()->IsTreatSubOutlineLevelsAsContent()
+ && m_nOutlinePos + 1 < nOutlineNodesCount
+ && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(m_nOutlinePos + 1) > nLevel)
+ sQuickHelp += " (" + SwResId(STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT) + ")";
+ SetQuickHelpText(sQuickHelp);
+
+ // Set the position of the window
+ SwRect aFrameAreaRect = pTextFrame->getFrameArea();
+ aFrameAreaRect.AddTop(pTextFrame->GetTopMargin());
+ SwSpecialPos aSpecialPos;
+ aSpecialPos.nExtendRange = pTextNode->HasVisibleNumberingOrBullet() ? SwSPExtendRange::BEFORE
+ : SwSPExtendRange::NONE;
+ SwCursorMoveState aMoveState;
+ aMoveState.m_pSpecialPos = &aSpecialPos;
+ SwRect aCharRect;
+ pTextFrame->GetCharRect(aCharRect, SwPosition(*(pTextFrame->GetTextNodeForParaProps())),
+ &aMoveState);
+ Point aPxPt(GetEditWin()->GetOutDev()->LogicToPixel(
+ Point(aCharRect.Left(), aFrameAreaRect.Center().getY())));
+ if (pTextFrame->IsRightToLeft())
+ aPxPt.AdjustX(2);
+ else
+ aPxPt.AdjustX(-(GetSizePixel().getWidth() + 2));
+ aPxPt.AdjustY(-GetSizePixel().getHeight() / 2);
+ SetPosPixel(aPxPt);
+}
+
+void SwOutlineContentVisibilityWin::ShowAll(bool bShow)
+{
+ if (bShow)
+ {
+ m_nDelayAppearing = 0;
+ if (!m_bDestroyed && m_aDelayTimer.IsActive())
+ m_aDelayTimer.Stop();
+ if (!m_bDestroyed)
+ m_aDelayTimer.Start();
+ }
+ else
+ Hide();
+}
+
+bool SwOutlineContentVisibilityWin::Contains(const Point& rDocPt) const
+{
+ ::tools::Rectangle aRect(GetPosPixel(), GetSizePixel());
+ if (aRect.Contains(rDocPt))
+ return true;
+ return false;
+}
+
+IMPL_LINK(SwOutlineContentVisibilityWin, MouseMoveHdl, const MouseEvent&, rMEvt, bool)
+{
+ if (rMEvt.IsLeaveWindow())
+ {
+ if (GetSymbol() == ButtonSymbol::HIDE)
+ {
+ // MouseMove event may not be seen by the edit window for example when move is to
+ // a show button or when move is outside of the edit window.
+ // Only hide when mouse leave results in leaving the frame.
+ tools::Rectangle aFrameAreaPxRect
+ = GetEditWin()->LogicToPixel(GetFrame()->getFrameArea().SVRect());
+ auto nY = GetPosPixel().getY() + rMEvt.GetPosPixel().getY();
+ if (nY <= 0 || nY <= aFrameAreaPxRect.Top() || nY >= aFrameAreaPxRect.Bottom()
+ || nY >= GetEditWin()->GetSizePixel().Height())
+ {
+ GetEditWin()->SetSavedOutlineFrame(nullptr);
+ GetEditWin()->GetFrameControlsManager().RemoveControlsByType(
+ FrameControlType::Outline, GetFrame());
+ // warning: "this" is disposed now
+ }
+ }
+ }
+ else if (rMEvt.IsEnterWindow())
+ {
+ // Leave window event might not have resulted in removing hide button from saved frame
+ // and the edit win might not receive mouse event between leaving saved frame button and
+ // entering this button.
+ if (GetFrame() != GetEditWin()->GetSavedOutlineFrame())
+ {
+ SwFrameControlPtr pFrameControl = GetEditWin()->GetFrameControlsManager().GetControl(
+ FrameControlType::Outline, GetEditWin()->GetSavedOutlineFrame());
+ if (pFrameControl)
+ {
+ SwOutlineContentVisibilityWin* pControl
+ = dynamic_cast<SwOutlineContentVisibilityWin*>(pFrameControl->GetIFacePtr());
+ if (pControl && pControl->GetSymbol() == ButtonSymbol::HIDE)
+ {
+ GetEditWin()->GetFrameControlsManager().RemoveControlsByType(
+ FrameControlType::Outline, GetEditWin()->GetSavedOutlineFrame());
+ // The outline content visibility window frame control (hide button)
+ // for saved outline frame is now disposed.
+ }
+ }
+ GetEditWin()->SetSavedOutlineFrame(
+ static_cast<SwTextFrame*>(const_cast<SwFrame*>(GetFrame())));
+ }
+ if (!m_bDestroyed && m_aDelayTimer.IsActive())
+ m_aDelayTimer.Stop();
+ // bring button to top
+ SetZOrder(this, ZOrderFlags::First);
+ }
+ return false;
+}
+
+// Toggle the outline content visibility on mouse press
+IMPL_LINK(SwOutlineContentVisibilityWin, MousePressHdl, const MouseEvent&, rMEvt, bool)
+{
+ Hide();
+ GetEditWin()->ToggleOutlineContentVisibility(m_nOutlinePos, rMEvt.IsRight());
+ return false;
+}
+
+IMPL_LINK_NOARG(SwOutlineContentVisibilityWin, DelayAppearHandler, Timer*, void)
+{
+ const int TICKS_BEFORE_WE_APPEAR = 3;
+ if (m_nDelayAppearing < TICKS_BEFORE_WE_APPEAR)
+ {
+ ++m_nDelayAppearing;
+ m_aDelayTimer.Start();
+ return;
+ }
+ if (GetEditWin()->GetSavedOutlineFrame() == GetFrame())
+ Show();
+ m_aDelayTimer.Stop();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */