1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #include <OutlineContentVisibilityWin.hxx>
15 #include <IDocumentOutlineNodes.hxx>
18 #include <vcl/InterimItemWindow.hxx>
19 #include <vcl/event.hxx>
20 #include <vcl/svapp.hxx>
21 #include <strings.hrc>
23 #include <viewopt.hxx>
25 #include <FrameControlsManager.hxx>
27 SwOutlineContentVisibilityWin::SwOutlineContentVisibilityWin(SwEditWin
* pEditWin
,
28 const SwFrame
* pFrame
)
29 : InterimItemWindow(pEditWin
, "modules/swriter/ui/outlinebutton.ui", "OutlineButton")
30 , m_xShowBtn(m_xBuilder
->weld_button("show"))
31 , m_xHideBtn(m_xBuilder
->weld_button("hide"))
32 , m_pEditWin(pEditWin
)
34 , m_nDelayAppearing(0)
35 , m_aDelayTimer("SwOutlineContentVisibilityWin m_aDelayTimer")
37 , m_nOutlinePos(SwOutlineNodes::npos
)
39 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
40 SetPaintTransparent(false);
41 SetBackground(rStyleSettings
.GetFaceColor());
43 Size
aBtnsSize(m_xShowBtn
->get_preferred_size());
44 auto nDim
= std::max(aBtnsSize
.Width(), aBtnsSize
.Height());
45 m_xShowBtn
->set_size_request(nDim
, nDim
);
46 m_xHideBtn
->set_size_request(nDim
, nDim
);
48 SetSizePixel(get_preferred_size());
49 SetSymbol(ButtonSymbol::NONE
);
51 m_xShowBtn
->connect_mouse_press(LINK(this, SwOutlineContentVisibilityWin
, MousePressHdl
));
52 m_xHideBtn
->connect_mouse_press(LINK(this, SwOutlineContentVisibilityWin
, MousePressHdl
));
54 m_aDelayTimer
.SetTimeout(25);
55 m_aDelayTimer
.SetInvokeHandler(LINK(this, SwOutlineContentVisibilityWin
, DelayAppearHandler
));
58 void SwOutlineContentVisibilityWin::dispose()
69 InterimItemWindow::dispose();
72 ButtonSymbol
SwOutlineContentVisibilityWin::GetSymbol() const
74 if (m_xShowBtn
->get_visible())
75 return ButtonSymbol::SHOW
;
76 if (m_xHideBtn
->get_visible())
77 return ButtonSymbol::HIDE
;
78 return ButtonSymbol::NONE
;
81 void SwOutlineContentVisibilityWin::SetSymbol(ButtonSymbol eStyle
)
83 if (GetSymbol() == eStyle
)
86 bool bShow
= eStyle
== ButtonSymbol::SHOW
;
87 bool bHide
= eStyle
== ButtonSymbol::HIDE
;
89 // disable mouse move for the hidden button so we don't get mouse
90 // leave events we don't care about when we swap buttons
91 m_xShowBtn
->connect_mouse_move(Link
<const MouseEvent
&, bool>());
92 m_xHideBtn
->connect_mouse_move(Link
<const MouseEvent
&, bool>());
94 m_xShowBtn
->set_visible(bShow
);
95 m_xHideBtn
->set_visible(bHide
);
97 weld::Button
* pButton
= nullptr;
99 pButton
= m_xShowBtn
.get();
101 pButton
= m_xHideBtn
.get();
102 InitControlBase(pButton
);
104 pButton
->connect_mouse_move(LINK(this, SwOutlineContentVisibilityWin
, MouseMoveHdl
));
107 void SwOutlineContentVisibilityWin::Set()
109 const SwTextFrame
* pTextFrame
= static_cast<const SwTextFrame
*>(GetFrame());
110 const SwTextNode
* pTextNode
= pTextFrame
->GetTextNodeFirst();
111 SwWrtShell
& rSh
= GetEditWin()->GetView().GetWrtShell();
112 const SwOutlineNodes
& rOutlineNodes
= rSh
.GetNodes().GetOutLineNds();
114 (void)rOutlineNodes
.Seek_Entry(static_cast<SwNode
*>(const_cast<SwTextNode
*>(pTextNode
)),
117 // set symbol displayed on button
118 bool bVisible
= true;
119 const_cast<SwTextNode
*>(pTextNode
)->GetAttrOutlineContentVisible(bVisible
);
120 SetSymbol(bVisible
? ButtonSymbol::HIDE
: ButtonSymbol::SHOW
);
123 SwOutlineNodes::size_type nOutlineNodesCount
124 = rSh
.getIDocumentOutlineNodesAccess()->getOutlineNodesCount();
125 int nLevel
= rSh
.getIDocumentOutlineNodesAccess()->getOutlineLevel(m_nOutlinePos
);
126 OUString
sQuickHelp(SwResId(STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY
));
127 if (!rSh
.GetViewOptions()->IsTreatSubOutlineLevelsAsContent()
128 && m_nOutlinePos
+ 1 < nOutlineNodesCount
129 && rSh
.getIDocumentOutlineNodesAccess()->getOutlineLevel(m_nOutlinePos
+ 1) > nLevel
)
130 sQuickHelp
+= " (" + SwResId(STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT
) + ")";
131 SetQuickHelpText(sQuickHelp
);
133 // Set the position of the window
134 SwRect aFrameAreaRect
= pTextFrame
->getFrameArea();
135 aFrameAreaRect
.AddTop(pTextFrame
->GetTopMargin());
136 SwSpecialPos aSpecialPos
;
137 aSpecialPos
.nExtendRange
= pTextNode
->HasVisibleNumberingOrBullet() ? SwSPExtendRange::BEFORE
138 : SwSPExtendRange::NONE
;
139 SwCursorMoveState aMoveState
;
140 aMoveState
.m_pSpecialPos
= &aSpecialPos
;
142 pTextFrame
->GetCharRect(aCharRect
, SwPosition(*(pTextFrame
->GetTextNodeForParaProps())),
144 Point
aPxPt(GetEditWin()->GetOutDev()->LogicToPixel(
145 Point(aCharRect
.Left(), aFrameAreaRect
.Center().getY())));
146 if (pTextFrame
->IsRightToLeft())
149 aPxPt
.AdjustX(-(GetSizePixel().getWidth() + 2));
150 aPxPt
.AdjustY(-GetSizePixel().getHeight() / 2);
154 void SwOutlineContentVisibilityWin::ShowAll(bool bShow
)
158 m_nDelayAppearing
= 0;
159 if (!m_bDestroyed
&& m_aDelayTimer
.IsActive())
160 m_aDelayTimer
.Stop();
162 m_aDelayTimer
.Start();
168 bool SwOutlineContentVisibilityWin::Contains(const Point
& rDocPt
) const
170 ::tools::Rectangle
aRect(GetPosPixel(), GetSizePixel());
171 if (aRect
.Contains(rDocPt
))
176 IMPL_LINK(SwOutlineContentVisibilityWin
, MouseMoveHdl
, const MouseEvent
&, rMEvt
, bool)
178 if (rMEvt
.IsLeaveWindow())
180 if (GetSymbol() == ButtonSymbol::HIDE
)
182 // MouseMove event may not be seen by the edit window for example when move is to
183 // a show button or when move is outside of the edit window.
184 // Only hide when mouse leave results in leaving the frame.
185 tools::Rectangle aFrameAreaPxRect
186 = GetEditWin()->LogicToPixel(GetFrame()->getFrameArea().SVRect());
187 auto nY
= GetPosPixel().getY() + rMEvt
.GetPosPixel().getY();
188 if (nY
<= 0 || nY
<= aFrameAreaPxRect
.Top() || nY
>= aFrameAreaPxRect
.Bottom()
189 || nY
>= GetEditWin()->GetSizePixel().Height())
191 GetEditWin()->SetSavedOutlineFrame(nullptr);
192 GetEditWin()->GetFrameControlsManager().RemoveControlsByType(
193 FrameControlType::Outline
, GetFrame());
194 // warning: "this" is disposed now
198 else if (rMEvt
.IsEnterWindow())
200 // Leave window event might not have resulted in removing hide button from saved frame
201 // and the edit win might not receive mouse event between leaving saved frame button and
202 // entering this button.
203 if (GetFrame() != GetEditWin()->GetSavedOutlineFrame())
205 SwFrameControlPtr pFrameControl
= GetEditWin()->GetFrameControlsManager().GetControl(
206 FrameControlType::Outline
, GetEditWin()->GetSavedOutlineFrame());
209 SwOutlineContentVisibilityWin
* pControl
210 = dynamic_cast<SwOutlineContentVisibilityWin
*>(pFrameControl
->GetIFacePtr());
211 if (pControl
&& pControl
->GetSymbol() == ButtonSymbol::HIDE
)
213 GetEditWin()->GetFrameControlsManager().RemoveControlsByType(
214 FrameControlType::Outline
, GetEditWin()->GetSavedOutlineFrame());
215 // The outline content visibility window frame control (hide button)
216 // for saved outline frame is now disposed.
219 GetEditWin()->SetSavedOutlineFrame(
220 static_cast<SwTextFrame
*>(const_cast<SwFrame
*>(GetFrame())));
222 if (!m_bDestroyed
&& m_aDelayTimer
.IsActive())
223 m_aDelayTimer
.Stop();
224 // bring button to top
225 SetZOrder(this, ZOrderFlags::First
);
230 // Toggle the outline content visibility on mouse press
231 IMPL_LINK(SwOutlineContentVisibilityWin
, MousePressHdl
, const MouseEvent
&, rMEvt
, bool)
234 GetEditWin()->ToggleOutlineContentVisibility(m_nOutlinePos
, rMEvt
.IsRight());
238 IMPL_LINK_NOARG(SwOutlineContentVisibilityWin
, DelayAppearHandler
, Timer
*, void)
240 const int TICKS_BEFORE_WE_APPEAR
= 3;
241 if (m_nDelayAppearing
< TICKS_BEFORE_WE_APPEAR
)
244 m_aDelayTimer
.Start();
247 if (GetEditWin()->GetSavedOutlineFrame() == GetFrame())
249 m_aDelayTimer
.Stop();
252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */