nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / uibase / wrtsh / navmgr.cxx
blobb123408b820e286694621097bfe0d13a9771bab8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
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>
20 #include <com/sun/star/frame/XLayoutManager.hpp>
21 #include <com/sun/star/beans/XPropertySet.hpp>
23 // This method positions the cursor to the position rPos.
25 void SwNavigationMgr::GotoSwPosition(const SwPosition &rPos) {
26 // EnterStdMode() prevents the cursor to 'block' the current
27 // shell when it should move from the image back to the normal shell
28 m_rMyShell.EnterStdMode();
29 m_rMyShell.StartAllAction();
30 // cursor consists of two SwPositions: Point and Mark.
31 // Such a pair is called a PaM. SwPaM is derived from SwRing.
32 // The Ring contains the single regions of a multi-selection.
33 SwPaM* pPaM = m_rMyShell.GetCursor();
35 if(pPaM->HasMark())
36 pPaM->DeleteMark(); // If there was a selection, get rid of it
37 *pPaM->GetPoint() = rPos; // Position Cursor
39 m_rMyShell.EndAllAction();
42 // Ctor for the SwNavigationMgr class
43 // Sets the shell to the current shell
44 // and the index of the current position to 0
46 SwNavigationMgr::SwNavigationMgr(SwWrtShell & rShell)
47 : m_nCurrent(0), m_rMyShell(rShell)
51 SwNavigationMgr::~SwNavigationMgr()
53 SolarMutexGuard g;
54 for (auto & it : m_entries)
56 EndListening(it->m_aNotifier);
58 m_entries.clear();
61 void SwNavigationMgr::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
63 // our cursors may now spontaneously self-destruct: remove from
64 // m_entries if that happens
65 if (typeid(rHint) == typeid(sw::UnoCursorHint))
67 auto it = std::find_if(m_entries.begin(), m_entries.end(),
68 [&rBC](const sw::UnoCursorPointer& rItem) { return !rItem || &rBC == &rItem->m_aNotifier; });
69 if (it != m_entries.end())
71 EndListening(rBC);
72 m_entries.erase(it);
77 // This method is used by the navigation shell - defined in sw/source/uibase/inc/navsh.hxx
78 // and implemented in sw/source/uibase/shells/navsh.cxx
79 // It is called when we want to check if the back button should be enabled or not.
80 // The back button should be enabled only if there are some entries in the navigation history
82 bool SwNavigationMgr::backEnabled() {
83 return (m_nCurrent > 0);
86 // Similar to backEnabled() method.
87 // The forward button should be enabled if we ever clicked back
88 // Due to the implementation of the navigation class, this is when the
89 // current position within the navigation history entries in not the last one
90 // i.e. when the m_nCurrent index is not at the end of the m_entries vector
92 bool SwNavigationMgr::forwardEnabled() {
93 return m_nCurrent+1 < m_entries.size();
96 // The goBack() method positions the cursor to the previous entry in the navigation history
97 // If there was no history to go forward to, it adds the current position of the cursor
98 // to the history so we could go forward to where we came from
100 void SwNavigationMgr::goBack() {
102 // Although the button should be disabled whenever the backEnabled() returns false,
103 // the UI is sometimes not as responsive as we would like it to be :)
104 // this check prevents segmentation faults and in this way the class is not relying on the UI
106 if (!backEnabled()) return;
108 /* Trying to get the current cursor */
109 SwPaM* pPaM = m_rMyShell.GetCursor();
110 if (!pPaM) {
111 return;
113 // This flag will be used to manually refresh the buttons
115 bool bForwardWasDisabled = !forwardEnabled();
117 // If we're going backwards in our history, but the current location is not
118 // in the history then we need to add *here* to it so that we can "go
119 // forward" to here again.
121 if (bForwardWasDisabled) {
123 // the cursor consists of two SwPositions: Point and Mark.
124 // We are adding the current Point to the navigation history
125 // so we could later navigate forward to it
127 // The addEntry() method returns true iff we should decrement
128 // the index before navigating back
130 if (addEntry(*pPaM->GetPoint()) ) {
131 m_nCurrent--;
134 m_nCurrent--;
135 // Position cursor to appropriate navigation history entry
136 GotoSwPosition(*m_entries[m_nCurrent]->GetPoint());
137 // Refresh the buttons
138 if (bForwardWasDisabled)
139 m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
140 if (!backEnabled())
141 m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK);
144 // The goForward() method positions the cursor to the next entry in the navigation history
146 void SwNavigationMgr::goForward() {
148 // Although the button should be disabled whenever the backForward() returns false,
149 // the UI is sometimes not as responsive as we would like it to be :)
150 // this check prevents segmentation faults and in this way the class is not relying on the UI
152 if (!forwardEnabled()) return;
154 // This flag will be used to manually refresh the buttons
155 bool bBackWasDisabled = !backEnabled();
156 // The current index is positioned at the current entry in the navigation history
157 // We have to increment it to go to the next entry
158 m_nCurrent++;
159 GotoSwPosition(*m_entries[m_nCurrent]->GetPoint());
160 // Refresh the buttons
161 if (bBackWasDisabled)
162 m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK);
163 if (!forwardEnabled())
164 m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
167 // This method adds the SwPosition rPos to the navigation history
168 // rPos is usually the current position of the cursor in the document
170 bool SwNavigationMgr::addEntry(const SwPosition& rPos) {
171 // Flags that will be used for refreshing the buttons
172 bool bBackWasDisabled = !backEnabled();
173 bool bForwardWasEnabled = forwardEnabled();
175 bool bRet = false; // return value of the function.
176 // Indicates whether the index should be decremented before
177 // jumping back or not
178 // The navigation history has recency with temporal ordering enhancement,
179 // as described on http://zing.ncsl.nist.gov/hfweb/proceedings/greenberg/
180 // If any forward history exists, twist the tail of the
181 // list from the current position to the end
182 if (bForwardWasEnabled) {
184 size_t number_ofm_entries = m_entries.size(); // To avoid calling m_entries.size() multiple times
185 int curr = m_nCurrent; // Index from which we'll twist the tail.
186 int n = (number_ofm_entries - curr) / 2; // Number of entries that will swap places
187 for (int i = 0; i < n; i++) {
188 std::swap(m_entries[curr + i], m_entries[number_ofm_entries -1 - i]);
191 if (*m_entries.back()->GetPoint() != rPos)
193 sw::UnoCursorPointer pCursor(m_rMyShell.GetDoc()->CreateUnoCursor(rPos));
194 StartListening(pCursor->m_aNotifier);
195 m_entries.push_back(pCursor);
197 bRet = true;
199 else {
200 if ( (!m_entries.empty() && *m_entries.back()->GetPoint() != rPos) || m_entries.empty() ) {
201 sw::UnoCursorPointer pCursor(m_rMyShell.GetDoc()->CreateUnoCursor(rPos));
202 StartListening(pCursor->m_aNotifier);
203 m_entries.push_back(pCursor);
204 bRet = true;
206 if (m_entries.size() > 1 && *m_entries.back()->GetPoint() == rPos)
207 bRet = true;
208 if (m_entries.size() == 1 && *m_entries.back()->GetPoint() == rPos)
209 bRet = false;
211 m_nCurrent = m_entries.size();
213 // Refresh buttons
214 if (bBackWasDisabled)
215 m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK);
216 if (bForwardWasEnabled)
217 m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
219 // show the Navigation toolbar
220 css::uno::Reference< css::frame::XFrame > xFrame =
221 m_rMyShell.GetView().GetViewFrame()->GetFrame().GetFrameInterface();
222 if (xFrame.is())
224 css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY);
225 if (xPropSet.is())
227 css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
228 css::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
230 aValue >>= xLayoutManager;
231 if (xLayoutManager.is())
233 const OUString sResourceURL( "private:resource/toolbar/navigationobjectbar" );
234 css::uno::Reference< css::ui::XUIElement > xUIElement = xLayoutManager->getElement(sResourceURL);
235 if (!xUIElement.is())
237 xLayoutManager->createElement( sResourceURL );
238 xLayoutManager->showElement( sResourceURL );
244 return bRet;
247 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */