Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : : *
5 : : * The contents of this file are subject to the Mozilla Public License Version
6 : : * 1.1 (the "License"); you may not use this file except in compliance with
7 : : * the License. You may obtain a copy of the License at
8 : : * http://www.mozilla.org/MPL/
9 : : *
10 : : * Software distributed under the License is distributed on an "AS IS" basis,
11 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : : * for the specific language governing rights and limitations under the
13 : : * License.
14 : : *
15 : : * The Initial Developer of the Original Code is
16 : : * [ Maja Djordjevic < ovcica@gmail.com > ]
17 : : * Portions created by the Initial Developer are Copyright (C) 2010 the
18 : : * Initial Developer. All Rights Reserved.
19 : : *
20 : : * Contributor(s): Cédric Bosdonnat <cbosdonnat@novell.com>
21 : : * Caolan McNamara <caolanm@redhat.com>
22 : : *
23 : : * Alternatively, the contents of this file may be used under the terms of
24 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
25 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
26 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
27 : : * instead of those above.
28 : : */
29 : :
30 : : #include "navmgr.hxx"
31 : : #include "wrtsh.hxx"
32 : : #include <sfx2/bindings.hxx>
33 : : #include <sfx2/viewfrm.hxx>
34 : : #include <cmdid.h>
35 : : #include <view.hxx>
36 : : #include <doc.hxx>
37 : : #include <unocrsr.hxx>
38 : :
39 : : #include <com/sun/star/frame/XLayoutManager.hpp>
40 : :
41 : : namespace css = ::com::sun::star;
42 : :
43 : : /**
44 : : * If SMART is defined, the navigation history has recency with temporal ordering enhancement,
45 : : * as described on http://zing.ncsl.nist.gov/hfweb/proceedings/greenberg/
46 : : */
47 : : #define SMART 1
48 : :
49 : : /*
50 : : * This method positions the cursor to the position rPos
51 : : */
52 : 0 : void SwNavigationMgr::GotoSwPosition(const SwPosition &rPos) {
53 : : /* EnterStdMode() prevents the cursor to 'block' the current shell when it should move from the image back to the normal shell */
54 : 0 : m_rMyShell.EnterStdMode();
55 : 0 : m_rMyShell.StartAllAction();
56 : : /*
57 : : * cursor consists of two SwPositions: Point and Mark.
58 : : * Such a pair is called a PaM. SwPaM is derived from SwRing.
59 : : * The Ring contains the single regions of a multi-selection.
60 : : */
61 : 0 : SwPaM* pPaM = m_rMyShell.GetCrsr();
62 : :
63 [ # # ]: 0 : if(pPaM->HasMark())
64 : 0 : pPaM->DeleteMark(); // If there was a selection, get rid of it
65 : 0 : *pPaM->GetPoint() = rPos; // Position Cursor
66 : :
67 : 0 : m_rMyShell.EndAllAction();
68 : 0 : }
69 : : /*
70 : : * Ctor for the SwNavigationMgr class
71 : : * Sets the shell to the current shell
72 : : * and the index of the current position to 0
73 : : */
74 : 1318 : SwNavigationMgr::SwNavigationMgr(SwWrtShell & rShell)
75 : 1318 : : m_nCurrent(0), m_rMyShell(rShell)
76 : : {
77 : 1318 : }
78 : :
79 : : /*
80 : : * This method is used by the navigation shell - defined in sw/source/ui/inc/navsh.hxx
81 : : * and implemented in sw/source/ui/shells/navsh.cxx
82 : : * It is called when we want to check if the back button should be enabled or not.
83 : : * The back button should be enabled only if there are some entries in the navigation history
84 : : */
85 : 3 : sal_Bool SwNavigationMgr::backEnabled() {
86 : 3 : return (m_nCurrent > 0);
87 : : }
88 : : /*
89 : : * Similar to backEnabled() method.
90 : : * The forward button should be enabled if we ever clicked back
91 : : * Due to the implementation of the navigation class, this is when the
92 : : * current position within the navigation history entries in not the last one
93 : : * i.e. when the m_nCurrent index is not at the end of the m_entries vector
94 : : */
95 : 3 : sal_Bool SwNavigationMgr::forwardEnabled() {
96 : 3 : return m_nCurrent+1 < m_entries.size();
97 : : }
98 : :
99 : :
100 : : /*
101 : : * The goBack() method positions the cursor to the previous entry in the navigation history
102 : : * If there was no history to go forward to, it adds the current position of the cursor
103 : : * to the history so we could go forward to where we came from
104 : : */
105 : 0 : void SwNavigationMgr::goBack() {
106 : : /*
107 : : * Although the button should be disabled whenever the backEnabled() returns false,
108 : : * the UI is sometimes not as responsive as we would like it to be :)
109 : : * this check prevents segmentation faults and in this way the class is not relying on the UI
110 : : */
111 [ # # ]: 0 : if (backEnabled()) {
112 : : /* Trying to get the current cursor */
113 : 0 : SwPaM* pPaM = m_rMyShell.GetCrsr();
114 [ # # ]: 0 : if (!pPaM) {
115 : 0 : return;
116 : : }
117 : :
118 : : /* This flag will be used to manually refresh the buttons */
119 : 0 : bool bForwardWasDisabled = !forwardEnabled();
120 : : /*
121 : : * If we're going backwards in our history, but the current location is not
122 : : * in the history then we need to add *here* to it so that we can "go
123 : : * forward" to here again.
124 : : */
125 : :
126 [ # # ]: 0 : if (bForwardWasDisabled) {
127 : : /*
128 : : * the cursor consists of two SwPositions: Point and Mark.
129 : : * We are adding the current Point to the navigation history
130 : : * so we could later navigate forward to it
131 : : */
132 : : /* The addEntry() method returns true iff we should decrement the index before navigating back */
133 [ # # ]: 0 : if (addEntry(*pPaM->GetPoint()) ) {
134 : 0 : m_nCurrent--;
135 : : }
136 : : }
137 : 0 : m_nCurrent--;
138 : : /* Position cursor to appropriate navigation history entry */
139 : 0 : GotoSwPosition(*m_entries[m_nCurrent]->GetPoint());
140 : : /* Refresh the buttons */
141 [ # # ]: 0 : if (bForwardWasDisabled)
142 : 0 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
143 [ # # ]: 0 : if (!backEnabled())
144 : 0 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK);
145 : : }
146 : : }
147 : : /*
148 : : * The goForward() method positions the cursor to the next entry in the navigation history
149 : : */
150 : :
151 : 0 : void SwNavigationMgr::goForward() {
152 : : /*
153 : : * Although the button should be disabled whenever the backForward() returns false,
154 : : * the UI is sometimes not as responsive as we would like it to be :)
155 : : * this check prevents segmentation faults and in this way the class is not relying on the UI
156 : : */
157 : :
158 [ # # ]: 0 : if (forwardEnabled()) {
159 : : /* This flag will be used to manually refresh the buttons */
160 : 0 : bool bBackWasDisabled = !backEnabled();
161 : : /*
162 : : * The current index is positioned at the current entry in the navigation history
163 : : * We have to increment it to go to the next entry
164 : : */
165 : 0 : m_nCurrent++;
166 : 0 : GotoSwPosition(*m_entries[m_nCurrent]->GetPoint());
167 : : /* Refresh the buttons */
168 [ # # ]: 0 : if (bBackWasDisabled)
169 : 0 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK);
170 [ # # ]: 0 : if (!forwardEnabled())
171 : 0 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
172 : : }
173 : 0 : }
174 : : /*
175 : : * This method adds the SwPosition rPos to the navigation history
176 : : * rPos is usually the current position of the cursor in the document
177 : : */
178 : 2 : bool SwNavigationMgr::addEntry(const SwPosition& rPos) {
179 : : /* Flags that will be used for refreshing the buttons */
180 : 2 : bool bBackWasDisabled = !backEnabled();
181 : 2 : bool bForwardWasEnabled = forwardEnabled();
182 : :
183 : 2 : bool bRet = false; // return value of the function.
184 : : // Indicates whether the index should be decremented before jumping back or not
185 : : #if SMART
186 : : /* If any forward history exists, twist the tail of the list from the current position to the end */
187 [ - + ]: 2 : if (bForwardWasEnabled) {
188 : :
189 : 0 : size_t number_ofm_entries = m_entries.size(); /* To avoid calling m_entries.size() multiple times */
190 : 0 : int curr = m_nCurrent; /* Index from which we'll twist the tail. */
191 : 0 : int n = (number_ofm_entries - curr) / 2; /* Number of entries that will swap places */
192 [ # # ]: 0 : for (int i = 0; i < n; i++) {
193 [ # # ]: 0 : ::std::swap(m_entries[curr + i], m_entries[number_ofm_entries -1 - i]);
194 : : }
195 : :
196 [ # # ][ # # ]: 0 : if (*m_entries.back()->GetPoint() != rPos)
[ # # ]
197 : : {
198 [ # # ]: 0 : SwUnoCrsr *const pCursor = m_rMyShell.GetDoc()->CreateUnoCrsr(rPos);
199 [ # # ][ # # ]: 0 : m_entries.push_back(::boost::shared_ptr<SwUnoCrsr>(pCursor));
[ # # ]
200 : : }
201 : 0 : bRet = true;
202 : : }
203 : : else {
204 [ - + ][ # # ]: 2 : if ( (!m_entries.empty() && *m_entries.back()->GetPoint() != rPos) || m_entries.empty() ) {
[ # # ][ # # ]
[ + - ][ + - ]
205 [ + - ]: 2 : SwUnoCrsr *const pCursor = m_rMyShell.GetDoc()->CreateUnoCrsr(rPos);
206 [ + - ][ + - ]: 2 : m_entries.push_back(::boost::shared_ptr<SwUnoCrsr>(pCursor));
[ + - ]
207 : 2 : bRet = true;
208 : : }
209 [ - + ][ # # ]: 2 : if (m_entries.size() > 1 && *m_entries.back()->GetPoint() == rPos)
[ # # ][ # # ]
[ - + ]
210 : 0 : bRet = true;
211 [ + - ][ + - ]: 2 : if (m_entries.size() == 1 && *m_entries.back()->GetPoint() == rPos)
[ + - ][ + - ]
[ + - ]
212 : 2 : bRet = false;
213 : : }
214 : : #else
215 : : m_entries.erase(m_entries.begin() + m_nCurrent, m_entries.end());
216 : : SwUnoCrsr *const pCursor = m_rMyShell.GetDoc()->CreateUnoCrsr(rPos);
217 : : m_entries.push_back(::boost::shared_ptr<SwUnoCrsr>(pCursor));
218 : : bRet = true;
219 : : #endif
220 : 2 : m_nCurrent = m_entries.size();
221 : :
222 : : /* Refresh buttons */
223 [ + - ]: 2 : if (bBackWasDisabled)
224 [ + - ]: 2 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK);
225 [ - + ]: 2 : if (bForwardWasEnabled)
226 [ # # ]: 0 : m_rMyShell.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD);
227 : :
228 : : /* show the Navigation toolbar */
229 : : css::uno::Reference< css::frame::XFrame > xFrame =
230 [ + - ][ + - ]: 2 : m_rMyShell.GetView().GetViewFrame()->GetFrame().GetFrameInterface();
231 [ + - ]: 2 : if (xFrame.is())
232 : : {
233 [ + - ]: 2 : css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY);
234 [ + - ]: 2 : if (xPropSet.is())
235 : : {
236 : 2 : css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
237 [ + - ][ + - ]: 2 : css::uno::Any aValue = xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ) ) );
[ + - ]
238 : :
239 [ + - ]: 2 : aValue >>= xLayoutManager;
240 [ + - ]: 2 : if (xLayoutManager.is())
241 : : {
242 [ + - ]: 2 : const ::rtl::OUString sResourceURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/navigationobjectbar" ) );
243 [ + - ][ + - ]: 2 : css::uno::Reference< css::ui::XUIElement > xUIElement = xLayoutManager->getElement(sResourceURL);
244 [ + - ]: 2 : if (!xUIElement.is())
245 : : {
246 [ + - ][ + - ]: 2 : xLayoutManager->createElement( sResourceURL );
247 [ + - ][ + - ]: 2 : xLayoutManager->showElement( sResourceURL );
248 : 2 : }
249 : 2 : }
250 : 2 : }
251 : : }
252 : :
253 : 2 : return bRet;
254 : : }
255 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|