1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
12 #include <sfx2/bindings.hxx>
13 #include <sfx2/viewfrm.hxx>
17 #include <unocrsr.hxx>
19 #include <com/sun/star/frame/XLayoutManager.hpp>
22 * If SMART is defined, the navigation history has recency with temporal ordering enhancement,
23 * as described on http://zing.ncsl.nist.gov/hfweb/proceedings/greenberg/
28 // This method positions the cursor to the position rPos.
30 void SwNavigationMgr::GotoSwPosition(const SwPosition
&rPos
) {
31 // EnterStdMode() prevents the cursor to 'block' the current
32 // shell when it should move from the image back to the normal shell
33 m_rMyShell
.EnterStdMode();
34 m_rMyShell
.StartAllAction();
35 // cursor consists of two SwPositions: Point and Mark.
36 // Such a pair is called a PaM. SwPaM is derived from SwRing.
37 // The Ring contains the single regions of a multi-selection.
38 SwPaM
* pPaM
= m_rMyShell
.GetCrsr();
41 pPaM
->DeleteMark(); // If there was a selection, get rid of it
42 *pPaM
->GetPoint() = rPos
; // Position Cursor
44 m_rMyShell
.EndAllAction();
47 // Ctor for the SwNavigationMgr class
48 // Sets the shell to the current shell
49 // and the index of the current position to 0
51 SwNavigationMgr::SwNavigationMgr(SwWrtShell
& rShell
)
52 : m_nCurrent(0), m_rMyShell(rShell
)
56 // This method is used by the navigation shell - defined in sw/source/ui/inc/navsh.hxx
57 // and implemented in sw/source/ui/shells/navsh.cxx
58 // It is called when we want to check if the back button should be enabled or not.
59 // The back button should be enabled only if there are some entries in the navigation history
61 bool SwNavigationMgr::backEnabled() {
62 return (m_nCurrent
> 0);
65 // Similar to backEnabled() method.
66 // The forward button should be enabled if we ever clicked back
67 // Due to the implementation of the navigation class, this is when the
68 // current position within the navigation history entries in not the last one
69 // i.e. when the m_nCurrent index is not at the end of the m_entries vector
71 bool SwNavigationMgr::forwardEnabled() {
72 return m_nCurrent
+1 < m_entries
.size();
75 // The goBack() method positions the cursor to the previous entry in the navigation history
76 // If there was no history to go forward to, it adds the current position of the cursor
77 // to the history so we could go forward to where we came from
79 void SwNavigationMgr::goBack() {
81 // Although the button should be disabled whenever the backEnabled() returns false,
82 // the UI is sometimes not as responsive as we would like it to be :)
83 // this check prevents segmentation faults and in this way the class is not relying on the UI
86 /* Trying to get the current cursor */
87 SwPaM
* pPaM
= m_rMyShell
.GetCrsr();
91 // This flag will be used to manually refresh the buttons
93 bool bForwardWasDisabled
= !forwardEnabled();
95 // If we're going backwards in our history, but the current location is not
96 // in the history then we need to add *here* to it so that we can "go
97 // forward" to here again.
99 if (bForwardWasDisabled
) {
101 // the cursor consists of two SwPositions: Point and Mark.
102 // We are adding the current Point to the navigation history
103 // so we could later navigate forward to it
105 // The addEntry() method returns true iff we should decrement
106 // the index before navigating back
108 if (addEntry(*pPaM
->GetPoint()) ) {
113 // Position cursor to appropriate navigation history entry
114 GotoSwPosition(*m_entries
[m_nCurrent
]->GetPoint());
115 // Refresh the buttons
116 if (bForwardWasDisabled
)
117 m_rMyShell
.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD
);
119 m_rMyShell
.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK
);
123 // The goForward() method positions the cursor to the next entry in the navigation history
125 void SwNavigationMgr::goForward() {
127 // Although the button should be disabled whenever the backForward() returns false,
128 // the UI is sometimes not as responsive as we would like it to be :)
129 // this check prevents segmentation faults and in this way the class is not relying on the UI
131 if (forwardEnabled()) {
132 // This flag will be used to manually refresh the buttons
133 bool bBackWasDisabled
= !backEnabled();
134 // The current index is positioned at the current entry in the navigation history
135 // We have to increment it to go to the next entry
137 GotoSwPosition(*m_entries
[m_nCurrent
]->GetPoint());
138 // Refresh the buttons
139 if (bBackWasDisabled
)
140 m_rMyShell
.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK
);
141 if (!forwardEnabled())
142 m_rMyShell
.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD
);
146 // This method adds the SwPosition rPos to the navigation history
147 // rPos is usually the current position of the cursor in the document
149 bool SwNavigationMgr::addEntry(const SwPosition
& rPos
) {
150 // Flags that will be used for refreshing the buttons
151 bool bBackWasDisabled
= !backEnabled();
152 bool bForwardWasEnabled
= forwardEnabled();
154 bool bRet
= false; // return value of the function.
155 // Indicates whether the index should be decremented before
156 // jumping back or not
158 // If any forward history exists, twist the tail of the
159 // list from the current position to the end
160 if (bForwardWasEnabled
) {
162 size_t number_ofm_entries
= m_entries
.size(); // To avoid calling m_entries.size() multiple times
163 int curr
= m_nCurrent
; // Index from which we'll twist the tail.
164 int n
= (number_ofm_entries
- curr
) / 2; // Number of entries that will swap places
165 for (int i
= 0; i
< n
; i
++) {
166 ::std::swap(m_entries
[curr
+ i
], m_entries
[number_ofm_entries
-1 - i
]);
169 if (*m_entries
.back()->GetPoint() != rPos
)
171 SwUnoCrsr
*const pCursor
= m_rMyShell
.GetDoc()->CreateUnoCrsr(rPos
);
172 m_entries
.push_back(::boost::shared_ptr
<SwUnoCrsr
>(pCursor
));
177 if ( (!m_entries
.empty() && *m_entries
.back()->GetPoint() != rPos
) || m_entries
.empty() ) {
178 SwUnoCrsr
*const pCursor
= m_rMyShell
.GetDoc()->CreateUnoCrsr(rPos
);
179 m_entries
.push_back(::boost::shared_ptr
<SwUnoCrsr
>(pCursor
));
182 if (m_entries
.size() > 1 && *m_entries
.back()->GetPoint() == rPos
)
184 if (m_entries
.size() == 1 && *m_entries
.back()->GetPoint() == rPos
)
188 m_entries
.erase(m_entries
.begin() + m_nCurrent
, m_entries
.end());
189 SwUnoCrsr
*const pCursor
= m_rMyShell
.GetDoc()->CreateUnoCrsr(rPos
);
190 m_entries
.push_back(::boost::shared_ptr
<SwUnoCrsr
>(pCursor
));
193 m_nCurrent
= m_entries
.size();
196 if (bBackWasDisabled
)
197 m_rMyShell
.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_BACK
);
198 if (bForwardWasEnabled
)
199 m_rMyShell
.GetView().GetViewFrame()->GetBindings().Invalidate(FN_NAVIGATION_FORWARD
);
201 // show the Navigation toolbar
202 css::uno::Reference
< css::frame::XFrame
> xFrame
=
203 m_rMyShell
.GetView().GetViewFrame()->GetFrame().GetFrameInterface();
206 css::uno::Reference
< css::beans::XPropertySet
> xPropSet(xFrame
, css::uno::UNO_QUERY
);
209 css::uno::Reference
< css::frame::XLayoutManager
> xLayoutManager
;
210 css::uno::Any aValue
= xPropSet
->getPropertyValue( OUString( "LayoutManager" ) );
212 aValue
>>= xLayoutManager
;
213 if (xLayoutManager
.is())
215 const OUString
sResourceURL( "private:resource/toolbar/navigationobjectbar" );
216 css::uno::Reference
< css::ui::XUIElement
> xUIElement
= xLayoutManager
->getElement(sResourceURL
);
217 if (!xUIElement
.is())
219 xLayoutManager
->createElement( sResourceURL
);
220 xLayoutManager
->showElement( sResourceURL
);
228 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */