Line data Source code
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 <cmdid.h>
15 : #include <view.hxx>
16 : #include <doc.hxx>
17 : #include <unocrsr.hxx>
18 :
19 : #include <com/sun/star/frame/XLayoutManager.hpp>
20 :
21 : // This method positions the cursor to the position rPos.
22 :
23 0 : void SwNavigationMgr::GotoSwPosition(const SwPosition &rPos) {
24 : // EnterStdMode() prevents the cursor to 'block' the current
25 : // shell when it should move from the image back to the normal shell
26 0 : m_rMyShell.EnterStdMode();
27 0 : m_rMyShell.StartAllAction();
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 0 : SwPaM* pPaM = m_rMyShell.GetCrsr();
32 :
33 0 : if(pPaM->HasMark())
34 0 : pPaM->DeleteMark(); // If there was a selection, get rid of it
35 0 : *pPaM->GetPoint() = rPos; // Position Cursor
36 :
37 0 : m_rMyShell.EndAllAction();
38 0 : }
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 :
44 2761 : SwNavigationMgr::SwNavigationMgr(SwWrtShell & rShell)
45 2761 : : m_nCurrent(0), m_rMyShell(rShell)
46 : {
47 2761 : }
48 :
49 : // This method is used by the navigation shell - defined in sw/source/uibase/inc/navsh.hxx
50 : // and implemented in sw/source/uibase/shells/navsh.cxx
51 : // It is called when we want to check if the back button should be enabled or not.
52 : // The back button should be enabled only if there are some entries in the navigation history
53 :
54 28 : bool SwNavigationMgr::backEnabled() {
55 28 : return (m_nCurrent > 0);
56 : }
57 :
58 : // Similar to backEnabled() method.
59 : // The forward button should be enabled if we ever clicked back
60 : // Due to the implementation of the navigation class, this is when the
61 : // current position within the navigation history entries in not the last one
62 : // i.e. when the m_nCurrent index is not at the end of the m_entries vector
63 :
64 28 : bool SwNavigationMgr::forwardEnabled() {
65 28 : return m_nCurrent+1 < m_entries.size();
66 : }
67 :
68 : // The goBack() method positions the cursor to the previous entry in the navigation history
69 : // If there was no history to go forward to, it adds the current position of the cursor
70 : // to the history so we could go forward to where we came from
71 :
72 0 : void SwNavigationMgr::goBack() {
73 :
74 : // Although the button should be disabled whenever the backEnabled() returns false,
75 : // the UI is sometimes not as responsive as we would like it to be :)
76 : // this check prevents segmentation faults and in this way the class is not relying on the UI
77 :
78 0 : if (backEnabled()) {
79 : /* Trying to get the current cursor */
80 0 : SwPaM* pPaM = m_rMyShell.GetCrsr();
81 0 : if (!pPaM) {
82 0 : return;
83 : }
84 : // This flag will be used to manually refresh the buttons
85 :
86 0 : bool bForwardWasDisabled = !forwardEnabled();
87 :
88 : // If we're going backwards in our history, but the current location is not
89 : // in the history then we need to add *here* to it so that we can "go
90 : // forward" to here again.
91 :
92 0 : if (bForwardWasDisabled) {
93 :
94 : // the cursor consists of two SwPositions: Point and Mark.
95 : // We are adding the current Point to the navigation history
96 : // so we could later navigate forward to it
97 :
98 : // The addEntry() method returns true iff we should decrement
99 : // the index before navigating back
100 :
101 0 : if (addEntry(*pPaM->GetPoint()) ) {
102 0 : m_nCurrent--;
103 : }
104 : }
105 0 : m_nCurrent--;
106 : // Position cursor to appropriate navigation history entry
107 0 : GotoSwPosition(*m_entries[m_nCurrent]->GetPoint());
108 : // Refresh the buttons
109 0 : if (bForwardWasDisabled)
110 0 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
111 0 : if (!backEnabled())
112 0 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK);
113 : }
114 : }
115 :
116 : // The goForward() method positions the cursor to the next entry in the navigation history
117 :
118 0 : void SwNavigationMgr::goForward() {
119 :
120 : // Although the button should be disabled whenever the backForward() returns false,
121 : // the UI is sometimes not as responsive as we would like it to be :)
122 : // this check prevents segmentation faults and in this way the class is not relying on the UI
123 :
124 0 : if (forwardEnabled()) {
125 : // This flag will be used to manually refresh the buttons
126 0 : bool bBackWasDisabled = !backEnabled();
127 : // The current index is positioned at the current entry in the navigation history
128 : // We have to increment it to go to the next entry
129 0 : m_nCurrent++;
130 0 : GotoSwPosition(*m_entries[m_nCurrent]->GetPoint());
131 : // Refresh the buttons
132 0 : if (bBackWasDisabled)
133 0 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK);
134 0 : if (!forwardEnabled())
135 0 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
136 : }
137 0 : }
138 :
139 : // This method adds the SwPosition rPos to the navigation history
140 : // rPos is usually the current position of the cursor in the document
141 :
142 28 : bool SwNavigationMgr::addEntry(const SwPosition& rPos) {
143 : // Flags that will be used for refreshing the buttons
144 28 : bool bBackWasDisabled = !backEnabled();
145 28 : bool bForwardWasEnabled = forwardEnabled();
146 :
147 28 : bool bRet = false; // return value of the function.
148 : // Indicates whether the index should be decremented before
149 : // jumping back or not
150 : // The navigation history has recency with temporal ordering enhancement,
151 : // as described on http://zing.ncsl.nist.gov/hfweb/proceedings/greenberg/
152 : // If any forward history exists, twist the tail of the
153 : // list from the current position to the end
154 28 : if (bForwardWasEnabled) {
155 :
156 0 : size_t number_ofm_entries = m_entries.size(); // To avoid calling m_entries.size() multiple times
157 0 : int curr = m_nCurrent; // Index from which we'll twist the tail.
158 0 : int n = (number_ofm_entries - curr) / 2; // Number of entries that will swap places
159 0 : for (int i = 0; i < n; i++) {
160 0 : ::std::swap(m_entries[curr + i], m_entries[number_ofm_entries -1 - i]);
161 : }
162 :
163 0 : if (*m_entries.back()->GetPoint() != rPos)
164 : {
165 0 : sw::UnoCursorPointer pCursor(m_rMyShell.GetDoc()->CreateUnoCrsr(rPos));
166 0 : m_entries.push_back(pCursor);
167 : }
168 0 : bRet = true;
169 : }
170 : else {
171 28 : if ( (!m_entries.empty() && *m_entries.back()->GetPoint() != rPos) || m_entries.empty() ) {
172 10 : sw::UnoCursorPointer pCursor(m_rMyShell.GetDoc()->CreateUnoCrsr(rPos));
173 10 : m_entries.push_back(pCursor);
174 10 : bRet = true;
175 : }
176 28 : if (m_entries.size() > 1 && *m_entries.back()->GetPoint() == rPos)
177 6 : bRet = true;
178 28 : if (m_entries.size() == 1 && *m_entries.back()->GetPoint() == rPos)
179 22 : bRet = false;
180 : }
181 28 : m_nCurrent = m_entries.size();
182 :
183 : // Refresh buttons
184 28 : if (bBackWasDisabled)
185 4 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK);
186 28 : if (bForwardWasEnabled)
187 0 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
188 :
189 : // show the Navigation toolbar
190 : css::uno::Reference< css::frame::XFrame > xFrame =
191 28 : m_rMyShell.GetView().GetViewFrame()->GetFrame().GetFrameInterface();
192 28 : if (xFrame.is())
193 : {
194 28 : css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY);
195 28 : if (xPropSet.is())
196 : {
197 28 : css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
198 56 : css::uno::Any aValue = xPropSet->getPropertyValue("LayoutManager");
199 :
200 28 : aValue >>= xLayoutManager;
201 28 : if (xLayoutManager.is())
202 : {
203 28 : const OUString sResourceURL( "private:resource/toolbar/navigationobjectbar" );
204 56 : css::uno::Reference< css::ui::XUIElement > xUIElement = xLayoutManager->getElement(sResourceURL);
205 28 : if (!xUIElement.is())
206 : {
207 4 : xLayoutManager->createElement( sResourceURL );
208 4 : xLayoutManager->showElement( sResourceURL );
209 28 : }
210 28 : }
211 28 : }
212 : }
213 :
214 28 : return bRet;
215 177 : }
216 :
217 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|