sfx2/inc/sidebar/DeckDescriptor.hxx     |    1 
 sfx2/inc/sidebar/DeckTitleBar.hxx       |    3 -
 sfx2/inc/sidebar/TitleBar.hxx           |    2 
 sfx2/source/sidebar/Deck.cxx            |    3 -
 sfx2/source/sidebar/DeckDescriptor.cxx  |    1 
 sfx2/source/sidebar/DeckTitleBar.cxx    |   16 +++++-
 sfx2/source/sidebar/FocusManager.cxx    |   84 +++++++++++++-------------------
 sfx2/source/sidebar/ResourceManager.cxx |    1 
 sfx2/source/sidebar/TitleBar.cxx        |   13 ++++
 sfx2/uiconfig/ui/deck.ui                |   26 ++++++++-
 sw/qa/uitest/sidebar/tdf152921.py       |    6 +-
 11 files changed, 97 insertions(+), 59 deletions(-)

New commits:
commit 9ca60dc90958001c078ed6331bd432c36961a425
Author:     Rafael Lima <[email protected]>
AuthorDate: Wed Jul 26 02:00:40 2023 +0200
Commit:     Rafael Lima <[email protected]>
CommitDate: Sat Aug 5 00:05:56 2023 +0200

    tdf#156156 Add Help button to sidebar decks
    
    This patch adds a Help button to the sidebar deck, so that each deck has 
its own Help ID, which can later be used as reference to write help pages.
    
    The Help IDs of each sidebar deck is a combination of the string "SIDEBAR_" 
+ the deck ID (as defined in Sidebar.xcu).
    
    Change-Id: Ib7f106ff917e41130bde136e1e6f04bb2af40daf
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154918
    Tested-by: Jenkins
    Reviewed-by: Stéphane Guillou <[email protected]>
    Reviewed-by: Olivier Hallot <[email protected]>

diff --git a/sfx2/inc/sidebar/DeckDescriptor.hxx 
b/sfx2/inc/sidebar/DeckDescriptor.hxx
index 5381b4ea2cd7..8fde0c0330f7 100644
--- a/sfx2/inc/sidebar/DeckDescriptor.hxx
+++ b/sfx2/inc/sidebar/DeckDescriptor.hxx
@@ -34,6 +34,7 @@ public:
     OUString msTitleBarIconURL;
     OUString msHighContrastTitleBarIconURL;
     OUString msHelpText;
+    OUString msHelpId;
     ContextList maContextList;
     bool mbIsEnabled;
     sal_Int32 mnOrderIndex;
