1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "precompiled_sd.hxx"
25 #include "controller/SlsFocusManager.hxx"
26
27 #include "SlideSorter.hxx"
28 #include "PaneDockingWindow.hxx"
29 #include "controller/SlideSorterController.hxx"
30 #include "controller/SlsCurrentSlideManager.hxx"
31 #include "controller/SlsVisibleAreaManager.hxx"
32 #include "model/SlideSorterModel.hxx"
33 #include "model/SlsPageDescriptor.hxx"
34 #include "view/SlideSorterView.hxx"
35 #include "view/SlsLayouter.hxx"
36 #include <vcl/toolbox.hxx>
37
38 #include "Window.hxx"
39 #include "sdpage.hxx"
40
41 #define UNIFY_FOCUS_AND_CURRENT_PAGE
42
43 namespace sd { namespace slidesorter { namespace controller {
44
FocusManager(SlideSorter & rSlideSorter)45 FocusManager::FocusManager (SlideSorter& rSlideSorter)
46 : mrSlideSorter(rSlideSorter),
47 mnPageIndex(0),
48 mbPageIsFocused(false),
49 mbIsVerticalWrapActive(false)
50 {
51 if (mrSlideSorter.GetModel().GetPageCount() > 0)
52 mnPageIndex = 0;
53 }
54
55
56
57
~FocusManager(void)58 FocusManager::~FocusManager (void)
59 {
60 }
61
62
63
64
MoveFocus(FocusMoveDirection eDirection)65 void FocusManager::MoveFocus (FocusMoveDirection eDirection)
66 {
67 if (mnPageIndex >= 0 && mbPageIsFocused)
68 {
69 HideFocusIndicator (GetFocusedPageDescriptor());
70
71 const sal_Int32 nColumnCount (mrSlideSorter.GetView().GetLayouter().GetColumnCount());
72 const sal_Int32 nPageCount (mrSlideSorter.GetModel().GetPageCount());
73 switch (eDirection)
74 {
75 case FMD_NONE:
76 // Nothing to be done.
77 break;
78
79 case FMD_LEFT:
80 if (mnPageIndex > 0)
81 mnPageIndex -= 1;
82 else if (mbIsVerticalWrapActive)
83 mnPageIndex = nPageCount-1;
84 break;
85
86 case FMD_RIGHT:
87 if (mnPageIndex < nPageCount-1)
88 mnPageIndex += 1;
89 else if (mbIsVerticalWrapActive)
90 mnPageIndex = 0;
91 break;
92
93 case FMD_UP:
94 {
95 const sal_Int32 nCandidate (mnPageIndex - nColumnCount);
96 if (nCandidate < 0)
97 {
98 if (mbIsVerticalWrapActive)
99 {
100 // Wrap around to the bottom row or the one above
101 // and go to the correct column.
102 const sal_Int32 nLastIndex (nPageCount-1);
103 const sal_Int32 nLastColumn (nLastIndex % nColumnCount);
104 const sal_Int32 nCurrentColumn (mnPageIndex%nColumnCount);
105 if (nLastColumn >= nCurrentColumn)
106 {
107 // The last row contains the current column.
108 mnPageIndex = nLastIndex - (nLastColumn-nCurrentColumn);
109 }
110 else
111 {
112 // Only the second to last row contains the current column.
113 mnPageIndex = nLastIndex - nLastColumn
114 - nColumnCount
115 + nCurrentColumn;
116 }
117 }
118 }
119 else
120 {
121 // Move the focus the previous row.
122 mnPageIndex = nCandidate;
123 }
124 }
125 break;
126
127 case FMD_DOWN:
128 {
129 const sal_Int32 nCandidate (mnPageIndex + nColumnCount);
130 if (nCandidate >= nPageCount)
131 {
132 if (mbIsVerticalWrapActive)
133 {
134 // Wrap around to the correct column.
135 mnPageIndex = mnPageIndex % nColumnCount;
136 }
137 else
138 {
139 // Do not move the focus.
140 }
141 }
142 else
143 {
144 // Move the focus to the next row.
145 mnPageIndex = nCandidate;
146 }
147 }
148 break;
149 }
150
151 if (mnPageIndex < 0)
152 {
153 OSL_ASSERT(mnPageIndex>=0);
154 mnPageIndex = 0;
155 }
156 else if (mnPageIndex >= nPageCount)
157 {
158 OSL_ASSERT(mnPageIndex<nPageCount);
159 mnPageIndex = nPageCount - 1;
160 }
161
162 if (mbPageIsFocused)
163 {
164 ShowFocusIndicator(GetFocusedPageDescriptor(), true);
165 }
166 }
167 }
168
169
170
171
ShowFocus(const bool bScrollToFocus)172 void FocusManager::ShowFocus (const bool bScrollToFocus)
173 {
174 mbPageIsFocused = true;
175 ShowFocusIndicator(GetFocusedPageDescriptor(), bScrollToFocus);
176 }
177
178
179
180
HideFocus(void)181 void FocusManager::HideFocus (void)
182 {
183 mbPageIsFocused = false;
184 HideFocusIndicator(GetFocusedPageDescriptor());
185 }
186
187
188
189
ToggleFocus(void)190 bool FocusManager::ToggleFocus (void)
191 {
192 if (mnPageIndex >= 0)
193 {
194 if (mbPageIsFocused)
195 HideFocus ();
196 else
197 ShowFocus ();
198 }
199 return mbPageIsFocused;
200 }
201
202
203
204
HasFocus(void) const205 bool FocusManager::HasFocus (void) const
206 {
207 return mrSlideSorter.GetContentWindow()->HasFocus();
208 }
209
210
211
212
GetFocusedPageDescriptor(void) const213 model::SharedPageDescriptor FocusManager::GetFocusedPageDescriptor (void) const
214 {
215 return mrSlideSorter.GetModel().GetPageDescriptor(mnPageIndex);
216 }
217
218
219
220
GetFocusedPageIndex(void) const221 sal_Int32 FocusManager::GetFocusedPageIndex (void) const
222 {
223 return mnPageIndex;
224 }
225
226
227
228 /*
229 void FocusManager::FocusPage (sal_Int32 nPageIndex)
230 {
231 if (nPageIndex != mnPageIndex)
232 {
233 // Hide the focus while switching it to the specified page.
234 FocusHider aHider (*this);
235 mnPageIndex = nPageIndex;
236 }
237
238 if (HasFocus() && !IsFocusShowing())
239 ShowFocus();
240 }
241 */
242
243
244
SetFocusedPage(const model::SharedPageDescriptor & rpDescriptor)245 void FocusManager::SetFocusedPage (const model::SharedPageDescriptor& rpDescriptor)
246 {
247 if (rpDescriptor.get() != NULL)
248 {
249 FocusHider aFocusHider (*this);
250 mnPageIndex = (rpDescriptor->GetPage()->GetPageNum()-1)/2;
251 }
252 }
253
254
255
256
SetFocusedPage(sal_Int32 nPageIndex)257 void FocusManager::SetFocusedPage (sal_Int32 nPageIndex)
258 {
259 FocusHider aFocusHider (*this);
260 mnPageIndex = nPageIndex;
261 }
262
263
264
265
SetFocusedPageToCurrentPage(void)266 void FocusManager::SetFocusedPageToCurrentPage (void)
267 {
268 SetFocusedPage(mrSlideSorter.GetController().GetCurrentSlideManager()->GetCurrentSlide());
269 }
270
271
272
273
IsFocusShowing(void) const274 bool FocusManager::IsFocusShowing (void) const
275 {
276 return HasFocus() && mbPageIsFocused;
277 }
278
279
280
281
HideFocusIndicator(const model::SharedPageDescriptor & rpDescriptor)282 void FocusManager::HideFocusIndicator (const model::SharedPageDescriptor& rpDescriptor)
283 {
284 if (rpDescriptor.get() != NULL)
285 {
286 mrSlideSorter.GetView().SetState(rpDescriptor, model::PageDescriptor::ST_Focused, false);
287
288 // Hide focus should also fire the focus event, Currently, only accessibility add the focus listener
289 NotifyFocusChangeListeners();
290 }
291 }
292
293
294
295
ShowFocusIndicator(const model::SharedPageDescriptor & rpDescriptor,const bool bScrollToFocus)296 void FocusManager::ShowFocusIndicator (
297 const model::SharedPageDescriptor& rpDescriptor,
298 const bool bScrollToFocus)
299 {
300 if (rpDescriptor.get() != NULL)
301 {
302 mrSlideSorter.GetView().SetState(rpDescriptor, model::PageDescriptor::ST_Focused, true);
303
304 if (bScrollToFocus)
305 {
306 // Scroll the focused page object into the visible area and repaint
307 // it, so that the focus indicator becomes visible.
308 mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor,true);
309 }
310 mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
311
312 NotifyFocusChangeListeners();
313 }
314 }
315
316
317
318
AddFocusChangeListener(const Link & rListener)319 void FocusManager::AddFocusChangeListener (const Link& rListener)
320 {
321 if (::std::find (maFocusChangeListeners.begin(), maFocusChangeListeners.end(), rListener)
322 == maFocusChangeListeners.end())
323 {
324 maFocusChangeListeners.push_back (rListener);
325 }
326 }
327
328
329
330
RemoveFocusChangeListener(const Link & rListener)331 void FocusManager::RemoveFocusChangeListener (const Link& rListener)
332 {
333 maFocusChangeListeners.erase (
334 ::std::find (maFocusChangeListeners.begin(), maFocusChangeListeners.end(), rListener));
335 }
336
337
338
339
SetFocusToToolBox(void)340 void FocusManager::SetFocusToToolBox (void)
341 {
342 HideFocus();
343
344 if (mrSlideSorter.GetViewShell() != NULL)
345 {
346 ::Window* pParentWindow = mrSlideSorter.GetViewShell()->GetParentWindow();
347 DockingWindow* pDockingWindow = NULL;
348 while (pParentWindow!=NULL && pDockingWindow==NULL)
349 {
350 pDockingWindow = dynamic_cast<DockingWindow*>(pParentWindow);
351 pParentWindow = pParentWindow->GetParent();
352 }
353 if (pDockingWindow)
354 {
355 PaneDockingWindow* pPaneDockingWindow = dynamic_cast<PaneDockingWindow*>(pDockingWindow);
356 if (pPaneDockingWindow != NULL)
357 pPaneDockingWindow->GetToolBox().GrabFocus();
358 }
359 }
360 }
361
362
363
364
NotifyFocusChangeListeners(void) const365 void FocusManager::NotifyFocusChangeListeners (void) const
366 {
367 // Create a copy of the listener list to be safe when that is modified.
368 ::std::vector<Link> aListeners (maFocusChangeListeners);
369
370 // Tell the slection change listeners that the selection has changed.
371 ::std::vector<Link>::iterator iListener (aListeners.begin());
372 ::std::vector<Link>::iterator iEnd (aListeners.end());
373 for (; iListener!=iEnd; ++iListener)
374 {
375 iListener->Call(NULL);
376 }
377 }
378
379
380
381
FocusHider(FocusManager & rManager)382 FocusManager::FocusHider::FocusHider (FocusManager& rManager)
383 : mbFocusVisible(rManager.IsFocusShowing())
384 , mrManager(rManager)
385 {
386 mrManager.HideFocus();
387 }
388
389
390
391
~FocusHider(void)392 FocusManager::FocusHider::~FocusHider (void)
393 {
394 if (mbFocusVisible)
395 mrManager.ShowFocus();
396 }
397
398 } } } // end of namespace ::sd::slidesorter::controller
399
400