sc/source/ui/formdlg/dwfunctr.cxx     |  137 +++++++++++++++++++++++++++++++---
 sc/source/ui/inc/dwfunctr.hxx         |    8 +
 sc/source/ui/view/tabvwsh3.cxx        |    3 
 sc/uiconfig/scalc/ui/functionpanel.ui |   36 ++++++++
 4 files changed, 166 insertions(+), 18 deletions(-)

New commits:
commit b5a8cdbd71a61c76f2b1a6ad33b0757911603184
Author:     Rafael Lima <rafael.palma.l...@gmail.com>
AuthorDate: Tue Jul 25 22:42:49 2023 +0200
Commit:     Rafael Lima <rafael.palma.l...@gmail.com>
CommitDate: Fri Sep 15 13:25:49 2023 +0200

    tdf#122718 Add search functionality to the Functions sidebar
    
    With this patch it is possible to search the list of functions in the 
Functions sidebar.
    
    To use this feature:
    1) In Calc, go to View - Function List
    2) The Functions sidebar will open with the "Search" entry focused
    3) You can now type your search
    4) With the "Search" entry focused, it is possible to use the arrow keys 
(up/down) to select the function to insert
    5) Press "Enter" to insert the function
    
    The Escape key will clear the search box and F1 will open the help page of 
the selected function.
    
    Change-Id: I1af6c1c2489ff736c44e1b3750bea21c05786602
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154917
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>
    Tested-by: Jenkins
    Reviewed-by: Rafael Lima <rafael.palma.l...@gmail.com>

diff --git a/sc/source/ui/formdlg/dwfunctr.cxx 
b/sc/source/ui/formdlg/dwfunctr.cxx
index 8fde50549be1..d158a4aada69 100644
--- a/sc/source/ui/formdlg/dwfunctr.cxx
+++ b/sc/source/ui/formdlg/dwfunctr.cxx
@@ -21,6 +21,7 @@
 #include <editeng/editview.hxx>
 #include <sfx2/viewsh.hxx>
 #include <formula/funcvarargs.h>
+#include <unotools/charclass.hxx>
 
 #include <global.hxx>
 #include <scmod.hxx>
@@ -29,6 +30,8 @@
 #include <funcdesc.hxx>
 
 #include <dwfunctr.hxx>
+#include <scresid.hxx>
+#include <strings.hrc>
 
 /*************************************************************************
 #*  Member:     ScFunctionWin
@@ -50,6 +53,7 @@ ScFunctionWin::ScFunctionWin(weld::Widget* pParent)
     , xFuncList(m_xBuilder->weld_tree_view("funclist"))
     , xInsertButton(m_xBuilder->weld_button("insert"))
     , xFiFuncDesc(m_xBuilder->weld_text_view("funcdesc"))
+    , m_xSearchString(m_xBuilder->weld_entry("search"))
     , xConfigListener(new 
comphelper::ConfigurationListener("/org.openoffice.Office.Calc/Formula/Syntax"))
     , 
xConfigChange(std::make_unique<EnglishFunctionNameChange>(xConfigListener, 
this))
     , pFuncDesc(nullptr)
@@ -57,11 +61,15 @@ ScFunctionWin::ScFunctionWin(weld::Widget* pParent)
     InitLRUList();
 
     nArgs=0;
-    m_aHelpId = xFuncList->get_help_id();
+    m_aListHelpId = xFuncList->get_help_id();
+    m_aSearchHelpId = m_xSearchString->get_help_id();
 
     // Description box has a height of 8 lines of text
     xFiFuncDesc->set_size_request(-1, 8 * xFiFuncDesc->get_text_height());
 
+    m_xSearchString->connect_changed(LINK(this, ScFunctionWin, ModifyHdl));
+    m_xSearchString->connect_key_press(LINK(this, ScFunctionWin, KeyInputHdl));
+
     xCatBox->connect_changed(LINK( this, ScFunctionWin, SelComboHdl));
     xFuncList->connect_changed(LINK( this, ScFunctionWin, SelTreeHdl));
 
@@ -100,7 +108,7 @@ ScFunctionWin::~ScFunctionWin()
 }
 
 /*************************************************************************
-#*  Member:     UpdateFunctionList
+#*  Member:     InitLRUList
 #*------------------------------------------------------------------------
 #*
 #*  Class:      ScFunctionWin
@@ -121,11 +129,11 @@ void ScFunctionWin::InitLRUList()
     sal_Int32 nSelPos  = xCatBox->get_active();
 
     if (nSelPos == 0)
-        UpdateFunctionList();
+        UpdateFunctionList("");
 }
 
 /*************************************************************************
-#*  Member:     UpdateFunctionList
+#*  Member:     UpdateLRUList
 #*------------------------------------------------------------------------
 #*
 #*  Class:      ScFunctionWin
@@ -183,7 +191,7 @@ void ScFunctionWin::SetDescription()
         if (!sHelpId.isEmpty())
             xFuncList->set_help_id(pDesc->getHelpId());
         else
-            xFuncList->set_help_id(m_aHelpId);
+            xFuncList->set_help_id(m_aListHelpId);
     }
 }
 
@@ -195,13 +203,13 @@ void ScFunctionWin::SetDescription()
 #*
 #*  Function:   Updates the list of functions depending on the set category
 #*
-#*  Input:      ---
+#*  Input:      Search string used to filter the list of functions
 #*
 #*  Output:     ---
 #*
 #************************************************************************/
 
