LibreOffice Module sw (master)  1
OutlineContentVisibilityWin.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  */
9 
10 #include <edtwin.hxx>
12 #include <view.hxx>
13 #include <wrtsh.hxx>
14 
16 #include <txtfrm.hxx>
17 #include <ndtxt.hxx>
19 #include <vcl/event.hxx>
20 #include <vcl/svapp.hxx>
21 #include <strings.hrc>
22 #include <svx/svdview.hxx>
23 
24 #include <viewopt.hxx>
25 
27  const SwFrame* pFrame)
28  : InterimItemWindow(pEditWin, "modules/swriter/ui/outlinebutton.ui", "OutlineButton")
29  , m_xRightBtn(m_xBuilder->weld_button("right"))
30  , m_xDownBtn(m_xBuilder->weld_button("down"))
31  , m_pEditWin(pEditWin)
32  , m_pFrame(pFrame)
33  , m_nDelayAppearing(0)
34  , m_bDestroyed(false)
35  , m_nOutlinePos(SwOutlineNodes::npos)
36 {
37  const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
38  SetPaintTransparent(false);
39  SetBackground(rStyleSettings.GetFaceColor());
40 
41  Size aBtnsSize(m_xRightBtn->get_preferred_size());
42  auto nDim = std::max(aBtnsSize.Width(), aBtnsSize.Height());
43  m_xRightBtn->set_size_request(nDim, nDim);
44  m_xDownBtn->set_size_request(nDim, nDim);
45 
47  SetSymbol(SymbolType::DONTKNOW);
48 
49  m_xRightBtn->connect_mouse_press(LINK(this, SwOutlineContentVisibilityWin, MousePressHdl));
50  m_xDownBtn->connect_mouse_press(LINK(this, SwOutlineContentVisibilityWin, MousePressHdl));
51 
52  m_xRightBtn->connect_key_press(LINK(this, SwOutlineContentVisibilityWin, KeyInputHdl));
53  m_xDownBtn->connect_key_press(LINK(this, SwOutlineContentVisibilityWin, KeyInputHdl));
54 
57 }
58 
60 {
61  m_bDestroyed = true;
63 
64  m_pEditWin.clear();
65  m_pFrame = nullptr;
66 
67  m_xDownBtn.reset();
68  m_xRightBtn.reset();
69 
71 }
72 
74 {
75  if (m_xRightBtn->get_visible())
76  return SymbolType::ARROW_RIGHT;
77  if (m_xDownBtn->get_visible())
78  return SymbolType::ARROW_DOWN;
79  return SymbolType::DONTKNOW;
80 }
81 
83 {
84  if (GetSymbol() == eStyle)
85  return;
86 
87  bool bRight = eStyle == SymbolType::ARROW_RIGHT;
88  bool bDown = eStyle == SymbolType::ARROW_DOWN;
89 
90  bool bControlHasFocus = ControlHasFocus();
91 
92  // disable mouse move for the hidden button so we don't get mouse
93  // leave events we don't care about when we swap buttons
94  m_xRightBtn->connect_mouse_move(Link<const MouseEvent&, bool>());
95  m_xDownBtn->connect_mouse_move(Link<const MouseEvent&, bool>());
96 
97  m_xRightBtn->set_visible(bRight);
98  m_xDownBtn->set_visible(bDown);
99 
100  weld::Button* pButton = nullptr;
101  if (bRight)
102  pButton = m_xRightBtn.get();
103  else if (bDown)
104  pButton = m_xDownBtn.get();
105  InitControlBase(pButton);
106  if (pButton)
107  {
108  pButton->connect_mouse_move(LINK(this, SwOutlineContentVisibilityWin, MouseMoveHdl));
109  if (bControlHasFocus)
110  pButton->grab_focus();
111  }
112 }
113 
115 {
116  const SwTextFrame* pTextFrame = static_cast<const SwTextFrame*>(GetFrame());
117 
118  // outline node frame containing folded outline node content might be folded so need to hide it
119  if (!pTextFrame || pTextFrame->IsInDtor())
120  {
121  SetSymbol(SymbolType::DONTKNOW);
122  Hide();
123  return;
124  }
125  const SwTextNode* pTextNode = pTextFrame->GetTextNodeFirst();
127  const SwOutlineNodes& rOutlineNodes = rSh.GetNodes().GetOutLineNds();
128  if (!pTextNode
129  || !rOutlineNodes.Seek_Entry(static_cast<SwNode*>(const_cast<SwTextNode*>(pTextNode)),
130  &m_nOutlinePos)
132  {
133  assert(false); // should never get here
134  return;
135  }
136 
137  // set symbol displayed on button
138  SetSymbol(rSh.IsOutlineContentVisible(m_nOutlinePos) ? SymbolType::ARROW_DOWN
139  : SymbolType::ARROW_RIGHT);
140 
141  // set quick help
142  SwOutlineNodes::size_type nOutlineNodesCount
145  OUString sQuickHelp(SwResId(STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY));
147  && m_nOutlinePos + 1 < nOutlineNodesCount
149  sQuickHelp += " (" + SwResId(STR_OUTLINE_CONTENT_TOGGLE_VISIBILITY_EXT) + ")";
150  SetQuickHelpText(sQuickHelp);
151 
152  // Set the position of the window
153  SwRect aSwRect = GetFrame()->getFrameArea(); // not far in margin
154  //SwRect aSwRect = GetFrame()->GetPaintArea(); // far in margin
155  aSwRect.AddTop(GetFrame()->GetTopMargin());
157  aSwRect.TopLeft() - (aSwRect.TopLeft() - aSwRect.BottomLeft()) / 2));
158  aPxPt.AdjustX(-GetSizePixel().getWidth() + 1);
159  aPxPt.AdjustY(-GetSizePixel().getHeight() / 2);
160  SetPosPixel(aPxPt);
161 }
162 
164 {
165  if (bShow)
166  {
167  m_nDelayAppearing = 0;
170  if (!m_bDestroyed)
172  }
173  else
174  Hide();
175 }
176 
177 bool SwOutlineContentVisibilityWin::Contains(const Point& rDocPt) const
178 {
180  if (aRect.IsInside(rDocPt))
181  return true;
182  return false;
183 }
184 
186 {
188  rSh.LockView(true);
189  if (GetEditWin()->GetView().GetDrawView()->IsTextEdit())
190  rSh.EndTextEdit();
191  if (GetEditWin()->GetView().IsDrawMode())
193  rSh.EnterStdMode();
194  // set cursor position here so Navigator tracks outline
195  // when doc changed broadcast message is sent in toggle function
199  else if (bSubs)
200  {
201  // toggle including sub levels
203  SwOutlineNodes::size_type nOutlineNodesCount
207  do
208  {
209  if (rSh.IsOutlineContentVisible(nPos) == bVisible)
211  } while (++nPos < nOutlineNodesCount
212  && rSh.getIDocumentOutlineNodesAccess()->getOutlineLevel(nPos) > nLevel);
213  }
214  else
216  if (!m_bDestroyed)
217  {
218  SetSymbol(rSh.IsOutlineContentVisible(m_nOutlinePos) ? SymbolType::ARROW_DOWN
219  : SymbolType::ARROW_RIGHT);
220  }
221  rSh.LockView(false);
222 }
223 
224 IMPL_LINK(SwOutlineContentVisibilityWin, KeyInputHdl, const KeyEvent&, rKEvt, bool)
225 {
226  bool bConsumed = false;
227 
228  vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
229  if (!aKeyCode.GetModifier()
230  && (aKeyCode.GetCode() == KEY_RETURN || aKeyCode.GetCode() == KEY_SPACE))
231  {
232  ToggleOutlineContentVisibility(aKeyCode.GetCode() == KEY_RETURN);
233  bConsumed = true;
234  }
235  else if (aKeyCode.GetCode() == KEY_ESCAPE)
236  {
237  Hide();
238  GrabFocusToDocument();
239  bConsumed = true;
240  }
241 
242  return bConsumed;
243 }
244 
245 IMPL_LINK(SwOutlineContentVisibilityWin, MouseMoveHdl, const MouseEvent&, rMEvt, bool)
246 {
247  if (rMEvt.IsLeaveWindow())
248  {
249  // MouseMove event may not be seen by edit window
250  // hide collapse button and grab focus to document
251  if (GetSymbol() != SymbolType::ARROW_RIGHT)
252  Hide();
253  GrabFocusToDocument();
254  }
255  else if (rMEvt.IsEnterWindow())
256  {
257  if (!m_bDestroyed && m_aDelayTimer.IsActive())
258  m_aDelayTimer.Stop();
259  // bring button to top and grab focus
260  SetZOrder(this, ZOrderFlags::First);
261  if (!ControlHasFocus())
262  GrabFocus();
263  }
264  GetEditWin()->SetSavedOutlineFrame(const_cast<SwFrame*>(GetFrame()));
265  return false;
266 }
267 
268 IMPL_LINK(SwOutlineContentVisibilityWin, MousePressHdl, const MouseEvent&, rMEvt, bool)
269 {
270  ToggleOutlineContentVisibility(rMEvt.IsRight());
271  return false;
272 }
273 
275 {
276  const int TICKS_BEFORE_WE_APPEAR = 5;
277  if (m_nDelayAppearing < TICKS_BEFORE_WE_APPEAR)
278  {
279  ++m_nDelayAppearing;
280  m_aDelayTimer.Start();
281  return;
282  }
283  if (GetEditWin()->GetSavedOutlineFrame() == GetFrame())
284  {
285  Show();
286  //GrabFocus(); commented out for tdf#140567
287  }
288  m_aDelayTimer.Stop();
289 }
290 
291 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< weld::Button > m_xDownBtn
virtual Point GetPosPixel() const
Base class of the Writer layout elements.
Definition: frame.hxx:298
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:157
bool bVisible
const SwNodes & GetNodes() const
Definition: viewsh.cxx:2084
virtual bool Contains(const Point &rDocPt) const override
Returns true if the point is inside the control.
IMPL_LINK(SwOutlineContentVisibilityWin, KeyInputHdl, const KeyEvent &, rKEvt, bool)
const SwView & GetView() const
Definition: edtwin.hxx:244
const IDocumentOutlineNodes * getIDocumentOutlineNodesAccess() const
Definition: viewsh.cxx:2694
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
const Color & GetFaceColor() const
virtual SwEditWin * GetEditWin() override
virtual Size GetSizePixel() const
virtual void SetSizePixel(const Size &rNewSize)
sal_uInt16 GetCode() const
void EnterStdMode()
Definition: select.cxx:550
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
constexpr sal_uInt16 KEY_SPACE
void SetQuickHelpText(const OUString &rHelpText)
SwWrtShell & GetWrtShell() const
Definition: view.hxx:400
void AddTop(const tools::Long nAdd)
Definition: swrect.cxx:165
bool IsActive() const
bool ControlHasFocus() const
Used by the UI to modify the document model.
Definition: wrtsh.hxx:91
Point TopLeft() const
Definition: swrect.cxx:174
virtual const SwFrame * GetFrame() override
void SetBackground()
int m_nDelayAppearing
Before we show the control, wait a few timer ticks to avoid appearing with every mouse over...
SymbolType
const SwRect & getFrameArea() const
Definition: frame.hxx:178
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
std::unique_ptr< weld::Button > m_xRightBtn
sal_uInt16 GetModifier() const
virtual void connect_mouse_move(const Link< const MouseEvent &, bool > &rLink)
SwTextNode * GetTextNodeFirst()
Definition: txtfrm.hxx:454
bool IsInDtor() const
Definition: frame.hxx:873
void clear()
static constexpr auto npos
Definition: ndarr.hxx:79
Window class for the Writer edit area, this is the one handling mouse and keyboard events and doing t...
Definition: edtwin.hxx:58
void ToggleOutlineContentVisibility(const bool bSubs)
virtual int getOutlineLevel(const tSortedOutlineNodeList::size_type nIdx) const =0
IMPL_LINK_NOARG(SwOutlineContentVisibilityWin, DelayAppearHandler, Timer *, void)
virtual tSortedOutlineNodeList::size_type getOutlineNodesCount() const =0
virtual void Start() override
Size get_preferred_size() const
bool IsInside(const Point &rPOINT) const
const SwOutlineNodes & GetOutLineNds() const
Array of all OutlineNodes.
Definition: ndarr.hxx:231
void SetPaintTransparent(bool bTransparent)
OUString SwResId(const char *pId)
Definition: swmodule.cxx:166
void LeaveDrawCreate()
Definition: view.hxx:525
virtual void ShowAll(bool bShow) override
void SetTimeout(sal_uInt64 nTimeoutMs)
constexpr sal_uInt16 KEY_RETURN
Point LogicToPixel(const Point &rLogicPt) const
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
bool IsOutlineContentVisible(const size_t nPos)
Definition: wrtsh1.cxx:1991
void Stop()
SwOutlineContentVisibilityWin(SwEditWin *pEditWin, const SwFrame *pFrame)
void LockView(bool b)
Definition: viewsh.hxx:462
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:423
constexpr sal_uInt16 KEY_ESCAPE
virtual void grab_focus()=0
void ToggleOutlineContentVisibility(SwNode *pNd, const bool bForceNotVisible=false)
Definition: wrtsh1.cxx:2007
virtual void dispose() override
::OutputDevice const * GetOutDev() const
void GotoOutline(SwOutlineNodes::size_type nIdx)
Definition: move.cxx:617
void EndTextEdit()
Deletes object if required.
Definition: feshview.cxx:1217
void SetInvokeHandler(const Link< Timer *, void > &rLink)
bool IsTreatSubOutlineLevelsAsContent() const
Definition: viewopt.cxx:106
bool Seek_Entry(SwNode *rP, size_type *pnPos) const
Definition: ndnum.cxx:32
std::vector< SwNode * >::size_type size_type
virtual void SetPosPixel(const Point &rNewPos)
void InitControlBase(weld::Widget *pWidget)
sal_uInt16 nPos
Point BottomLeft() const
Definition: swrect.cxx:176