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 #include "precompiled_sfx2.hxx"
23 
24 #include "FocusManager.hxx"
25 #include "Panel.hxx"
26 #include "sfx2/sidebar/Tools.hxx"
27 #include "TitleBar.hxx"
28 #include <vcl/button.hxx>
29 #include <vcl/toolbox.hxx>
30 #include <toolkit/helper/vclunohelper.hxx>
31 
32 
33 namespace sfx2 { namespace sidebar {
34 
35 namespace
36 {
37     enum PanelComponent
38     {
39         PC_TitleBar,
40         PC_ToolBox,
41         PC_Content,
42         PC_None
43     };
44 
45     PanelComponent GetFocusedComponent (const Panel& rPanel)
46     {
47         if (rPanel.HasFocus())
48             return PC_Content;
49         else if (rPanel.GetTitleBar() != NULL)
50         {
51             if (rPanel.GetTitleBar()->HasFocus())
52                 return PC_TitleBar;
53             else if (rPanel.GetTitleBar()->GetToolBox().HasFocus())
54                 return PC_ToolBox;
55         }
56 	return PC_None;
57     }
58 }
59 
60 
61 FocusManager::FocusManager (void)
62     : maPanels(),
63       maButtons(),
64       mpTopLevelWindow(NULL)
65 {
66 }
67 
68 
69 
70 
71 FocusManager::~FocusManager (void)
72 {
73     Clear();
74 }
75 
76 
77 
78 
79 void FocusManager::GrabFocus (void)
80 {
81     if ( ! maPanels.empty())
82         FocusPanel(0);
83 }
84 
85 
86 
87 
88 void FocusManager::Clear (void)
89 {
90     ClearPanels();
91     ClearButtons();
92 }
93 
94 
95 
96 void FocusManager::ClearPanels (void)
97 {
98     SetTopLevelWindow(NULL);
99 
100     ::std::vector<Panel*> aPanels;
101     aPanels.swap(maPanels);
102     for (::std::vector<Panel*>::iterator iPanel(aPanels.begin()),iEnd(aPanels.end());
103          iPanel!=iEnd;
104         ++iPanel)
105     {
106         UnregisterWindow(**iPanel);
107         if ((*iPanel)->GetTitleBar() != NULL)
108         {
109             UnregisterWindow(*(*iPanel)->GetTitleBar());
110             UnregisterWindow((*iPanel)->GetTitleBar()->GetToolBox());
111         }
112     }
113 }
114 
115 
116 
117 
118 void FocusManager::ClearButtons (void)
119 {
120     ::std::vector<Window*> aButtons;
121     for (::std::vector<Window*>::iterator iButton(aButtons.begin()),iEnd(aButtons.end());
122          iButton!=iEnd;
123         ++iButton)
124     {
125         UnregisterWindow(**iButton);
126     }
127 }
128 
129 
130 
131 
132 void FocusManager::SetPanels (const SharedPanelContainer& rPanels)
133 {
134     ClearPanels();
135     for(SharedPanelContainer::const_iterator iPanel(rPanels.begin()),iEnd(rPanels.end());
136         iPanel!=iEnd;
137         ++iPanel)
138     {
139         RegisterWindow(**iPanel);
140         if ((*iPanel)->GetTitleBar() != NULL)
141         {
142             RegisterWindow(*(*iPanel)->GetTitleBar());
143             RegisterWindow((*iPanel)->GetTitleBar()->GetToolBox());
144         }
145         maPanels.push_back(iPanel->get());
146     }
147 
148     RegisterTopLevelListener();
149 }
150 
151 
152 
153 
154 void FocusManager::SetButtons (const ::std::vector<Button*>& rButtons)
155 {
156     ClearButtons();
157     for (::std::vector<Button*>::const_iterator iButton(rButtons.begin()),iEnd(rButtons.end());
158          iButton!=iEnd;
159          ++iButton)
160     {
161         RegisterWindow(**iButton);
162         maButtons.push_back(*iButton);
163     }
164 }
165 
166 
167 
168 
169 void FocusManager::RegisterWindow (Window& rWindow)
170 {
171     rWindow.AddEventListener(LINK(this, FocusManager, WindowEventListener));
172 }
173 
174 
175 
176 
177 void FocusManager::UnregisterWindow (Window& rWindow)
178 {
179     rWindow.RemoveEventListener(LINK(this, FocusManager, WindowEventListener));
180 }
181 
182 
183 
184 
185 void FocusManager::RegisterTopLevelListener (void)
186 {
187     if (maPanels.empty())
188         return;
189     Window* pWindow = maPanels.front();
190     while (pWindow != NULL && pWindow->GetParent()!=NULL)
191     {
192         pWindow = pWindow->GetParent();
193     }
194     SetTopLevelWindow(pWindow);
195 }
196 
197 
198 
199 
200 void FocusManager::SetTopLevelWindow (Window* pWindow)
201 {
202     if (mpTopLevelWindow != pWindow)
203     {
204         if (mpTopLevelWindow != NULL)
205         {
206             UnregisterWindow(*mpTopLevelWindow);
207             mpTopLevelWindow->RemoveChildEventListener(LINK(this, FocusManager, WindowEventListener));
208         }
209         mpTopLevelWindow = pWindow;
210         if (mpTopLevelWindow != NULL)
211         {
212             RegisterWindow(*mpTopLevelWindow);
213             mpTopLevelWindow->AddChildEventListener(LINK(this, FocusManager, WindowEventListener));
214         }
215     }
216 }
217 
218 
219 
220 
221 sal_Int32 FocusManager::GetPanelIndex (const Window& rWindow) const
222 {
223     for (sal_Int32 nIndex=0,nCount(maPanels.size()); nIndex<nCount; ++nIndex)
224     {
225         if (maPanels[nIndex] == &rWindow)
226             return nIndex;
227         TitleBar* pTitleBar = maPanels[nIndex]->GetTitleBar();
228         if (pTitleBar == &rWindow)
229             return nIndex;
230         if (pTitleBar!=NULL && &pTitleBar->GetToolBox()==&rWindow)
231             return nIndex;
232     }
233     return -1;
234 }
235 
236 
237 
238 
239 sal_Int32 FocusManager::GetButtonIndex (const Window& rWindow) const
240 {
241     for (sal_Int32 nIndex=0,nCount(maButtons.size()); nIndex<nCount; ++nIndex)
242         if (maButtons[nIndex] == &rWindow)
243             return nIndex;
244     return -1;
245 }
246 
247 
248 
249 
250 bool FocusManager::IsAnyPanelFocused (void) const
251 {
252     for (::std::vector<Panel*>::const_iterator iPanel(maPanels.begin()),iEnd(maPanels.end());
253          iPanel!=iEnd;
254          ++iPanel)
255     {
256         if ((*iPanel)->HasFocus())
257             return true;
258         else if ((*iPanel)->HasChildPathFocus())
259             return true;
260     }
261     return false;
262 }
263 
264 
265 
266 
267 bool FocusManager::IsAnyButtonFocused (void) const
268 {
269     for (::std::vector<Button*>::const_iterator iButton(maButtons.begin()),iEnd(maButtons.end());
270          iButton!=iEnd;
271          ++iButton)
272     {
273         if ((*iButton)->HasFocus())
274             return true;
275     }
276     return false;
277 }
278 
279 
280 
281 
282 void FocusManager::FocusPanel (const sal_Int32 nPanelIndex)
283 {
284     Panel& rPanel (*maPanels[nPanelIndex]);
285     TitleBar* pTitleBar = rPanel.GetTitleBar();
286     if (pTitleBar!=NULL && pTitleBar->IsVisible())
287     {
288         rPanel.SetExpanded(true);
289         pTitleBar->GrabFocus();
290     }
291     else
292         FocusPanelContent(nPanelIndex);
293 }
294 
295 
296 
297 
298 void FocusManager::FocusPanelContent (const sal_Int32 nPanelIndex)
299 {
300     Window* pWindow = VCLUnoHelper::GetWindow(maPanels[nPanelIndex]->GetElementWindow());
301     if (pWindow != NULL)
302         pWindow->GrabFocus();
303 }
304 
305 
306 
307 
308 void FocusManager::FocusButton (const sal_Int32 nButtonIndex)
309 {
310     maButtons[nButtonIndex]->GrabFocus();
311     maButtons[nButtonIndex]->Invalidate();
312 }
313 
314 
315 
316 
317 void FocusManager::ClickButton (const sal_Int32 nButtonIndex)
318 {
319     maButtons[nButtonIndex]->Click();
320     if (nButtonIndex > 0)
321         if ( ! maPanels.empty())
322             FocusPanel(0);
323     maButtons[nButtonIndex]->GetParent()->Invalidate();
324 }
325 
326 
327 
328 
329 void FocusManager::RemoveWindow (Window& rWindow)
330 {
331     ::std::vector<Panel*>::iterator iPanel (::std::find(maPanels.begin(), maPanels.end(), &rWindow));
332     if (iPanel != maPanels.end())
333     {
334         UnregisterWindow(rWindow);
335         if ((*iPanel)->GetTitleBar() != NULL)
336         {
337             UnregisterWindow(*(*iPanel)->GetTitleBar());
338             UnregisterWindow((*iPanel)->GetTitleBar()->GetToolBox());
339         }
340         maPanels.erase(iPanel);
341         return;
342     }
343 
344     ::std::vector<Button*>::iterator iButton (::std::find(maButtons.begin(), maButtons.end(), &rWindow));
345     if (iButton != maButtons.end())
346     {
347         UnregisterWindow(rWindow);
348         maButtons.erase(iButton);
349         return;
350     }
351 }
352 
353 
354 
355 
356 bool FocusManager::MoveFocusInsidePanel (
357     const sal_Int32 nPanelIndex,
358     const sal_Int32 nDirection)
359 {
360     Panel& rPanel (*maPanels[nPanelIndex]);
361     switch (GetFocusedComponent(rPanel))
362     {
363         case  PC_TitleBar:
364             if (nDirection > 0)
365                 rPanel.GetTitleBar()->GetToolBox().GrabFocus();
366             else
367                 FocusPanelContent(nPanelIndex);
368             return true;
369 
370         case PC_ToolBox:
371             if (nDirection > 0)
372                 FocusPanelContent(nPanelIndex);
373             else
374                 rPanel.GetTitleBar()->GrabFocus();
375             return true;
376 
377         default:
378             return false;
379     }
380 }
381 
382 
383 
384 
385 long FocusManager::NotifyDockingWindowEvent (const KeyEvent& rKeyEvent)
386 {
387     switch(rKeyEvent.GetKeyCode().GetCode())
388     {
389         case KEY_F6:
390             if (rKeyEvent.GetKeyCode().IsShift())
391             {
392                 if (IsAnyButtonFocused())
393                 {
394                     FocusPanel(0);
395                     return 1;
396                 }
397             }
398             else
399             {
400                 if (IsAnyPanelFocused())
401                 {
402                     FocusButton(0);
403                     return 1;
404                 }
405             }
406             break;
407     }
408     return 0;
409 }
410 
411 
412 
413 
414 void FocusManager::HandleKeyEvent (
415     const KeyCode& rKeyCode,
416     const Window& rWindow)
417 {
418     if (rKeyCode.GetModifier() != 0)
419         return;
420 
421     const sal_Int32 nPanelIndex (GetPanelIndex(rWindow));
422     // const bool bIsPanelTitleFocused (nPanelIndex>=0 && maPanels[nPanelIndex] != &rWindow);
423     // const bool bIsPanelToolBoxFocused (nPanelIndex>=0 && maPanels[nPanelIndex] != &rWindow);
424     sal_Int32 nButtonIndex (nPanelIndex==-1 ? GetButtonIndex(rWindow) : -1);
425 
426     switch (rKeyCode.GetCode())
427     {
428         case KEY_F6:
429             if (nPanelIndex >= 0)
430                 FocusButton(0);
431             else
432                 return;
433             break;
434 
435         case KEY_SPACE:
436             if (nPanelIndex >= 0)
437             {
438                 if (GetFocusedComponent(*maPanels[nPanelIndex]) == PC_TitleBar)
439                 {
440                     // Toggle the expansion state.
441                     maPanels[nPanelIndex]->SetExpanded( ! maPanels[nPanelIndex]->IsExpanded());
442                 }
443             }
444             else if (nButtonIndex >= 0)
445             {
446                 // Activate the button.
447                 ClickButton(nButtonIndex);
448             }
449             return;
450 
451         case KEY_RETURN:
452             if (nPanelIndex >= 0)
453             {
454                 if (GetFocusedComponent(*maPanels[nPanelIndex]) == PC_TitleBar)
455                 {
456                     // Enter the panel.
457                     FocusPanelContent(nPanelIndex);
458                 }
459             }
460             else if (nButtonIndex >= 0)
461             {
462                 // Activate the button.
463                 ClickButton(nButtonIndex);
464             }
465             return;
466 
467         case KEY_TAB:
468             if (nPanelIndex >= 0)
469             {
470                 if (rKeyCode.IsShift())
471                     MoveFocusInsidePanel(nPanelIndex, -1);
472                 else
473                     MoveFocusInsidePanel(nPanelIndex, +1);
474             }
475             break;
476 
477         case KEY_LEFT:
478         case KEY_UP:
479             // Go to previous element in focus ring.
480             if (nPanelIndex >= 0)
481             {
482                 FocusPanel((nPanelIndex + maPanels.size() - 1) % maPanels.size());
483             }
484             else if (nButtonIndex >= 0)
485             {
486                 FocusButton((nButtonIndex + maButtons.size() - 1) % maButtons.size());
487             }
488             break;
489 
490         case KEY_RIGHT:
491         case KEY_DOWN:
492             // Go to next element in focus ring.
493             if (nPanelIndex >= 0)
494             {
495                 FocusPanel((nPanelIndex + 1) % maPanels.size());
496             }
497             else if (nButtonIndex >= 0)
498             {
499                 FocusButton((nButtonIndex + 1) % maButtons.size());
500             }
501             break;
502     }
503 }
504 
505 
506 
507 
508 void FocusManager::HandleTopLevelEvent (VclWindowEvent& rEvent)
509 {
510     switch (rEvent.GetId())
511     {
512         case VCLEVENT_WINDOW_KEYINPUT:
513         {
514             KeyEvent* pKeyEvent = static_cast<KeyEvent*>(rEvent.GetData());
515             switch (pKeyEvent->GetKeyCode().GetCode())
516             {
517                 case KEY_F6:
518                     OSL_TRACE("");
519                     break;
520             }
521         }
522     }
523 }
524 
525 
526 
527 
528 IMPL_LINK(FocusManager, WindowEventListener, VclSimpleEvent*, pEvent)
529 {
530     if (pEvent == NULL)
531         return 0;
532 
533     if ( ! pEvent->ISA(VclWindowEvent))
534         return 0;
535 
536     VclWindowEvent* pWindowEvent = static_cast<VclWindowEvent*>(pEvent);
537     Window* pSource = pWindowEvent->GetWindow();
538     if (pSource == NULL)
539         return 0;
540 
541     if (pSource == mpTopLevelWindow)
542         HandleTopLevelEvent(*pWindowEvent);
543     else
544         switch (pWindowEvent->GetId())
545         {
546             case VCLEVENT_WINDOW_KEYINPUT:
547             {
548                 KeyEvent* pKeyEvent = static_cast<KeyEvent*>(pWindowEvent->GetData());
549                 HandleKeyEvent(pKeyEvent->GetKeyCode(), *pSource);
550                 return 1;
551             }
552 
553             case VCLEVENT_OBJECT_DYING:
554                 RemoveWindow(*pSource);
555                 return 1;
556 
557             case VCLEVENT_WINDOW_GETFOCUS:
558             case VCLEVENT_WINDOW_LOSEFOCUS:
559                 pSource->Invalidate();
560         }
561     return 0;
562 }
563 
564 
565 
566 } } // end of namespace sfx2::sidebar
567