[Libreoffice-commits] .: offapi/com offapi/UnoApi_offapi.mk oox/source sc/inc sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Wed Jan 4 18:22:31 PST 2012


 offapi/UnoApi_offapi.mk                                |    1 
 offapi/com/sun/star/chart2/data/XSheetDataProvider.idl |   52 ++++++
 oox/source/xls/excelchartconverter.cxx                 |   67 +++++---
 sc/inc/chart2uno.hxx                                   |   18 +-
 sc/source/ui/unoobj/chart2uno.cxx                      |  131 +++++++++++++++++
 5 files changed, 239 insertions(+), 30 deletions(-)

New commits:
commit 578292d707077c18079de050c928afaae268a25d
Author: Kohei Yoshida <kohei.yoshida at suse.com>
Date:   Wed Jan 4 15:45:09 2012 -0500

    Register chart data ranges via tokens rather than string.
    
    Doing it this way avoids having to re-generate the data ranges in
    Calc A1 before passing it to the chart backend in Calc.  We need this
    in order to remove the silly restriction that forces us to always pass
    data range strings in Calc A1 format, which is error-prone.
    
    This is also necessary in order to fix the bug that prevents editing
    data ranges of an existing chart when the formula syntax is something
    other than Calc A1.

diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index e83b667..b6c4bd4 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -1983,6 +1983,7 @@ $(eval $(call gb_UnoApiTarget_add_idlfiles,offapi,offapi/com/sun/star/chart2/dat
 	XNumericalDataSequence \
 	XRangeHighlighter \
 	XRangeXMLConversion \
+	XSheetDataProvider \
 	XTextualDataSequence \
 ))
 $(eval $(call gb_UnoApiTarget_add_idlfiles,offapi,offapi/com/sun/star/configuration,\
diff --git a/offapi/com/sun/star/chart2/data/XSheetDataProvider.idl b/offapi/com/sun/star/chart2/data/XSheetDataProvider.idl
new file mode 100644
index 0000000..db443c9
--- /dev/null
+++ b/offapi/com/sun/star/chart2/data/XSheetDataProvider.idl
@@ -0,0 +1,52 @@
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Major Contributor(s):
+ *   Copyright (C) 2012 Kohei Yoshida <kohei.yoshida at suse.com>
+ *
+ * All Rights Reserved.
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+
+#ifndef com_sun_star_chart2_data_XSheetDataProvider_idl
+#define com_sun_star_chart2_data_XSheetDataProvider_idl
+
+#include <com/sun/star/uno/XInterface.idl>
+#include <com/sun/star/chart2/data/XDataSequence.idl>
+#include <com/sun/star/sheet/FormulaToken.idl>
+
+module com { module sun { module star { module chart2 { module data {
+
+/**
+ * Interface specific to spreadsheet data provider backend.
+ */
+interface XSheetDataProvider : com::sun::star::uno::XInterface
+{
+    boolean createDataSequenceByFormulaTokensPossible(
+        [in] sequence< com::sun::star::sheet::FormulaToken > aTokens );
+
+    XDataSequence createDataSequenceByFormulaTokens(
+        [in] sequence< com::sun::star::sheet::FormulaToken > aTokens )
+        raises( com::sun::star::lang::IllegalArgumentException );
+};
+
+};};};};};
+
+#endif
diff --git a/oox/source/xls/excelchartconverter.cxx b/oox/source/xls/excelchartconverter.cxx
index da938ea..2fb699d 100644
--- a/oox/source/xls/excelchartconverter.cxx
+++ b/oox/source/xls/excelchartconverter.cxx
@@ -31,6 +31,8 @@
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
 #include <com/sun/star/chart2/data/XDataProvider.hpp>
 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
+#include <com/sun/star/chart2/data/XSheetDataProvider.hpp>
+
 #include "oox/core/filterbase.hxx"
 #include "oox/drawingml/chart/datasourcemodel.hxx"
 #include "oox/helper/containerhelper.hxx"
@@ -79,42 +81,53 @@ Reference< XDataSequence > ExcelChartConverter::createDataSequence(
         const Reference< XDataProvider >& rxDataProvider, const DataSequenceModel& rDataSeq )
 {
     Reference< XDataSequence > xDataSeq;
-    if( rxDataProvider.is() )
+    if (!rxDataProvider.is())
+        return xDataSeq;
+
+    Reference<XSheetDataProvider> xSheetProvider(rxDataProvider, UNO_QUERY);
+    if (!xSheetProvider.is())
+        return xDataSeq;
+
+    if (!rDataSeq.maFormula.isEmpty())
     {
-        OUString aRangeRep;
-        if( !rDataSeq.maFormula.isEmpty() )
-        {
-            // parse the formula string, create a token sequence
-            FormulaParser& rParser = getFormulaParser();
-            CellAddress aBaseAddr( getCurrentSheetIndex(), 0, 0 );
-            ApiTokenSequence aTokens = rParser.importFormula( aBaseAddr, rDataSeq.maFormula );
-
-            // create a range list from the token sequence
-            ApiCellRangeList aRanges;
-            rParser.extractCellRangeList( aRanges, aTokens, false );
-            aRangeRep = rParser.generateApiRangeListString( aRanges );
-        }
-        else if( !rDataSeq.maData.empty() )
-        {
-            // create a single-row array from constant source data
-            Matrix< Any > aMatrix( rDataSeq.maData.size(), 1 );
-            Matrix< Any >::iterator aMIt = aMatrix.begin();
-            // TODO: how to handle missing values in the map?
-            for( DataSequenceModel::AnyMap::const_iterator aDIt = rDataSeq.maData.begin(), aDEnd = rDataSeq.maData.end(); aDIt != aDEnd; ++aDIt, ++aMIt )
-                *aMIt = aDIt->second;
-            aRangeRep = FormulaProcessorBase::generateApiArray( aMatrix );
-        }
+        // parse the formula string, create a token sequence
+        FormulaParser& rParser = getFormulaParser();
+        CellAddress aBaseAddr( getCurrentSheetIndex(), 0, 0 );
+        ApiTokenSequence aTokens = rParser.importFormula( aBaseAddr, rDataSeq.maFormula );
 
-        if( !aRangeRep.isEmpty() ) try
+        try
         {
             // create the data sequence
-            xDataSeq = rxDataProvider->createDataSequenceByRangeRepresentation( aRangeRep );
+            xDataSeq = xSheetProvider->createDataSequenceByFormulaTokens(aTokens);
         }
-        catch( Exception& )
+        catch (Exception&)
         {
             OSL_FAIL( "ExcelChartConverter::createDataSequence - cannot create data sequence" );
         }
     }
+    else if (!rDataSeq.maData.empty())
+    {
+        // create a single-row array from constant source data
+        Matrix< Any > aMatrix( rDataSeq.maData.size(), 1 );
+        Matrix< Any >::iterator aMIt = aMatrix.begin();
+        // TODO: how to handle missing values in the map?
+        for( DataSequenceModel::AnyMap::const_iterator aDIt = rDataSeq.maData.begin(), aDEnd = rDataSeq.maData.end(); aDIt != aDEnd; ++aDIt, ++aMIt )
+            *aMIt = aDIt->second;
+        OUString aRangeRep = FormulaProcessorBase::generateApiArray( aMatrix );
+
+        if (!aRangeRep.isEmpty())
+        {
+            try
+            {
+                // create the data sequence
+                xDataSeq = rxDataProvider->createDataSequenceByRangeRepresentation( aRangeRep );
+            }
+            catch (Exception&)
+            {
+                OSL_FAIL( "ExcelChartConverter::createDataSequence - cannot create data sequence" );
+            }
+        }
+    }
     return xDataSeq;
 }
 
diff --git a/sc/inc/chart2uno.hxx b/sc/inc/chart2uno.hxx
index 544ab9b..86b14b2 100644
--- a/sc/inc/chart2uno.hxx
+++ b/sc/inc/chart2uno.hxx
@@ -38,6 +38,7 @@
 #include <svl/lstner.hxx>
 #include <com/sun/star/chart/ChartDataRowSource.hpp>
 #include <com/sun/star/chart2/data/XDataProvider.hpp>
+#include <com/sun/star/chart2/data/XSheetDataProvider.hpp>
 #include <com/sun/star/chart2/data/XRangeXMLConversion.hpp>
 #include <com/sun/star/chart2/data/XDataSource.hpp>
 #include <com/sun/star/chart2/data/XDataSequence.hpp>
@@ -50,8 +51,7 @@
 #include <com/sun/star/util/XCloneable.hpp>
 #include <com/sun/star/util/XModifyBroadcaster.hpp>
 #include <cppuhelper/implbase2.hxx>
-#include <cppuhelper/implbase4.hxx>
-#include <cppuhelper/implbase6.hxx>
+#include <cppuhelper/implbase5.hxx>
 #include <cppuhelper/implbase7.hxx>
 #include <rtl/ustring.hxx>
 #include <svl/itemprop.hxx>
@@ -69,8 +69,9 @@ class ScDocument;
 // DataProvider ==============================================================
 
 class ScChart2DataProvider : public
-                ::cppu::WeakImplHelper4<
+                ::cppu::WeakImplHelper5<
                     ::com::sun::star::chart2::data::XDataProvider,
+                    ::com::sun::star::chart2::data::XSheetDataProvider,
                     ::com::sun::star::chart2::data::XRangeXMLConversion,
                     ::com::sun::star::beans::XPropertySet,
                     ::com::sun::star::lang::XServiceInfo>,
@@ -110,6 +111,17 @@ public:
     virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XRangeSelection > SAL_CALL getRangeSelection()
         throw (::com::sun::star::uno::RuntimeException);
 
+    // XSheetDataProvider ----------------------------------------------------
+
+    virtual sal_Bool SAL_CALL createDataSequenceByFormulaTokensPossible(
+        const ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken >& aTokens )
+            throw (::com::sun::star::uno::RuntimeException);
+
+    virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSequence >
+        SAL_CALL createDataSequenceByFormulaTokens(
+            const ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken >& aTokens )
+                throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+
     // XRangeXMLConversion ---------------------------------------------------
 
     virtual ::rtl::OUString SAL_CALL convertRangeToXML( const ::rtl::OUString& sRangeRepresentation )
diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx
index 4865128..c9a1aad 100644
--- a/sc/source/ui/unoobj/chart2uno.cxx
+++ b/sc/source/ui/unoobj/chart2uno.cxx
@@ -42,6 +42,9 @@
 #include "reftokenhelper.hxx"
 #include "chartlis.hxx"
 #include "stlalgorithm.hxx"
+#include "tokenuno.hxx"
+
+#include "formula/opcode.hxx"
 
 #include <sfx2/objsh.hxx>
 #include <tools/table.hxx>
@@ -2103,6 +2106,134 @@ uno::Reference< sheet::XRangeSelection > SAL_CALL ScChart2DataProvider::getRange
     return xResult;
 }
 
+sal_Bool SAL_CALL ScChart2DataProvider::createDataSequenceByFormulaTokensPossible(
+    const Sequence<sheet::FormulaToken>& aTokens )
+        throw (uno::RuntimeException)
+{
+    if (aTokens.getLength() <= 0)
+        return false;
+
+    ScTokenArray aCode;
+    if (!ScTokenConversion::ConvertToTokenArray(*m_pDocument, aCode, aTokens))
+        return false;
+
+    sal_uInt16 n = aCode.GetLen();
+    if (!n)
+        return false;
+
+    const formula::FormulaToken* pFirst = aCode.First();
+    const formula::FormulaToken* pLast = aCode.GetArray()[n-1];
+    for (const formula::FormulaToken* p = aCode.First(); p; p = aCode.Next())
+    {
+        switch (p->GetType())
+        {
+            case svSep:
+            {
+                switch (p->GetOpCode())
+                {
+                    case ocSep:
+                        // separators are allowed.
+                    break;
+                    case ocOpen:
+                        if (p != pFirst)
+                            // open paran is allowed only as the first token.
+                            return false;
+                    break;
+                    case ocClose:
+                        if (p != pLast)
+                            // close paren is allowed only as the last token.
+                            return false;
+                    break;
+                    default:
+                        return false;
+                }
+            }
+            break;
+            case svSingleRef:
+            case svDoubleRef:
+            case svExternalSingleRef:
+            case svExternalDoubleRef:
+            break;
+            default:
+                return false;
+        }
+    }
+
+    return true;
+}
+
+Reference<chart2::data::XDataSequence> SAL_CALL
+ScChart2DataProvider::createDataSequenceByFormulaTokens(
+    const Sequence<sheet::FormulaToken>& aTokens )
+        throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+    Reference<chart2::data::XDataSequence> xResult;
+    if (aTokens.getLength() <= 0)
+        return xResult;
+
+    ScTokenArray aCode;
+    if (!ScTokenConversion::ConvertToTokenArray(*m_pDocument, aCode, aTokens))
+        return xResult;
+
+    sal_uInt16 n = aCode.GetLen();
+    if (!n)
+        return xResult;
+
+    vector<ScTokenRef> aRefTokens;
+    const formula::FormulaToken* pFirst = aCode.First();
+    const formula::FormulaToken* pLast = aCode.GetArray()[n-1];
+    for (const formula::FormulaToken* p = aCode.First(); p; p = aCode.Next())
+    {
+        switch (p->GetType())
+        {
+            case svSep:
+            {
+                switch (p->GetOpCode())
+                {
+                    case ocSep:
+                        // separators are allowed.
+                    break;
+                    case ocOpen:
+                        if (p != pFirst)
+                            // open paran is allowed only as the first token.
+                            throw lang::IllegalArgumentException();
+                    break;
+                    case ocClose:
+                        if (p != pLast)
+                            // close paren is allowed only as the last token.
+                            throw lang::IllegalArgumentException();
+                    break;
+                    default:
+                        throw lang::IllegalArgumentException();
+                }
+            }
+            break;
+            case svSingleRef:
+            case svDoubleRef:
+            case svExternalSingleRef:
+            case svExternalDoubleRef:
+            {
+                ScTokenRef pNew(static_cast<const ScToken*>(p->Clone()));
+                aRefTokens.push_back(pNew);
+            }
+            break;
+            default:
+                throw lang::IllegalArgumentException();
+        }
+    }
+
+    if (aRefTokens.empty())
+        return xResult;
+
+    shrinkToDataRange(m_pDocument, aRefTokens);
+
+    // ScChart2DataSequence manages the life cycle of pRefTokens.
+    vector<ScTokenRef>* pRefTokens = new vector<ScTokenRef>();
+    pRefTokens->swap(aRefTokens);
+    xResult.set(new ScChart2DataSequence(m_pDocument, this, pRefTokens, m_bIncludeHiddenCells));
+    return xResult;
+}
+
 // XRangeXMLConversion ---------------------------------------------------
 
 rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeToXML( const rtl::OUString& sRangeRepresentation )


More information about the Libreoffice-commits mailing list