Kaydet (Commit) ce7dafae authored tarafından Andre Fischer's avatar Andre Fischer Kaydeden (comit) Caolán McNamara

Resolves: #i122247# Improved focus traveling in sidebar

(cherry picked from commit 4b0aafb8)

Change-Id: Ieae8e44fe147309cc3ff447a6dbc375d1b2f34d0
(cherry picked from commit ab0360c3)
üst ac2bac4a
...@@ -81,4 +81,13 @@ void NavigatorWrapper::UpdateNavigator (void) ...@@ -81,4 +81,13 @@ void NavigatorWrapper::UpdateNavigator (void)
} }
void NavigatorWrapper::GetFocus (void)
{
maNavigator.GrabFocus();
}
} } // end of namespace sd::sidebar } } // end of namespace sd::sidebar
...@@ -51,6 +51,7 @@ public: ...@@ -51,6 +51,7 @@ public:
// Control // Control
virtual void Resize (void); virtual void Resize (void);
virtual void GetFocus (void);
// From ILayoutableWindow // From ILayoutableWindow
virtual css::ui::LayoutSize GetHeightForWidth (const sal_Int32 nWidth); virtual css::ui::LayoutSize GetHeightForWidth (const sal_Int32 nWidth);
......
...@@ -42,7 +42,9 @@ FocusManager::FocusManager (const ::boost::function<void(const Panel&)>& rShowPa ...@@ -42,7 +42,9 @@ FocusManager::FocusManager (const ::boost::function<void(const Panel&)>& rShowPa
: mpDeckTitleBar(), : mpDeckTitleBar(),
maPanels(), maPanels(),
maButtons(), maButtons(),
maShowPanelFunctor(rShowPanelFunctor) maShowPanelFunctor(rShowPanelFunctor),
mbObservingContentControlFocus(false),
mpFirstFocusedContentControl(NULL)
{ {
} }
...@@ -254,17 +256,23 @@ bool FocusManager::IsAnyButtonFocused (void) const ...@@ -254,17 +256,23 @@ bool FocusManager::IsAnyButtonFocused (void) const
void FocusManager::FocusDeckTitle (void) void FocusManager::FocusDeckTitle (void)
{ {
if (IsDeckTitleVisible()) if (mpDeckTitleBar != NULL)
{ {
ToolBox& rToolBox = mpDeckTitleBar->GetToolBox(); if (IsDeckTitleVisible())
if (rToolBox.GetItemCount() > 0) {
mpDeckTitleBar->GrabFocus();
}
else if (mpDeckTitleBar->GetToolBox().GetItemCount() > 0)
{ {
ToolBox& rToolBox = mpDeckTitleBar->GetToolBox();
rToolBox.GrabFocus(); rToolBox.GrabFocus();
rToolBox.Invalidate(); rToolBox.Invalidate();
} }
else
FocusPanel(0, false);
} }
else else
FocusPanel(0); FocusPanel(0, false);
} }
...@@ -278,10 +286,31 @@ bool FocusManager::IsDeckTitleVisible (void) const ...@@ -278,10 +286,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())) 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; return;
}
Panel& rPanel (*maPanels[nPanelIndex]); Panel& rPanel (*maPanels[nPanelIndex]);
TitleBar* pTitleBar = rPanel.GetTitleBar(); TitleBar* pTitleBar = rPanel.GetTitleBar();
if (pTitleBar!=NULL && pTitleBar->IsVisible()) if (pTitleBar!=NULL && pTitleBar->IsVisible())
...@@ -289,8 +318,21 @@ void FocusManager::FocusPanel (const sal_Int32 nPanelIndex) ...@@ -289,8 +318,21 @@ void FocusManager::FocusPanel (const sal_Int32 nPanelIndex)
rPanel.SetExpanded(true); rPanel.SetExpanded(true);
pTitleBar->GrabFocus(); 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 else
FocusPanelContent(nPanelIndex); FocusPanelContent(nPanelIndex);
if (maShowPanelFunctor) if (maShowPanelFunctor)
maShowPanelFunctor(rPanel); maShowPanelFunctor(rPanel);
} }
...@@ -302,7 +344,11 @@ void FocusManager::FocusPanelContent (const sal_Int32 nPanelIndex) ...@@ -302,7 +344,11 @@ void FocusManager::FocusPanelContent (const sal_Int32 nPanelIndex)
{ {
Window* pWindow = VCLUnoHelper::GetWindow(maPanels[nPanelIndex]->GetElementWindow()); Window* pWindow = VCLUnoHelper::GetWindow(maPanels[nPanelIndex]->GetElementWindow());
if (pWindow != NULL) if (pWindow != NULL)
{
mbObservingContentControlFocus = true;
pWindow->GrabFocus(); pWindow->GrabFocus();
mbObservingContentControlFocus = false;
}
} }
...@@ -322,7 +368,7 @@ void FocusManager::ClickButton (const sal_Int32 nButtonIndex) ...@@ -322,7 +368,7 @@ void FocusManager::ClickButton (const sal_Int32 nButtonIndex)
maButtons[nButtonIndex]->Click(); maButtons[nButtonIndex]->Click();
if (nButtonIndex > 0) if (nButtonIndex > 0)
if ( ! maPanels.empty()) if ( ! maPanels.empty())
FocusPanel(0); FocusPanel(0, true);
maButtons[nButtonIndex]->GetParent()->Invalidate(); maButtons[nButtonIndex]->GetParent()->Invalidate();
} }
...@@ -386,11 +432,46 @@ bool FocusManager::MoveFocusInsidePanel ( ...@@ -386,11 +432,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 ( void FocusManager::HandleKeyEvent (
const KeyCode& rKeyCode, const KeyCode& rKeyCode,
const Window& rWindow) const Window& rWindow)
{ {
const FocusLocation aLocation (GetFocusLocation(rWindow)); const FocusLocation aLocation (GetFocusLocation(rWindow));
mpLastFocusedWindow = NULL;
switch (rKeyCode.GetCode()) switch (rKeyCode.GetCode())
{ {
...@@ -435,21 +516,29 @@ void FocusManager::HandleKeyEvent ( ...@@ -435,21 +516,29 @@ void FocusManager::HandleKeyEvent (
return; return;
case KEY_TAB: case KEY_TAB:
{
const sal_Int32 nDirection (
rKeyCode.IsShift()
? -1
: +1);
switch (aLocation.meComponent) switch (aLocation.meComponent)
{ {
case PC_PanelTitle: case PC_PanelTitle:
case PC_PanelToolBox: case PC_PanelToolBox:
case PC_PanelContent: case PC_PanelContent:
if (rKeyCode.IsShift()) MoveFocusInsidePanel(aLocation, nDirection);
MoveFocusInsidePanel(aLocation, -1); break;
else
MoveFocusInsidePanel(aLocation, +1); case PC_DeckTitle:
case PC_DeckToolBox:
MoveFocusInsideDeckTitle(aLocation, nDirection);
break; break;
default: default:
break; break;
} }
break; break;
}
case KEY_LEFT: case KEY_LEFT:
case KEY_UP: case KEY_UP:
...@@ -460,7 +549,7 @@ void FocusManager::HandleKeyEvent ( ...@@ -460,7 +549,7 @@ void FocusManager::HandleKeyEvent (
case PC_PanelContent: case PC_PanelContent:
// Go to previous panel or the deck title. // Go to previous panel or the deck title.
if (aLocation.mnIndex > 0) if (aLocation.mnIndex > 0)
FocusPanel(aLocation.mnIndex-1); FocusPanel(aLocation.mnIndex-1, true);
else if (IsDeckTitleVisible()) else if (IsDeckTitleVisible())
FocusDeckTitle(); FocusDeckTitle();
else else
...@@ -476,7 +565,7 @@ void FocusManager::HandleKeyEvent ( ...@@ -476,7 +565,7 @@ void FocusManager::HandleKeyEvent (
case PC_TabBar: case PC_TabBar:
// Go to previous tab bar item. // Go to previous tab bar item.
if (aLocation.mnIndex == 0) if (aLocation.mnIndex == 0)
FocusPanel(maPanels.size()-1); FocusPanel(maPanels.size()-1, true);
else else
FocusButton((aLocation.mnIndex + maButtons.size() - 1) % maButtons.size()); FocusButton((aLocation.mnIndex + maButtons.size() - 1) % maButtons.size());
break; break;
...@@ -495,7 +584,7 @@ void FocusManager::HandleKeyEvent ( ...@@ -495,7 +584,7 @@ void FocusManager::HandleKeyEvent (
case PC_PanelContent: case PC_PanelContent:
// Go to next panel. // Go to next panel.
if (aLocation.mnIndex < static_cast<sal_Int32>(maPanels.size())-1) if (aLocation.mnIndex < static_cast<sal_Int32>(maPanels.size())-1)
FocusPanel(aLocation.mnIndex+1); FocusPanel(aLocation.mnIndex+1, false);
else else
FocusButton(0); FocusButton(0);
break; break;
...@@ -503,7 +592,10 @@ void FocusManager::HandleKeyEvent ( ...@@ -503,7 +592,10 @@ void FocusManager::HandleKeyEvent (
case PC_DeckTitle: case PC_DeckTitle:
case PC_DeckToolBox: case PC_DeckToolBox:
// Focus the first panel. // Focus the first panel.
FocusPanel(0); if (IsPanelTitleVisible(0))
FocusPanel(0, false);
else
FocusButton(0);
break; break;
case PC_TabBar: case PC_TabBar:
...@@ -513,7 +605,7 @@ void FocusManager::HandleKeyEvent ( ...@@ -513,7 +605,7 @@ void FocusManager::HandleKeyEvent (
else if (IsDeckTitleVisible()) else if (IsDeckTitleVisible())
FocusDeckTitle(); FocusDeckTitle();
else else
FocusPanel(0); FocusPanel(0, true);
break; break;
default: default:
...@@ -586,8 +678,8 @@ IMPL_LINK(FocusManager, ChildEventListener, VclSimpleEvent*, pEvent) ...@@ -586,8 +678,8 @@ IMPL_LINK(FocusManager, ChildEventListener, VclSimpleEvent*, pEvent)
{ {
KeyEvent* pKeyEvent = static_cast<KeyEvent*>(pWindowEvent->GetData()); KeyEvent* pKeyEvent = static_cast<KeyEvent*>(pWindowEvent->GetData());
// Go up the window hierarchy to find the parent of the // Go up the window hierarchy to find out whether the
// event source which is known to us. // parent of the event source is known to us.
Window* pWindow = pSource; Window* pWindow = pSource;
FocusLocation aLocation (PC_None, -1); FocusLocation aLocation (PC_None, -1);
while (true) while (true)
...@@ -606,7 +698,17 @@ IMPL_LINK(FocusManager, ChildEventListener, VclSimpleEvent*, pEvent) ...@@ -606,7 +698,17 @@ IMPL_LINK(FocusManager, ChildEventListener, VclSimpleEvent*, pEvent)
{ {
case KEY_ESCAPE: case KEY_ESCAPE:
// Return focus back to the panel title. // 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; break;
default: default:
...@@ -616,6 +718,16 @@ IMPL_LINK(FocusManager, ChildEventListener, VclSimpleEvent*, pEvent) ...@@ -616,6 +718,16 @@ IMPL_LINK(FocusManager, ChildEventListener, VclSimpleEvent*, pEvent)
return 1; 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: default:
break; break;
} }
......
...@@ -72,6 +72,9 @@ private: ...@@ -72,6 +72,9 @@ private:
::std::vector<Panel*> maPanels; ::std::vector<Panel*> maPanels;
::std::vector<Button*> maButtons; ::std::vector<Button*> maButtons;
const ::boost::function<void(const Panel&)> maShowPanelFunctor; const ::boost::function<void(const Panel&)> maShowPanelFunctor;
bool mbObservingContentControlFocus;
Window* mpFirstFocusedContentControl;
Window* mpLastFocusedWindow;
enum PanelComponent enum PanelComponent
{ {
...@@ -114,17 +117,30 @@ private: ...@@ -114,17 +117,30 @@ private:
void FocusDeckTitle (void); void FocusDeckTitle (void);
bool IsDeckTitleVisible (void) const; 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 /** Set the focus to the title bar of the panel or, if the the
title bar is not visible, directly to the panel. 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 FocusPanelContent (const sal_Int32 nPanelIndex);
void FocusButton (const sal_Int32 nButtonIndex); void FocusButton (const sal_Int32 nButtonIndex);
void ClickButton (const sal_Int32 nButtonIndex); void ClickButton (const sal_Int32 nButtonIndex);
bool MoveFocusInsidePanel ( bool MoveFocusInsidePanel (
const FocusLocation aLocation, const FocusLocation aLocation,
const sal_Int32 nDirection); const sal_Int32 nDirection);
bool MoveFocusInsideDeckTitle (
const FocusLocation aLocation,
const sal_Int32 nDirection);
void HandleKeyEvent ( void HandleKeyEvent (
const KeyCode& rKeyCode, const KeyCode& rKeyCode,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment