[Libreoffice-commits] core.git: sc/inc sc/source

Keigo Kawamura 2448848492 at mail.ecc.u-tokyo.ac.jp
Mon Jan 18 09:42:51 PST 2016


 sc/inc/globstr.hrc            |    5 -
 sc/source/ui/app/inputhdl.cxx |  200 +++++++++++++++++++++++++++++++++++++++---
 sc/source/ui/inc/inputhdl.hxx |    1 
 sc/source/ui/src/globstr.src  |    8 +
 4 files changed, 200 insertions(+), 14 deletions(-)

New commits:
commit b2a82d9bb256516ac589350579b90f43b68bd452
Author: Keigo Kawamura <2448848492 at mail.ecc.u-tokyo.ac.jp>
Date:   Mon Nov 16 20:39:06 2015 +0900

    tdf#95878 made more useful function suggestion system in formula editing
    
    I made function list suggestion and description tip in libreoffice calc.
    This change give us a nice function suggestion and easy function input.
    For example if I write "=i" then calc suggests
    "[if], iferror, ifna, and 50 more". You should only choice the function
    you would write with Ctrl-Tab and Ctrl-Shift-Tab, and then type Enter.
    Also there is a description of suggesting function, so even if you
    do not know the true name of the function you want to write, you can
    find the function.
    This change also give us a description of arguments of selected function.
    If I write "=i" and push enter key, then calc show "=if()" and
    a description of arguments of function "if()".
    
    Change-Id: Icd5ad04ea092fa39f27bb2776fd9e93649896baf
    Reviewed-on: https://gerrit.libreoffice.org/20035
    Reviewed-by: Eike Rathke <erack at redhat.com>
    Tested-by: Eike Rathke <erack at redhat.com>

diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc
index 3522387..5fa3e40 100644
--- a/sc/inc/globstr.hrc
+++ b/sc/inc/globstr.hrc
@@ -703,7 +703,10 @@
 
 #define STR_TABLE_COUNT                 530
 
-#define SC_GLOBSTR_STR_COUNT            531     /**< the count of permanently resident strings */
+#define STR_FUNCTIONS_FOUND             531
+#define STR_FUNCTIONS_NAMEDESCS         532
+
+#define SC_GLOBSTR_STR_COUNT            533     /**< the count of permanently resident strings */
 
 #endif
 
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx
index 68db271..f672797 100644
--- a/sc/source/ui/app/inputhdl.cxx
+++ b/sc/source/ui/app/inputhdl.cxx
@@ -181,6 +181,102 @@ OUString getExactMatch(const ScTypedCaseStrSet& rDataSet, const OUString& rStrin
     return rString;
 }
 
