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