sd/source/ui/sidebar/NavigatorWrapper.cxx | 9 + sd/source/ui/sidebar/NavigatorWrapper.hxx | 1 sfx2/source/sidebar/FocusManager.cxx | 150 ++++++++++++++++++++++++++---- sfx2/source/sidebar/FocusManager.hxx | 18 +++ 4 files changed, 158 insertions(+), 20 deletions(-)
New commits: commit 4b0aafb8182b1f86b9edf947a4c62ff9948c6676 Author: Andre Fischer <a...@apache.org> Date: Thu May 23 14:30:17 2013 +0000 122247: Improved focus traveling in sidebar. diff --git a/sd/source/ui/sidebar/NavigatorWrapper.cxx b/sd/source/ui/sidebar/NavigatorWrapper.cxx index 6a4f3bc..eeaa7d4 100644 --- a/sd/source/ui/sidebar/NavigatorWrapper.cxx +++ b/sd/source/ui/sidebar/NavigatorWrapper.cxx @@ -86,4 +86,13 @@ void NavigatorWrapper::UpdateNavigator (void) } + + +void NavigatorWrapper::GetFocus (void) +{ + maNavigator.GrabFocus(); +} + + + } } // end of namespace sd::sidebar diff --git a/sd/source/ui/sidebar/NavigatorWrapper.hxx b/sd/source/ui/sidebar/NavigatorWrapper.hxx index 83370d1..16ee30a 100644 --- a/sd/source/ui/sidebar/NavigatorWrapper.hxx +++ b/sd/source/ui/sidebar/NavigatorWrapper.hxx @@ -55,6 +55,7 @@ public: // Control virtual void Resize (void); + virtual void GetFocus (void); // From ILayoutableWindow virtual css::ui::LayoutSize GetHeightForWidth (const sal_Int32 nWidth); diff --git a/sfx2/source/sidebar/FocusManager.cxx b/sfx2/source/sidebar/FocusManager.cxx index 9d29355..f568e52 100644 --- a/sfx2/source/sidebar/FocusManager.cxx +++ b/sfx2/source/sidebar/FocusManager.cxx @@ -47,7 +47,9 @@ FocusManager::FocusManager (const ::boost::function<void(const Panel&)>& rShowPa : mpDeckTitleBar(), maPanels(), maButtons(), - maShowPanelFunctor(rShowPanelFunctor) + maShowPanelFunctor(rShowPanelFunctor), + mbObservingContentControlFocus(false), + mpFirstFocusedContentControl(NULL) { } @@ -259,17 +261,23 @@ bool FocusManager::IsAnyButtonFocused (void) const void FocusManager::FocusDeckTitle (void) { - if (IsDeckTitleVisible()) + if (mpDeckTitleBar != NULL) { - ToolBox& rToolBox = mpDeckTitleBar->GetToolBox(); - if (rToolBox.GetItemCount() > 0) + if (IsDeckTitleVisible()) + { + mpDeckTitleBar->GrabFocus(); + } + else if (mpDeckTitleBar->GetToolBox().GetItemCount() > 0) { + ToolBox& rToolBox = mpDeckTitleBar->GetToolBox(); rToolBox.GrabFocus(); rToolBox.Invalidate(); } + else + FocusPanel(0, false); } else - FocusPanel(0); + FocusPanel(0, false); } @@ -283,10 +291,31 @@ bool FocusManager::IsDeckTitleVisible (void) const -void FocusManager::FocusPanel (const sal_Int32 nPanelIndex) +bool FocusManager::IsPanelTitleVisible (const sal_Int32 nPanelIndex) const { if (nPanelIndex<0 || nPanelIndex>=static_cast<sal_Int32>(maPanels.size())) + return false; + + TitleBar* pTitleBar = maPanels[nPanelIndex]->GetTitleBar(); + if (pTitleBar==NULL) + return false; + return pTitleBar->IsVisible(); +} + + + + +void FocusManager::FocusPanel ( + const sal_Int32 nPanelIndex, + const bool bFallbackToDeckTitle) +{ + if (nPanelIndex<0 || nPanelIndex>=static_cast<sal_Int32>(maPanels.size())) + { + if (bFallbackToDeckTitle) + FocusDeckTitle(); return; + } + Panel& rPanel (*maPanels[nPanelIndex]); TitleBar* pTitleBar = rPanel.GetTitleBar(); if (pTitleBar!=NULL && pTitleBar->IsVisible()) @@ -294,8 +323,21 @@ void FocusManager::FocusPanel (const sal_Int32 nPanelIndex) rPanel.SetExpanded(true); pTitleBar->GrabFocus(); } + else if (bFallbackToDeckTitle) + { + // The panel title is not visible, fall back to the deck + // title. + // Make sure that the desk title is visible here to prevent a + // loop when both the title of panel 0 and the deck title are + // not present. + if (IsDeckTitleVisible()) + FocusDeckTitle(); + else + FocusPanelContent(nPanelIndex); + } else FocusPanelContent(nPanelIndex); + if (maShowPanelFunctor) maShowPanelFunctor(rPanel); } @@ -307,7 +349,11 @@ void FocusManager::FocusPanelContent (const sal_Int32 nPanelIndex) { Window* pWindow = VCLUnoHelper::GetWindow(maPanels[nPanelIndex]->GetElementWindow()); if (pWindow != NULL) + { + mbObservingContentControlFocus = true; pWindow->GrabFocus(); + mbObservingContentControlFocus = false; + } } @@ -327,7 +373,7 @@ void FocusManager::ClickButton (const sal_Int32 nButtonIndex) maButtons[nButtonIndex]->Click(); if (nButtonIndex > 0) if ( ! maPanels.empty()) - FocusPanel(0); + FocusPanel(0, true); maButtons[nButtonIndex]->GetParent()->Invalidate(); } @@ -391,11 +437,46 @@ bool FocusManager::MoveFocusInsidePanel ( +bool FocusManager::MoveFocusInsideDeckTitle ( + const FocusLocation aFocusLocation, + const sal_Int32 nDirection) +{ + // Note that when the title bar of the first (and only) panel is + // not visible then the deck title takes its place and the focus + // is moved between a) deck title, b) deck closer and c) content + // of panel 0. + const bool bHasToolBoxItem ( + mpDeckTitleBar->GetToolBox().GetItemCount() > 0); + switch (aFocusLocation.meComponent) + { + case PC_DeckTitle: + if (nDirection<0 && ! IsPanelTitleVisible(0)) + FocusPanelContent(0); + else if (bHasToolBoxItem) + mpDeckTitleBar->GetToolBox().GrabFocus(); + return true; + + case PC_DeckToolBox: + if (nDirection>0 && ! IsPanelTitleVisible(0)) + FocusPanelContent(0); + else + mpDeckTitleBar->GrabFocus(); + return true; + + default: + return false; + } +} + + + + void FocusManager::HandleKeyEvent ( const KeyCode& rKeyCode, const Window& rWindow) { const FocusLocation aLocation (GetFocusLocation(rWindow)); + mpLastFocusedWindow = NULL; switch (rKeyCode.GetCode()) { @@ -440,21 +521,29 @@ void FocusManager::HandleKeyEvent ( return; case KEY_TAB: + { + const sal_Int32 nDirection ( + rKeyCode.IsShift() + ? -1 + : +1); switch (aLocation.meComponent) { case PC_PanelTitle: case PC_PanelToolBox: case PC_PanelContent: - if (rKeyCode.IsShift()) - MoveFocusInsidePanel(aLocation, -1); - else - MoveFocusInsidePanel(aLocation, +1); + MoveFocusInsidePanel(aLocation, nDirection); + break; + + case PC_DeckTitle: + case PC_DeckToolBox: + MoveFocusInsideDeckTitle(aLocation, nDirection); break; default: break; } break; + } case KEY_LEFT: case KEY_UP: @@ -465,7 +554,7 @@ void FocusManager::HandleKeyEvent ( case PC_PanelContent: // Go to previous panel or the deck title. if (aLocation.mnIndex > 0) - FocusPanel(aLocation.mnIndex-1); + FocusPanel(aLocation.mnIndex-1, true); else if (IsDeckTitleVisible()) FocusDeckTitle(); else @@ -481,7 +570,7 @@ void FocusManager::HandleKeyEvent ( case PC_TabBar: // Go to previous tab bar item. if (aLocation.mnIndex == 0) - FocusPanel(maPanels.size()-1); + FocusPanel(maPanels.size()-1, true); else FocusButton((aLocation.mnIndex + maButtons.size() - 1) % maButtons.size()); break; @@ -500,7 +589,7 @@ void FocusManager::HandleKeyEvent ( case PC_PanelContent: // Go to next panel. if (aLocation.mnIndex < static_cast<sal_Int32>(maPanels.size())-1) - FocusPanel(aLocation.mnIndex+1); + FocusPanel(aLocation.mnIndex+1, false); else FocusButton(0); break; @@ -508,7 +597,10 @@ void FocusManager::HandleKeyEvent ( case PC_DeckTitle: case PC_DeckToolBox: // Focus the first panel. - FocusPanel(0); + if (IsPanelTitleVisible(0)) + FocusPanel(0, false); + else + FocusButton(0); break; case PC_TabBar: @@ -518,7 +610,7 @@ void FocusManager::HandleKeyEvent ( else if (IsDeckTitleVisible()) FocusDeckTitle(); else - FocusPanel(0); + FocusPanel(0, true); break; default: @@ -591,8 +683,8 @@ IMPL_LINK(FocusManager, ChildEventListener, VclSimpleEvent*, pEvent) { KeyEvent* pKeyEvent = static_cast<KeyEvent*>(pWindowEvent->GetData()); - // Go up the window hierarchy to find the parent of the - // event source which is known to us. + // Go up the window hierarchy to find out whether the + // parent of the event source is known to us. Window* pWindow = pSource; FocusLocation aLocation (PC_None, -1); while (true) @@ -611,7 +703,17 @@ IMPL_LINK(FocusManager, ChildEventListener, VclSimpleEvent*, pEvent) { case KEY_ESCAPE: // Return focus back to the panel title. - FocusPanel(aLocation.mnIndex); + FocusPanel(aLocation.mnIndex, true); + break; + + case KEY_TAB: + if (mpFirstFocusedContentControl!=NULL + && mpLastFocusedWindow == mpFirstFocusedContentControl) + { + // Move focus back to panel (or deck) + // title. + FocusPanel(aLocation.mnIndex, true); + } break; default: @@ -621,6 +723,16 @@ IMPL_LINK(FocusManager, ChildEventListener, VclSimpleEvent*, pEvent) return 1; } + case VCLEVENT_WINDOW_GETFOCUS: + // Keep track of focused controls in panel content. + // Remember the first focused control. When it is later + // focused again due to pressing the TAB key then the + // focus is moved to the panel or deck title. + mpLastFocusedWindow = pSource; + if (mbObservingContentControlFocus) + mpFirstFocusedContentControl = pSource; + break; + default: break; } diff --git a/sfx2/source/sidebar/FocusManager.hxx b/sfx2/source/sidebar/FocusManager.hxx index 019b50c..4ca5b92 100644 --- a/sfx2/source/sidebar/FocusManager.hxx +++ b/sfx2/source/sidebar/FocusManager.hxx @@ -76,6 +76,9 @@ private: ::std::vector<Panel*> maPanels; ::std::vector<Button*> maButtons; const ::boost::function<void(const Panel&)> maShowPanelFunctor; + bool mbObservingContentControlFocus; + Window* mpFirstFocusedContentControl; + Window* mpLastFocusedWindow; enum PanelComponent { @@ -118,17 +121,30 @@ private: void FocusDeckTitle (void); bool IsDeckTitleVisible (void) const; + bool IsPanelTitleVisible (const sal_Int32 nPanelIndex) const; /** Set the focus to the title bar of the panel or, if the the title bar is not visible, directly to the panel. + @param nPanelIndex + Index of the panel to focus. + @param bFallbackToDeckTitle + When the panel title bar is not visible then The fallback + bias defines whether to focus the deck (true) or the panel + content (false) will be focused instead. */ - void FocusPanel (const sal_Int32 nPanelIndex); + void FocusPanel ( + const sal_Int32 nPanelIndex, + const bool bFallbackToDeckTitle); + void FocusPanelContent (const sal_Int32 nPanelIndex); void FocusButton (const sal_Int32 nButtonIndex); void ClickButton (const sal_Int32 nButtonIndex); bool MoveFocusInsidePanel ( const FocusLocation aLocation, const sal_Int32 nDirection); + bool MoveFocusInsideDeckTitle ( + const FocusLocation aLocation, + const sal_Int32 nDirection); void HandleKeyEvent ( const KeyCode& rKeyCode, _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits