LibreOffice Module sw (master)  1
navmgr.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 <navmgr.hxx>
11 #include <wrtsh.hxx>
12 #include <sfx2/bindings.hxx>
13 #include <sfx2/viewfrm.hxx>
14 #include <vcl/svapp.hxx>
15 #include <cmdid.h>
16 #include <view.hxx>
17 #include <doc.hxx>
18 #include <unocrsr.hxx>
19 
20 // This method positions the cursor to the position rPos.
21 
23 
24  // EnterStdMode() prevents the cursor to 'block' the current
25  // shell when it should move from the image back to the normal shell
28  // cursor consists of two SwPositions: Point and Mark.
29  // Such a pair is called a PaM. SwPaM is derived from SwRing.
30  // The Ring contains the single regions of a multi-selection.
31  SwPaM* pPaM = m_rMyShell.GetCursor();
32 
33  if(pPaM->HasMark())
34  pPaM->DeleteMark(); // If there was a selection, get rid of it
35  *pPaM->GetPoint() = rPos; // Position Cursor
36 
38 }
39 
40 // Ctor for the SwNavigationMgr class
41 // Sets the shell to the current shell
42 // and the index of the current position to 0
43 
45  : m_nCurrent(0), m_rMyShell(rShell)
46 {
47 }
48 
50 {
52  for (auto & it : m_entries)
53  {
54  EndListening(it->m_aNotifier);
55  }
56  m_entries.clear();
57 }
58 
60 {
61  // our cursors may now spontaneously self-destruct: remove from
62  // m_entries if that happens
63  if (typeid(rHint) == typeid(sw::UnoCursorHint))
64  {
65  auto it = std::find_if(m_entries.begin(), m_entries.end(),
66  [&rBC](const sw::UnoCursorPointer& rItem) { return !rItem || &rBC == &rItem->m_aNotifier; });
67  if (it != m_entries.end())
68  {
69  EndListening(rBC);
70  m_entries.erase(it);
71  }
72  }
73 }
74 
75 // This method is used by the navigation shell - defined in sw/source/uibase/inc/navsh.hxx
76 // and implemented in sw/source/uibase/shells/navsh.cxx
77 // It is called when we want to check if the back button should be enabled or not.
78 // The back button should be enabled only if there are some entries in the navigation history
79 
81  return (m_nCurrent > 0);
82 }
83 
84 // Similar to backEnabled() method.
85 // The forward button should be enabled if we ever clicked back
86 // Due to the implementation of the navigation class, this is when the
87 // current position within the navigation history entries in not the last one
88 // i.e. when the m_nCurrent index is not at the end of the m_entries vector
89 
91  return m_nCurrent+1 < m_entries.size();
92 }
93 
94 // The goBack() method positions the cursor to the previous entry in the navigation history
95 // If there was no history to go forward to, it adds the current position of the cursor
96 // to the history so we could go forward to where we came from
97 
99 
100  // Although the button should be disabled whenever the backEnabled() returns false,
101  // the UI is sometimes not as responsive as we would like it to be :)
102  // this check prevents segmentation faults and in this way the class is not relying on the UI
103 
104  if (!backEnabled()) return;
105 
106  /* Trying to get the current cursor */
107  SwPaM* pPaM = m_rMyShell.GetCursor();
108  if (!pPaM) {
109  return;
110  }
111  // This flag will be used to manually refresh the buttons
112 
113  bool bForwardWasDisabled = !forwardEnabled();
114 
115  // If we're going backwards in our history, but the current location is not
116  // in the history then we need to add *here* to it so that we can "go
117  // forward" to here again.
118 
119  if (bForwardWasDisabled) {
120 
121  // the cursor consists of two SwPositions: Point and Mark.
122  // We are adding the current Point to the navigation history
123  // so we could later navigate forward to it
124 
125  // The addEntry() method returns true iff we should decrement
126  // the index before navigating back
127 
128  if (addEntry(*pPaM->GetPoint()) ) {
129  m_nCurrent--;
130  }
131  }
132  m_nCurrent--;
133  // Position cursor to appropriate navigation history entry
134  GotoSwPosition(*m_entries[m_nCurrent]->GetPoint());
135  // Refresh the buttons
136  if (bForwardWasDisabled)
138  if (!backEnabled())
140 }
141 
142 // The goForward() method positions the cursor to the next entry in the navigation history
143 
145 
146  // Although the button should be disabled whenever the backForward() returns false,
147  // the UI is sometimes not as responsive as we would like it to be :)
148  // this check prevents segmentation faults and in this way the class is not relying on the UI
149 
150  if (!forwardEnabled()) return;
151 
152  // This flag will be used to manually refresh the buttons
153  bool bBackWasDisabled = !backEnabled();
154  // The current index is positioned at the current entry in the navigation history
155  // We have to increment it to go to the next entry
156  m_nCurrent++;
157  GotoSwPosition(*m_entries[m_nCurrent]->GetPoint());
158  // Refresh the buttons
159  if (bBackWasDisabled)
161  if (!forwardEnabled())
163 }
164 
165 // This method adds the SwPosition rPos to the navigation history
166 // rPos is usually the current position of the cursor in the document
167 
169 
170  // Flags that will be used for refreshing the buttons
171  bool bBackWasDisabled = !backEnabled();
172  bool bForwardWasEnabled = forwardEnabled();
173 
174  bool bRet = false; // return value of the function.
175  // Indicates whether the index should be decremented before
176  // jumping back or not
177  // The navigation history has recency with temporal ordering enhancement,
178  // as described on http://zing.ncsl.nist.gov/hfweb/proceedings/greenberg/
179  // If any forward history exists, twist the tail of the
180  // list from the current position to the end
181  if (bForwardWasEnabled) {
182 
183  size_t number_ofm_entries = m_entries.size(); // To avoid calling m_entries.size() multiple times
184  int curr = m_nCurrent; // Index from which we'll twist the tail.
185  int n = (number_ofm_entries - curr) / 2; // Number of entries that will swap places
186  for (int i = 0; i < n; i++) {
187  std::swap(m_entries[curr + i], m_entries[number_ofm_entries -1 - i]);
188  }
189 
190  if (*m_entries.back()->GetPoint() != rPos)
191  {
193  StartListening(pCursor->m_aNotifier);
194  m_entries.push_back(pCursor);
195  }
196  bRet = true;
197  }
198  else {
199  if ( (!m_entries.empty() && *m_entries.back()->GetPoint() != rPos) || m_entries.empty() ) {
201  StartListening(pCursor->m_aNotifier);
202  m_entries.push_back(pCursor);
203  bRet = true;
204  }
205  if (m_entries.size() > 1 && *m_entries.back()->GetPoint() == rPos)
206  bRet = true;
207  if (m_entries.size() == 1 && *m_entries.back()->GetPoint() == rPos)
208  bRet = false;
209  }
210  m_nCurrent = m_entries.size();
211 
212  // Refresh buttons
213  if (bBackWasDisabled)
215  if (bForwardWasEnabled)
217 
218  return bRet;
219 }
220 
221 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SfxViewFrame * GetViewFrame() const
std::shared_ptr< SwUnoCursor > CreateUnoCursor(const SwPosition &rPos, bool bTableCursor=false)
Definition: doc.cxx:1775
void DeleteMark()
Definition: pam.hxx:178
Marks a position in the document model.
Definition: pam.hxx:36
bool forwardEnabled()
Definition: navmgr.cxx:90
#define FN_NAVIGATION_FORWARD
Definition: cmdid.h:627
sal_Int64 n
bool addEntry(const SwPosition &rPos)
Definition: navmgr.cxx:168
void EnterStdMode()
Definition: select.cxx:551
void Invalidate(sal_uInt16 nId)
void EndAllAction()
Definition: edws.cxx:97
Used by the UI to modify the document model.
Definition: wrtsh.hxx:96
void goBack()
Definition: navmgr.cxx:98
const SwView & GetView() const
Definition: wrtsh.hxx:437
Stack_t::size_type m_nCurrent
Definition: navmgr.hxx:34
SwDoc * GetDoc() const
Definition: viewsh.hxx:282
void GotoSwPosition(const SwPosition &rPos)
Definition: navmgr.cxx:22
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:137
Stack_t m_entries
Definition: navmgr.hxx:33
void goForward()
Definition: navmgr.cxx:144
int i
bool backEnabled()
Definition: navmgr.cxx:80
const SwPosition * GetPoint() const
Definition: pam.hxx:208
SwNavigationMgr(SwWrtShell &rShell)
Definition: navmgr.cxx:44
SfxBindings & GetBindings()
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:206
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:195
SwWrtShell & m_rMyShell
Definition: navmgr.hxx:35
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
#define FN_NAVIGATION_BACK
Definition: cmdid.h:626
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: navmgr.cxx:59
~SwNavigationMgr() override
Definition: navmgr.cxx:49
void StartAllAction()
For all views of this document.
Definition: edws.cxx:86