+ScTypedCaseStrSet::const_iterator findTextAll(
+    const ScTypedCaseStrSet& rDataSet, ScTypedCaseStrSet::const_iterator itPos,
+    const OUString& rStart, ::std::vector< OUString > &rResultVec, bool bBack)
+{
+    rResultVec.clear(); // clear contents
+
+    size_t nCount = 0;
+    ScTypedCaseStrSet::const_iterator retit;
+    if ( bBack ) // Backwards
+    {
+        ScTypedCaseStrSet::const_reverse_iterator it, itEnd;
+        if ( itPos == rDataSet.end() )
+        {
+            it = rDataSet.rend();
+            --it;
+            itEnd = it;
+        }
+        else
+        {
+            it = rDataSet.rbegin();
+            size_t nPos = std::distance(rDataSet.begin(), itPos);
+            size_t nRPos = rDataSet.size() - 1 - nPos; // if itPos == rDataSet.end(), then nRPos = -1
+            std::advance(it, nRPos);
+            if ( it == rDataSet.rend() )
+                it = rDataSet.rbegin();
+            itEnd = it;
+        }
+        bool bFirstTime = true;
+
+        while ( it != itEnd || bFirstTime )
+        {
+            ++it;
+            if ( it == rDataSet.rend() ) // go to the first if reach the end
+                it = rDataSet.rbegin();
+
+            if ( bFirstTime )
+                bFirstTime = false;
+            const ScTypedStrData& rData = *it;
+            if ( rData.GetStringType() == ScTypedStrData::Value )
+                // skip values
+                continue;
+
+            if ( !ScGlobal::GetpTransliteration()->isMatch(rStart, rData.GetString()) )
+                // not a match
+                continue;
+
+            rResultVec.push_back(rData.GetString()); // set the match data
+            if ( nCount == 0 ) // convert the reverse iterator back to iterator.
+            {
+                // actually we want to do "retit = it;".
+                retit = rDataSet.begin();
+                size_t nRPos = std::distance(rDataSet.rbegin(), it);
+                size_t nPos = rDataSet.size() - 1 - nRPos;
+                std::advance(retit, nPos);
+            }
+            ++nCount;
+        }
+    }
+    else // Forwards
+    {
+        ScTypedCaseStrSet::const_iterator it, itEnd;
+        it = itPos;
+        if ( it == rDataSet.end() )
+            it = rDataSet.begin();
+        itEnd = it;
+        bool bFirstTime = true;
+
+        while ( it != itEnd || bFirstTime )
+        {
+            ++it;
+            if ( it == rDataSet.end() ) // go to the first if reach the end
+                it = rDataSet.begin();
+
+            if ( bFirstTime )
+                bFirstTime = false;
+            const ScTypedStrData& rData = *it;
+            if ( rData.GetStringType() == ScTypedStrData::Value )
+                // skip values
+                continue;
+
+            if ( !ScGlobal::GetpTransliteration()->isMatch(rStart, rData.GetString()) )
+                // not a match
+                continue;
+
+            rResultVec.push_back(rData.GetString()); // set the match data
+            if ( nCount == 0 )
+                retit = it; // remember first match iterator
+            ++nCount;
+        }
+    }
+
+    if ( nCount > 0 ) // at least one function has matched
+        return retit;
+    return rDataSet.end(); // no matching text found
+}
+
 void removeChars(OUString& rStr, sal_Unicode c)
 {
     OUStringBuffer aBuf(rStr);
@@ -914,14 +1010,30 @@ void ScInputHandler::ShowArgumentsTip( OUString& rSelText )
                                 aBuf.append(aNew.copy(0, nStartPosition));
                                 aBuf.append(static_cast<sal_Unicode>(0x25BA));
                                 aBuf.append(aNew.copy(nStartPosition));
+                                nArgs = ppFDesc->getParameterCount();
+                                sal_Int16 nVarArgsSet = 0;
+                                if ( nArgs >= PAIRED_VAR_ARGS )
+                                {
+                                    nVarArgsSet = 2;
+                                    nArgs -= PAIRED_VAR_ARGS - nVarArgsSet;
+                                }
+                                else if ( nArgs >= VAR_ARGS )
+                                {
+                                    nVarArgsSet = 1;
+                                    nArgs -= VAR_ARGS - nVarArgsSet;
+                                }
+                                if ( nVarArgsSet > 0 && nActive > nArgs )
+                                    nActive = nArgs - (nActive - nArgs) % nVarArgsSet;
+                                aBuf.append( ScGlobal::GetRscString( STR_FUNCTIONS_NAMEDESCS ) );
+                                aBuf.append( ppFDesc->getParameterDescription(nActive-1) );
                                 aNew = aBuf.makeStringAndClear();
-                                ShowTipBelow( aNew );
+                                ShowTip( aNew );
                                 bFound = true;
                             }
                         }
                         else
                         {
-                            ShowTipBelow( aNew );
+                            ShowTip( aNew );
                             bFound = true;
                         }
                     }
@@ -1038,6 +1150,64 @@ bool ScInputHandler::GetFuncName( OUString& aStart, OUString& aResult )
     return true;
 }
 