diff --git a/sfx2/inc/sidebar/DeckTitleBar.hxx 
b/sfx2/inc/sidebar/DeckTitleBar.hxx
index 72eda5cb7d7b..2834dda1e350 100644
--- a/sfx2/inc/sidebar/DeckTitleBar.hxx
+++ b/sfx2/inc/sidebar/DeckTitleBar.hxx
@@ -29,7 +29,7 @@ class GripWidget;
 class DeckTitleBar final : public TitleBar
 {
 public:
-    DeckTitleBar(const OUString& rsTitle, weld::Builder& rBuilder,
+    DeckTitleBar(const OUString& rsTitle, weld::Builder& rBuilder, const 
OUString& rsHelpId,
                  std::function<void()> aCloserAction);
     virtual ~DeckTitleBar() override;
 
@@ -48,6 +48,7 @@ private:
     std::unique_ptr<weld::CustomWeld> mxGripWeld;
     std::unique_ptr<weld::Label> mxLabel;
 
+    OUString msHelpId;
     const std::function<void()> maCloserAction;
     bool mbIsCloserVisible;
 };
diff --git a/sfx2/inc/sidebar/TitleBar.hxx b/sfx2/inc/sidebar/TitleBar.hxx
index 2cd7224bda12..7836a57be17a 100644
--- a/sfx2/inc/sidebar/TitleBar.hxx
+++ b/sfx2/inc/sidebar/TitleBar.hxx
@@ -56,10 +56,12 @@ protected:
     std::unique_ptr<weld::Image> mxAddonImage;
     std::unique_ptr<weld::Toolbar> mxToolBox;
     Theme::ThemeItem meThemeItem;
+    OUString msToolBoxRId;
 
     virtual void HandleToolBoxItemClick() = 0;
 
     DECL_LINK(SelectionHandler, const OUString&, void);
+    static void ShowHelp(const OUString& rHelpId);
 
 private:
     void SetBackground();
diff --git a/sfx2/source/sidebar/Deck.cxx b/sfx2/source/sidebar/Deck.cxx
index 629a1d76d3d0..c45ab52e574e 100644
--- a/sfx2/source/sidebar/Deck.cxx
+++ b/sfx2/source/sidebar/Deck.cxx
@@ -55,7 +55,8 @@ Deck::Deck(const DeckDescriptor& rDeckDescriptor, 
SidebarDockingWindow* pParentW
     , mnMinimalHeight(0)
     , maPanels()
     , mxParentWindow(pParentWindow)
-    , mxTitleBar(new DeckTitleBar(rDeckDescriptor.msTitle, *m_xBuilder, 
rCloserAction))
+    , mxTitleBar(new DeckTitleBar(rDeckDescriptor.msTitle, *m_xBuilder,
+                 rDeckDescriptor.msHelpId, rCloserAction))
     , mxVerticalScrollBar(m_xBuilder->weld_scrolled_window("scrolledwindow"))
     , mxContents(m_xBuilder->weld_box("contents"))
 {
diff --git a/sfx2/source/sidebar/DeckDescriptor.cxx 
b/sfx2/source/sidebar/DeckDescriptor.cxx
index fee839f08ad0..29af33e33f22 100644
--- a/sfx2/source/sidebar/DeckDescriptor.cxx
+++ b/sfx2/source/sidebar/DeckDescriptor.cxx
@@ -36,6 +36,7 @@ DeckDescriptor::DeckDescriptor (const DeckDescriptor& rOther)
       msTitleBarIconURL(rOther.msTitleBarIconURL),
       msHighContrastTitleBarIconURL(rOther.msHighContrastTitleBarIconURL),
       msHelpText(rOther.msHelpText),
+      msHelpId(rOther.msHelpId),
       maContextList(rOther.maContextList),
       mbIsEnabled(rOther.mbIsEnabled),
       mnOrderIndex(rOther.mnOrderIndex),
diff --git a/sfx2/source/sidebar/DeckTitleBar.cxx 
b/sfx2/source/sidebar/DeckTitleBar.cxx
index 44b9387dc14d..9e12fd15c6ab 100644
--- a/sfx2/source/sidebar/DeckTitleBar.cxx
+++ b/sfx2/source/sidebar/DeckTitleBar.cxx
@@ -61,11 +61,13 @@ public:
 
 DeckTitleBar::DeckTitleBar (const OUString& rsTitle,
                             weld::Builder& rBuilder,
+                            const OUString& rsHelpId,
                             std::function<void()> aCloserAction)
     : TitleBar(rBuilder, Theme::Color_DeckTitleBarBackground)
     , mxGripWidget(new GripWidget)
     , mxGripWeld(new weld::CustomWeld(rBuilder, "grip", *mxGripWidget))
     , mxLabel(rBuilder.weld_label("label"))
+    , msHelpId(rsHelpId)
     , maCloserAction(std::move(aCloserAction))
     , mbIsCloserVisible(false)
 {
@@ -110,8 +112,18 @@ void DeckTitleBar::SetCloserVisible (const bool 
bIsCloserVisible)
 
 void DeckTitleBar::HandleToolBoxItemClick()
 {
-    if (maCloserAction)
-        maCloserAction();
+    if (msToolBoxRId == "btn_help")
+    {
+        // Help toolbox button was clicked
+        DeckTitleBar::ShowHelp(msHelpId);
+    }
+    else if ((msToolBoxRId.isEmpty()) || (msToolBoxRId == "btn_close"))
+    {
+        if (maCloserAction)
+            maCloserAction();
+    }
+    // Reset the toolbox response id
+    msToolBoxRId = "";
 }
 
 void DeckTitleBar::DataChanged()
diff --git a/sfx2/source/sidebar/FocusManager.cxx 
b/sfx2/source/sidebar/FocusManager.cxx
index b77d30a75ba3..75622cde0ae3 100644
--- a/sfx2/source/sidebar/FocusManager.cxx
+++ b/sfx2/source/sidebar/FocusManager.cxx
@@ -222,7 +222,10 @@ void FocusManager::FocusPanel (
         rPanel.SetExpanded(true);
         pTitleBar->GetExpander().grab_focus();
     }
-    else if (bFallbackToDeckTitle)
+    // Fallback to deck title should only be applicable when there is more 
than one panel,
+    // or else it will never be possible to enter the panel contents when 
there's a single panel
+    // withouth a titlebar and expander
+    else if (bFallbackToDeckTitle && maPanels.size() > 1)
     {
         // The panel title is not visible, fall back to the deck
         // title.
@@ -348,11 +351,6 @@ bool FocusManager::HandleKeyEvent(
         case KEY_RETURN:
             switch (aLocation.meComponent)
             {
-                case PC_DeckToolBox:
-                    FocusButton(0);
-                    bConsumed = true;
-                    break;
-
                 case PC_PanelTitle:
                     // Enter the panel.
                     FocusPanelContent(aLocation.mnIndex);
@@ -381,19 +379,25 @@ bool FocusManager::HandleKeyEvent(
                     break;
 
                 case PC_DeckToolBox:
-                    bConsumed = MoveFocusInsideDeckTitle(aLocation, 
nDirection);
+                    {
+                        // Moves to the first deck activation button that is 
visible
+                        sal_Int32 nIndex(1);
+                        while(!maButtons[nIndex]->get_visible() && ++nIndex > 
0);
+                        FocusButton(nIndex);
+                        bConsumed = true;
+                    }
                     break;
 
                 case PC_TabBar:
                     if (rKeyCode.IsShift())
-                        FocusPanel(maPanels.size()-1, true);
-                    else
                     {
                         if (IsDeckTitleVisible())
                             FocusDeckTitle();
                         else
                             FocusPanel(0, true);
                     }
+                    else
+                        FocusPanel(0, true);
                     bConsumed = true;
                     break;
 
@@ -424,27 +428,22 @@ bool FocusManager::HandleKeyEvent(
                     bConsumed = true;
                     break;
 
-                case PC_DeckToolBox:
-                {
-                    // Focus the last button.
-                    sal_Int32 nIndex(maButtons.size()-1);
-                    while(!maButtons[nIndex]->get_visible() && --nIndex > 0);
-                    FocusButton(nIndex);
-                    bConsumed = true;
-                    break;
-                }
-
                 case PC_TabBar:
-                    // Go to previous tab bar item.
-                    if (aLocation.mnIndex == 0)
-                        FocusPanel(maPanels.size()-1, true);
-                    else
                     {
-                        sal_Int32 nIndex((aLocation.mnIndex + maButtons.size() 
- 1) % maButtons.size());
+                        if (rKeyCode.GetCode() == KEY_LEFT)
+                            break;
+
+                        sal_Int32 nIndex;
+                        if (aLocation.mnIndex <= 0)
+                            nIndex = maButtons.size() - 1;
+                        else
+                            nIndex = aLocation.mnIndex - 1;
+
+                        // Finds the previous visible button
                         while(!maButtons[nIndex]->get_visible() && --nIndex > 
0);
                         FocusButton(nIndex);
+                        bConsumed = true;
                     }
-                    bConsumed = true;
                     break;
 
                 default:
@@ -466,33 +465,22 @@ bool FocusManager::HandleKeyEvent(
                     bConsumed = true;
                     break;
 
-                case PC_DeckToolBox:
-                    // Focus the first panel.
-                    if (IsPanelTitleVisible(0))
-                        FocusPanel(0, false);
-                    else
-                        FocusButton(0);
-                    bConsumed = true;
-                    break;
-
                 case PC_TabBar:
-                    // Go to next tab bar item.
-                    if (aLocation.mnIndex < 
static_cast<sal_Int32>(maButtons.size())-1)
                     {
-                        sal_Int32 nIndex(aLocation.mnIndex + 1);
-                        while(!maButtons[nIndex]->get_visible() && ++nIndex < 
static_cast<sal_Int32>(maButtons.size()));
-                        if (nIndex < static_cast<sal_Int32>(maButtons.size()))
-                        {
-                            FocusButton(nIndex);
-                            bConsumed = true;
+                        if (rKeyCode.GetCode() == KEY_RIGHT)
                             break;
-                        }
+
+                        sal_Int32 nIndex;
+                        if (o3tl::make_unsigned(aLocation.mnIndex) >= 
maButtons.size() - 1)
+                            nIndex = 0;
+                        else
+                            nIndex = aLocation.mnIndex + 1;
+
+                        // Finds the next visible button
+                        while(!maButtons[nIndex]->get_visible() && ++nIndex > 
0);
+                        FocusButton(nIndex);
+                        bConsumed = true;
                     }
-                    if (IsDeckTitleVisible())
-                        FocusDeckTitle();
-                    else
-                        FocusPanel(0, true);
-                    bConsumed = true;
                     break;
 
                 default:
diff --git a/sfx2/source/sidebar/ResourceManager.cxx 
b/sfx2/source/sidebar/ResourceManager.cxx
index 7989d2820263..d4e5b9722815 100644
--- a/sfx2/source/sidebar/ResourceManager.cxx
+++ b/sfx2/source/sidebar/ResourceManager.cxx
@@ -278,6 +278,7 @@ void ResourceManager::ReadDeckList()
         rDeckDescriptor.msTitleBarIconURL = getString(aDeckNode, 
"TitleBarIconURL");
         rDeckDescriptor.msHighContrastTitleBarIconURL = getString(aDeckNode, 
"HighContrastTitleBarIconURL");
         rDeckDescriptor.msHelpText = rDeckDescriptor.msTitle;
+        rDeckDescriptor.msHelpId = "SIDEBAR_" + 
rDeckDescriptor.msId.toAsciiUpperCase();
         rDeckDescriptor.mnOrderIndex = getInt32(aDeckNode, "OrderIndex");
         rDeckDescriptor.mbExperimental = getBool(aDeckNode, "IsExperimental");
 
diff --git a/sfx2/source/sidebar/TitleBar.cxx b/sfx2/source/sidebar/TitleBar.cxx
index edab6d58b811..5bcf712dcf16 100644
--- a/sfx2/source/sidebar/TitleBar.cxx
+++ b/sfx2/source/sidebar/TitleBar.cxx
@@ -18,6 +18,8 @@
  */
 
 #include <sidebar/TitleBar.hxx>
+#include <vcl/help.hxx>
+#include <vcl/svapp.hxx>
 
 namespace sfx2::sidebar {
 
@@ -27,6 +29,7 @@ TitleBar::TitleBar(weld::Builder& rBuilder, Theme::ThemeItem 
eThemeItem)
     , mxAddonImage(rBuilder.weld_image("addonimage"))
     , mxToolBox(rBuilder.weld_toolbar("toolbar"))
     , meThemeItem(eThemeItem)
+    , msToolBoxRId("")
 {
     SetBackground();
 
@@ -70,8 +73,16 @@ void TitleBar::SetIcon(const 
css::uno::Reference<css::graphic::XGraphic>& rIcon)
     mxAddonImage->set_visible(rIcon.is());
 }
 
-IMPL_LINK_NOARG(TitleBar, SelectionHandler, const OUString&, void)
+void TitleBar::ShowHelp(const OUString& rHelpId)
 {
+    Help* pHelp = Application::GetHelp();
+    if (pHelp)
+        pHelp->Start(rHelpId);
+}
+
+IMPL_LINK(TitleBar, SelectionHandler, const OUString&, rId, void)
+{
+    msToolBoxRId = rId;
     HandleToolBoxItemClick();
 }
 
diff --git a/sfx2/uiconfig/ui/deck.ui b/sfx2/uiconfig/ui/deck.ui
index ca3c96dcfc7f..b4854579b77b 100644
--- a/sfx2/uiconfig/ui/deck.ui
+++ b/sfx2/uiconfig/ui/deck.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.38.2 -->
+<!-- Generated with glade 3.40.0 -->
 <interface domain="sfx">
   <requires lib="gtk+" version="3.20"/>
   <!-- n-columns=1 n-rows=2 -->
@@ -96,13 +96,33 @@
             <property name="show-arrow">False</property>
             <property name="icon_size">2</property>
             <child>
-              <object class="GtkToolButton" id="button">
+              <object class="GtkToolButton" id="btn_help">
                 <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="tooltip-text" translatable="yes" 
context="deck|SFX_STR_SIDEBAR_HELP_DECK">Help about this sidebar deck</property>
+                <property name="halign">center</property>
+                <property name="valign">center</property>
+                <property name="label">?</property>
+                <child internal-child="accessible">
+                  <object class="AtkObject" id="btn_help-atkobject">
+                    <property name="AtkObject::accessible-name" 
translatable="yes" context="deck|SFX_STR_SIDEBAR_HELP_DECK">Sidebar Deck 
Help</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="homogeneous">False</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkToolButton" id="btn_close">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
                 <property name="tooltip-text" translatable="yes" 
context="deck|SFX_STR_SIDEBAR_CLOSE_DECK">Close Sidebar Deck</property>
                 <property name="use-underline">True</property>
                 <property name="icon-name">window-close-symbolic</property>
                 <child internal-child="accessible">
-                  <object class="AtkObject" id="button-atkobject">
+                  <object class="AtkObject" id="btn_close-atkobject">
                     <property name="AtkObject::accessible-name" 
translatable="yes" context="deck|SFX_STR_SIDEBAR_CLOSE_DECK">Close Sidebar 
Deck</property>
                   </object>
                 </child>
diff --git a/sw/qa/uitest/sidebar/tdf152921.py 
b/sw/qa/uitest/sidebar/tdf152921.py
index a313343f5690..77f0370e2de1 100644
--- a/sw/qa/uitest/sidebar/tdf152921.py
+++ b/sw/qa/uitest/sidebar/tdf152921.py
@@ -25,7 +25,7 @@ class tdf152921(UITestCase):
 
             # make sure only the tabbar is visible, no deck
             xDeckTitleToolBar = xWriterEdit.getChild('toolbar')
-            xDeckTitleToolBar.executeAction("CLICK", mkPropertyValues({"POS": 
"0"}))
+            xDeckTitleToolBar.executeAction("CLICK", mkPropertyValues({"POS": 
"1"}))
             # tabbar is visible, deck is not
             # without the patch this assert would fail, a tab would be 
highlighted
             
self.assertFalse(len(get_state_as_dict(xTabBar)['HighlightedTabsIds']))
@@ -37,7 +37,7 @@ class tdf152921(UITestCase):
             
self.assertEqual(len(get_state_as_dict(xTabBar)['HighlightedTabsIds'].split(",")),
 1)
 
             # click on the 'Close Sidebar Deck' button in the deck title tool 
bar
-            xDeckTitleToolBar.executeAction("CLICK", mkPropertyValues({"POS": 
"0"}))
+            xDeckTitleToolBar.executeAction("CLICK", mkPropertyValues({"POS": 
"1"}))
             # without the patch this assert would fail, a tab would be 
highlighted
             
self.assertFalse(len(get_state_as_dict(xTabBar)['HighlightedTabsIds']))
 
@@ -63,7 +63,7 @@ class tdf152921(UITestCase):
             
self.assertEqual(len(get_state_as_dict(xTabBar)['HighlightedTabsIds'].split(",")),
 1)
 
             # click on the 'Close Sidebar Deck' button
-            xDeckTitleToolBar.executeAction("CLICK", mkPropertyValues({"POS": 
"0"}))
+            xDeckTitleToolBar.executeAction("CLICK", mkPropertyValues({"POS": 
"1"}))
             # without the patch this assert would fail, a tab would be 
highlighted
             
self.assertFalse(len(get_state_as_dict(xTabBar)['HighlightedTabsIds']))
 

Reply via email to