-void ScFunctionWin::UpdateFunctionList()
+void ScFunctionWin::UpdateFunctionList(const OUString& rSearchString)
 {
     sal_Int32  nSelPos   = xCatBox->get_active();
     sal_Int32  nCategory = ( -1 != nSelPos )
@@ -214,12 +222,32 @@ void ScFunctionWin::UpdateFunctionList()
     {
         ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr();
 
+        SvtSysLocale aSysLocale;
+        const CharClass& rCharClass = aSysLocale.GetCharClass();
+        const OUString aSearchStr(rCharClass.uppercase(rSearchString));
+
+        // First add the functions that start with the search string
         const ScFuncDesc* pDesc = pFuncMgr->First( nCategory );
         while ( pDesc )
         {
-            xFuncList->append(weld::toId(pDesc), *(pDesc->mxFuncName));
+            if (rSearchString.isEmpty()
+                || 
(rCharClass.uppercase(pDesc->getFunctionName()).startsWith(aSearchStr)))
+                xFuncList->append(weld::toId(pDesc), *(pDesc->mxFuncName));
             pDesc = pFuncMgr->Next();
         }
+
+        // Now add the functions that have the search string in the middle of 
the function name
+        // Note that this will only be necessary if the search string is not 
empty
+        if (!rSearchString.isEmpty())
+        {
+            pDesc = pFuncMgr->First( nCategory );
+            while ( pDesc )
+            {
+                if 
(rCharClass.uppercase(pDesc->getFunctionName()).indexOf(aSearchStr) > 0)
+                    xFuncList->append(weld::toId(pDesc), *(pDesc->mxFuncName));
+                pDesc = pFuncMgr->Next();
+            }
+        }
     }
     else // LRU list
     {
@@ -359,7 +387,90 @@ void ScFunctionWin::DoEnter()
 }
 
 /*************************************************************************
-#*  Handle:     SelHdl
+#*  Handle:     ModifyHdl
+#*------------------------------------------------------------------------
+#*
+#*  Class:      ScFunctionWin
+#*
+#*  Function:   Handles changes in the search text
+#*
+#************************************************************************/
+
+IMPL_LINK_NOARG(ScFunctionWin, ModifyHdl, weld::Entry&, void)
+{
+    // Switch to the "All" category when searching a function
+    xCatBox->set_active(1);
+    OUString searchStr = m_xSearchString->get_text();
+    UpdateFunctionList(searchStr);
+    SetDescription();
+}
+
+/*************************************************************************
+#*  Handle:     KeyInputHdl
+#*------------------------------------------------------------------------
+#*
+#*  Class:      ScFunctionWin
+#*
+#*  Function:   Processes key inputs when the serch entry has focus
+#*
+#************************************************************************/
+
+IMPL_LINK(ScFunctionWin, KeyInputHdl, const KeyEvent&, rEvent, bool)
+{
+    bool bHandled = false;
+
+    switch (rEvent.GetKeyCode().GetCode())
+    {
+    case KEY_RETURN:
+        {
+            DoEnter();
+            bHandled = true;
+        }
+        break;
+    case KEY_DOWN:
+        {
+            int nNewIndex = std::min(xFuncList->get_selected_index() + 1, 
xFuncList->n_children() - 1);
+            xFuncList->select(nNewIndex);
+            SetDescription();
+            bHandled = true;
+        }
+        break;
+    case KEY_UP:
+        {
+            int nNewIndex = std::max(xFuncList->get_selected_index() - 1, 0);
+            xFuncList->select(nNewIndex);
+            SetDescription();
+            bHandled = true;
+        }
+        break;
+    case KEY_ESCAPE:
+        {
+            m_xSearchString->set_text("");
+            UpdateFunctionList("");
+            bHandled = true;
+        }
+        break;
+    case KEY_F1:
+        {
+            const ScFuncDesc* pDesc = weld::fromId<const 
ScFuncDesc*>(xFuncList->get_selected_id());
+            OUString sHelpId;
+            if (pDesc)
+                sHelpId = pDesc->getHelpId();
+
+            if (!sHelpId.isEmpty())
+                m_xSearchString->set_help_id(sHelpId);
+            else
+                m_xSearchString->set_help_id(m_aSearchHelpId);
+            bHandled = false;
+        }
+        break;
+    }
+
+    return bHandled;
+}
+
+/*************************************************************************
+#*  Handle:     SelComboHdl
 #*------------------------------------------------------------------------
 #*
 #*  Class:      ScFunctionWin
@@ -374,8 +485,10 @@ void ScFunctionWin::DoEnter()
 
 IMPL_LINK_NOARG(ScFunctionWin, SelComboHdl, weld::ComboBox&, void)
 {
-    UpdateFunctionList();
+    UpdateFunctionList("");
     SetDescription();
+    m_xSearchString->set_text("");
+    m_xSearchString->grab_focus();
 }
 
 IMPL_LINK_NOARG(ScFunctionWin, SelTreeHdl, weld::TreeView&, void)
@@ -384,7 +497,7 @@ IMPL_LINK_NOARG(ScFunctionWin, SelTreeHdl, weld::TreeView&, 
void)
 }
 
 /*************************************************************************
-#*  Handle:     SelHdl
+#*  Handle:     SetSelectionClickHdl
 #*------------------------------------------------------------------------
 #*
 #*  Class:      ScFunctionWin
@@ -412,7 +525,7 @@ void EnglishFunctionNameChange::setProperty(const 
css::uno::Any &rProperty)
 {
     ConfigurationListenerProperty::setProperty(rProperty);
     m_pFunctionWin->InitLRUList();
-    m_pFunctionWin->UpdateFunctionList();
+    m_pFunctionWin->UpdateFunctionList("");
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/dwfunctr.hxx b/sc/source/ui/inc/dwfunctr.hxx
index b6d0d032a857..faf68ecd4198 100644
--- a/sc/source/ui/inc/dwfunctr.hxx
+++ b/sc/source/ui/inc/dwfunctr.hxx
@@ -47,12 +47,14 @@ private:
     std::unique_ptr<weld::TreeView> xFuncList;
     std::unique_ptr<weld::Button> xInsertButton;
     std::unique_ptr<weld::TextView> xFiFuncDesc;
+    std::unique_ptr<weld::Entry> m_xSearchString;
 
     rtl::Reference<comphelper::ConfigurationListener> xConfigListener;
     std::unique_ptr<EnglishFunctionNameChange> xConfigChange;
     const ScFuncDesc*   pFuncDesc;
     sal_uInt16          nArgs;
-    OUString m_aHelpId;
+    OUString m_aListHelpId;
+    OUString m_aSearchHelpId;
 
     ::std::vector< const formula::IFunctionDescription*> aLRUList;
 
@@ -64,6 +66,8 @@ private:
                     DECL_LINK( SetSelectionClickHdl, weld::Button&, void );
                     DECL_LINK( SelComboHdl, weld::ComboBox&, void );
                     DECL_LINK( SelTreeHdl, weld::TreeView&, void );
+                    DECL_LINK( ModifyHdl, weld::Entry&, void );
+                    DECL_LINK( KeyInputHdl, const KeyEvent&, bool);
 
 public:
     ScFunctionWin(weld::Widget* pParent);
@@ -71,7 +75,7 @@ public:
     virtual ~ScFunctionWin() override;
 
     void            InitLRUList();
-    void            UpdateFunctionList();
+    void            UpdateFunctionList(const OUString&);
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/tabvwsh3.cxx b/sc/source/ui/view/tabvwsh3.cxx
index ce0453040461..60754c58baff 100644
--- a/sc/source/ui/view/tabvwsh3.cxx
+++ b/sc/source/ui/view/tabvwsh3.cxx
@@ -677,7 +677,8 @@ void ScTabViewShell::Execute( SfxRequest& rReq )
                 rThisFrame.ShowChildWindow(SID_SIDEBAR);
 
                 ::sfx2::sidebar::Sidebar::ShowPanel(u"ScFunctionsPanel",
-                                                    
rThisFrame.GetFrame().GetFrameInterface());
+                                                    
rThisFrame.GetFrame().GetFrameInterface(),
+                                                    true);
                 rReq.Done ();
             }
             break;
diff --git a/sc/uiconfig/scalc/ui/functionpanel.ui 
b/sc/uiconfig/scalc/ui/functionpanel.ui
index 380bf7b6b651..c0682699776b 100644
--- a/sc/uiconfig/scalc/ui/functionpanel.ui
+++ b/sc/uiconfig/scalc/ui/functionpanel.ui
@@ -31,7 +31,7 @@
         <property name="border-width">6</property>
         <property name="row-spacing">6</property>
         <child>
-          <!-- n-columns=1 n-rows=2 -->
+          <!-- n-columns=1 n-rows=3 -->
           <object class="GtkGrid">
             <property name="visible">True</property>
             <property name="can-focus">False</property>
@@ -94,7 +94,7 @@
               </object>
               <packing>
                 <property name="left-attach">0</property>
-                <property name="top-attach">0</property>
+                <property name="top-attach">1</property>
               </packing>
             </child>
             <child>
@@ -138,7 +138,37 @@
               </object>
               <packing>
                 <property name="left-attach">0</property>
-                <property name="top-attach">1</property>
+                <property name="top-attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">6</property>
+                <child>
+                  <object class="GtkEntry" id="search">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="hexpand">True</property>
+                    <property name="placeholder-text" translatable="yes" 
context="functionpanel|search">Search all functions</property>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" id="search-atkobject">
+                        <property name="AtkObject::accessible-name" 
translatable="yes" context="functionpanel|accessiblename|search">Search all 
functions</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
               </packing>
             </child>
           </object>

Reply via email to