+void ScInputHandler::ShowFuncList( const ::std::vector< OUString > & rFuncStrVec )
+{
+    OUString aTipStr;
+    OUString aFuncNameStr;
+    OUString aDescFuncNameStr;
+    ::std::vector<OUString>::const_iterator itStr = rFuncStrVec.begin();
+    sal_Int32 nMaxFindNumber = 3;
+    sal_Int32 nRemainFindNumber = nMaxFindNumber;
+    for ( ; itStr != rFuncStrVec.end(); ++itStr )
+    {
+        const OUString& rFunc = *itStr;
+        if ( rFunc[rFunc.getLength()-1] == cParenthesesReplacement )
+        {
+            aFuncNameStr = rFunc.copy(0, rFunc.getLength()-1);
+        }
+        else
+        {
+            aFuncNameStr = rFunc;
+        }
+        if ( itStr == rFuncStrVec.begin() )
+        {
+            aTipStr = "[";
+            aDescFuncNameStr = aFuncNameStr + "()";
+        }
+        else
+        {
+            aTipStr = aTipStr + ", ";
+        }
+        aTipStr = aTipStr + aFuncNameStr;
+        if ( itStr == rFuncStrVec.begin() )
+            aTipStr += "]";
+        if ( --nRemainFindNumber <= 0 )
+            break;
+    }
+    sal_Int32 nRemainNumber = rFuncStrVec.size() - nMaxFindNumber;
+    if ( nRemainFindNumber == 0 && nRemainNumber > 0 )
+    {
+        OUString aBufStr( aTipStr );
+        OUString aMessage( ScGlobal::GetRscString( STR_FUNCTIONS_FOUND ) );
+        aMessage = aMessage.replaceFirst("%2", OUString::number( nRemainNumber, 10));
+        aMessage = aMessage.replaceFirst("%1", aBufStr);
+        aTipStr = aMessage;
+    }
+    FormulaHelper aHelper(ScGlobal::GetStarCalcFunctionMgr());
+    sal_Int32 nNextFStart = 0;
+    const IFunctionDescription* ppFDesc;
+    ::std::vector< OUString > aArgs;
+    OUString eqPlusFuncName = "=" + aDescFuncNameStr;
+    if ( aHelper.GetNextFunc( eqPlusFuncName, false, nNextFStart, NULL, &ppFDesc, &aArgs ) )
+    {
+        if ( !ppFDesc->getFunctionName().isEmpty() )
+        {
+            aTipStr += ScGlobal::GetRscString( STR_FUNCTIONS_NAMEDESCS ) + ppFDesc->getDescription();
+        }
+    }
+    ShowTip( aTipStr );
+}
+
 void ScInputHandler::UseFormulaData()
 {
     EditView* pActiveView = pTopView ? pTopView : pTableView;
@@ -1070,10 +1240,10 @@ void ScInputHandler::UseFormulaData()
             if ( GetFuncName( aSelText, aText ) )
             {
                 // function name is incomplete:
-                // show first matching function name as tip above cell
-                OUString aNew;
+                // show matching functions name as tip above cell
+                ::std::vector<OUString> aNewVec;
                 miAutoPosFormula = pFormulaData->end();
-                miAutoPosFormula = findText(*pFormulaData, miAutoPosFormula, aText, aNew, false);
+                miAutoPosFormula = findTextAll(*pFormulaData, miAutoPosFormula, aText, aNewVec, false);
                 if (miAutoPosFormula != pFormulaData->end())
                 {
                     // check if partial function name is not Between quotes
@@ -1086,9 +1256,7 @@ void ScInputHandler::UseFormulaData()
                     if ( bBetweenQuotes )
                         return;  // we're between quotes
 
-                    if (aNew[aNew.getLength()-1] == cParenthesesReplacement)
-                        aNew = aNew.copy( 0, aNew.getLength()-1) + "()";
-                    ShowTip( aNew );
+                    ShowFuncList(aNewVec);
                     aAutoSearch = aText;
                 }
                 return;
@@ -1106,14 +1274,12 @@ void ScInputHandler::NextFormulaEntry( bool bBack )
     EditView* pActiveView = pTopView ? pTopView : pTableView;
     if ( pActiveView && pFormulaData )
     {
-        OUString aNew;
-        ScTypedCaseStrSet::const_iterator itNew = findText(*pFormulaData, miAutoPosFormula, aAutoSearch, aNew, bBack);
+        ::std::vector<OUString> aNewVec;
+        ScTypedCaseStrSet::const_iterator itNew = findTextAll(*pFormulaData, miAutoPosFormula, aAutoSearch, aNewVec, bBack);
         if (itNew != pFormulaData->end())
         {
             miAutoPosFormula = itNew;
-            if (aNew[aNew.getLength()-1] == cParenthesesReplacement)
-                aNew = aNew.copy( 0, aNew.getLength()-1) + "()";
-            ShowTip(aNew); // Display a quick help
+            ShowFuncList( aNewVec );
         }
     }
 
@@ -3231,6 +3397,14 @@ bool ScInputHandler::KeyInput( const KeyEvent& rKEvt, bool bStartEdit /* = false
                 {
                     ShowTipCursor();
                 }
+                if( bUsed && bFormulaMode && nCode == KEY_BACKSPACE )
+                {
+                    if (bFormulaMode)
+                        UseFormulaData();
+                    else
+                        UseColData();
+                }
+
             }
 
             // #i114511# don't count cursor keys as modification
diff --git a/sc/source/ui/inc/inputhdl.hxx b/sc/source/ui/inc/inputhdl.hxx
index 5532f52..c41171c 100644
--- a/sc/source/ui/inc/inputhdl.hxx
+++ b/sc/source/ui/inc/inputhdl.hxx
@@ -208,6 +208,7 @@ public:
     void            ShowTipCursor();
     void            ShowTip( const OUString& rText );     // at Cursor
     void            ShowTipBelow( const OUString& rText );
+    void            ShowFuncList( const ::std::vector< OUString > & rFuncStrVec );
 
     void            SetRefScale( const Fraction& rX, const Fraction& rY );
     void            UpdateRefDevice();
diff --git a/sc/source/ui/src/globstr.src b/sc/source/ui/src/globstr.src
index 8ebb2c6..3d69832 100644
--- a/sc/source/ui/src/globstr.src
+++ b/sc/source/ui/src/globstr.src
@@ -2097,6 +2097,14 @@ Resource RID_GLOBSTR
     {
         Text [ en-US ] = "Sheet %1 of %2";
     };
+    String STR_FUNCTIONS_FOUND
+    {
+        Text [ en-US ] = "%1 and %2 more";
+    };
+    String STR_FUNCTIONS_NAMEDESCS
+    {
+        Text [ en-US ] = " : ";
+    };
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list