sc/Library_sc.mk                  |    1 
 sc/inc/Sparkline.hxx              |   46 ++++++++++++++++++++++++++++++++++++++
 sc/inc/SparklineGroup.hxx         |   30 ++++++++++++++++++++++++
 sc/inc/column.hxx                 |   10 +++++++-
 sc/inc/document.hxx               |    7 +++++
 sc/inc/mtvelements.hxx            |   16 ++++++++++---
 sc/source/core/data/Sparkline.cxx |   22 ++++++++++++++++++
 sc/source/core/data/column.cxx    |    5 ++++
 sc/source/core/data/column2.cxx   |   10 ++++++++
 sc/source/core/data/column3.cxx   |    3 ++
 sc/source/core/data/document.cxx  |   27 ++++++++++++++++++++++
 11 files changed, 173 insertions(+), 4 deletions(-)

New commits:
commit e51784458bc46411d739877707f7952dd6808fa2
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Wed Feb 23 09:52:50 2022 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Tue Mar 8 10:09:14 2022 +0100

    sc: add Sparkline to the model as a column multi_type_vector
    
    This adds a Sparkline class and a SparklineGroup class. The
    Sparkline class is added to a cell, and the SparklineGroup
    is referenced by the Sparkline, so multiple Sparklines can
    share the same properties.
    
    Change-Id: Id309ded34bfa7a35c1be43f7c0543d88594e66ff
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131162
    Tested-by: Tomaž Vajngerl <qui...@gmail.com>
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 62ab22a797c4..11449217edd9 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -185,6 +185,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/core/data/sheetevents \
     sc/source/core/data/simpleformulacalc \
     sc/source/core/data/sortparam \
+    sc/source/core/data/Sparkline \
     sc/source/core/data/stlpool \
     sc/source/core/data/stlsheet \
     sc/source/core/data/subtotalparam \
diff --git a/sc/inc/Sparkline.hxx b/sc/inc/Sparkline.hxx
new file mode 100644
index 000000000000..c8bb4d1baa22
--- /dev/null
+++ b/sc/inc/Sparkline.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include "scdllapi.h"
+#include "SparklineGroup.hxx"
+#include "rangelst.hxx"
+#include <memory>
+
+namespace sc
+{
+/** Sparkline data, used for rendering the content of a cell
+ *
+ * Contains the input range of the data that is being drawn and a reference
+ * to the SparklineGroup, which inclues common properties of multiple
+ * sparklines.
+ */
+class SC_DLLPUBLIC Sparkline
+{
+private:
+    ScRangeList m_aInputRange;
+    std::shared_ptr<SparklineGroup> m_pSparklineGroup;
+
+public:
+    Sparkline(std::shared_ptr<SparklineGroup>& pSparklineGroup);
+
+    Sparkline(const Sparkline&) = delete;
+    Sparkline& operator=(const Sparkline&) = delete;
+
+    void setInputRange(ScRangeList const& rInputRange) { m_aInputRange = 
rInputRange; }
+    ScRangeList const& getInputRange() { return m_aInputRange; }
+
+    std::shared_ptr<SparklineGroup> const& getSparklineGroup() { return 
m_pSparklineGroup; }
+};
+
+} // end sc
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/SparklineGroup.hxx b/sc/inc/SparklineGroup.hxx
new file mode 100644
index 000000000000..6d98e1b2dcbf
--- /dev/null
+++ b/sc/inc/SparklineGroup.hxx
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#pragma once
+
+#include "scdllapi.h"
+#include <optional>
+
+namespace sc
+{
+/** Common properties for a group of sparklines */
+class SC_DLLPUBLIC SparklineGroup
+{
+public:
+    SparklineGroup() {}
+
+    SparklineGroup(const SparklineGroup&) = delete;
+    SparklineGroup& operator=(const SparklineGroup&) = delete;
+};
+
+} // end sc
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 55cf70e09d7f..503cbaebddb1 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -65,6 +65,7 @@ class CompileFormulaContext;
 struct SetFormulaDirtyContext;
 enum class MatrixEdge;
 class ColumnIterator;
+class Sparkline;
 
 }
 
@@ -99,7 +100,7 @@ struct ScInterpreterContext;
 
 struct ScNeededSizeOptions
 {
-    const ScPatternAttr*    pPattern;
+    const ScPatternAttr* pPattern;
     bool                bFormula;
     bool                bSkipMerged;
     bool                bGetFont;
@@ -173,6 +174,9 @@ class ScColumn : protected ScColumnData
     // Cell values.
     sc::CellStoreType maCells;
 
+    // Sparklines
+    sc::SparklineStoreType maSparklines;
+
     size_t mnBlkCountFormula;
 
     SCCOL           nCol;
@@ -640,6 +644,10 @@ public:
     void BroadcastCells( const std::vector<SCROW>& rRows, SfxHintId nHint );
     void BroadcastRows( SCROW nStartRow, SCROW nEndRow, SfxHintId nHint );
 
+    // Spaklines
+    sc::Sparkline* GetSparkline(SCROW nRow);
+    void SetSparkline(SCROW nRow, std::unique_ptr<sc::Sparkline> pSparkline);
+
     // cell notes
     ScPostIt* GetCellNote( SCROW nRow );
     const ScPostIt* GetCellNote( SCROW nRow ) const;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index bca8c4bea5f5..8870e607638d 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -101,6 +101,8 @@ class UpdatedRangeNames;
 class TableColumnBlockPositionSet;
 class ColumnIterator;
 class ExternalDataMapper;
+class Sparkline;
+class SparklineGroup;
 
 }
 
@@ -1241,6 +1243,10 @@ public:
      */
     sc::MultiDataCellState HasMultipleDataCells( const ScRange& rRange ) const;
 
+    /** Spaklines */
+    SC_DLLPUBLIC sc::Sparkline* GetSparkline(ScAddress const & rPosition);
+    SC_DLLPUBLIC sc::Sparkline* CreateSparkline(ScAddress const & rPosition, 
std::shared_ptr<sc::SparklineGroup> & pSparklineGroup);
+
     /** Notes **/
     SC_DLLPUBLIC ScPostIt*       GetNote(const ScAddress& rPos);
     SC_DLLPUBLIC ScPostIt*       GetNote(SCCOL nCol, SCROW nRow, SCTAB nTab);
@@ -1272,6 +1278,7 @@ public:
     SC_DLLPUBLIC void GetAllNoteEntries( std::vector<sc::NoteEntry>& rNotes ) 
const;
     SC_DLLPUBLIC void GetAllNoteEntries( SCTAB nTab, 
std::vector<sc::NoteEntry>& rNotes ) const;
     void              GetNotesInRange( const ScRangeList& rRange, 
std::vector<sc::NoteEntry>& rNotes ) const;
+
     bool              ContainsNotesInRange( const ScRangeList& rRange ) const;
 
     SC_DLLPUBLIC void SetDrawPageSize(SCTAB nTab);
diff --git a/sc/inc/mtvelements.hxx b/sc/inc/mtvelements.hxx
index c74e1bc7d91b..6de0f3e7ec23 100644
--- a/sc/inc/mtvelements.hxx
+++ b/sc/inc/mtvelements.hxx
@@ -15,6 +15,7 @@
 #include <editeng/editobj.hxx>
 #include "calcmacros.hxx"
 #include "postit.hxx"
+#include "Sparkline.hxx"
 #include "celltextattr.hxx"
 
 #if DEBUG_COLUMN_STORAGE
@@ -49,6 +50,7 @@ const mdds::mtv::element_t element_type_edittext = 
mdds::mtv::element_type_user_
 const mdds::mtv::element_t element_type_formula = 
mdds::mtv::element_type_user_start + 4;
 
 const mdds::mtv::element_t element_type_cellnote = 
mdds::mtv::element_type_user_start + 5;
+const mdds::mtv::element_t element_type_sparkline = 
mdds::mtv::element_type_user_start + 6;
 
 /// Mapped standard element types (for convenience).
 const mdds::mtv::element_t element_type_numeric = 
mdds::mtv::element_type_double;
@@ -57,6 +59,7 @@ const mdds::mtv::element_t element_type_uint16 = 
mdds::mtv::element_type_uint16;
 
 /// Custom element blocks.
 
+typedef mdds::mtv::noncopyable_managed_element_block<element_type_sparkline, 
sc::Sparkline> sparkline_block;
 typedef mdds::mtv::noncopyable_managed_element_block<element_type_cellnote, 
ScPostIt> cellnote_block;
 typedef mdds::mtv::noncopyable_managed_element_block<element_type_broadcaster, 
SvtBroadcaster> broadcaster_block;
 typedef mdds::mtv::default_element_block<element_type_celltextattr, 
CellTextAttr> celltextattr_block;
@@ -68,8 +71,13 @@ typedef 
mdds::mtv::noncopyable_managed_element_block<element_type_formula, ScFor
 typedef mdds::mtv::double_element_block numeric_block;
 typedef mdds::mtv::uint16_element_block uint16_block;
 
-/// This needs to be in the same namespace as CellTextAttr.
+} // end sc namespace
+
+/// CAUTION! The following defines must be in the same namespace as the 
respective type.
+/// For example sc types like sc::CellTextAttr, ScFormulaCell in global 
namespace.
+namespace sc {
 MDDS_MTV_DEFINE_ELEMENT_CALLBACKS(CellTextAttr, element_type_celltextattr, 
CellTextAttr(), celltextattr_block)
+MDDS_MTV_DEFINE_ELEMENT_CALLBACKS_PTR(Sparkline, sc::element_type_sparkline, 
nullptr, sc::sparkline_block)
 }
 
 /// These need to be in global namespace just like their respective types are.
@@ -79,9 +87,7 @@ MDDS_MTV_DEFINE_ELEMENT_CALLBACKS_PTR(ScFormulaCell, 
sc::element_type_formula, n
 MDDS_MTV_DEFINE_ELEMENT_CALLBACKS_PTR(EditTextObject, 
sc::element_type_edittext, nullptr, sc::edittext_block)
 
 namespace svl {
-
 MDDS_MTV_DEFINE_ELEMENT_CALLBACKS(SharedString, sc::element_type_string, 
SharedString(), sc::string_block)
-
 }
 
 namespace sc {
@@ -110,6 +116,10 @@ struct CellStoreTrait
     static constexpr mdds::mtv::lu_factor_t loop_unrolling = 
mdds::mtv::lu_factor_t::lu16;
 };
 
+/// Sparkline container
+typedef mdds::mtv::custom_block_func1<sc::sparkline_block> CSparklineFunction;
+typedef mdds::mtv::soa::multi_type_vector<CSparklineFunction> 
SparklineStoreType;
+
 /// Cell note container
 typedef mdds::mtv::custom_block_func1<sc::cellnote_block> CNoteFunc;
 typedef mdds::mtv::soa::multi_type_vector<CNoteFunc> CellNoteStoreType;
diff --git a/sc/source/core/data/Sparkline.cxx 
b/sc/source/core/data/Sparkline.cxx
new file mode 100644
index 000000000000..301fda820ff2
--- /dev/null
+++ b/sc/source/core/data/Sparkline.cxx
@@ -0,0 +1,22 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <memory>
+#include <Sparkline.hxx>
+
+namespace sc
+{
+Sparkline::Sparkline(std::shared_ptr<SparklineGroup>& pSparklineGroup)
+    : m_pSparklineGroup(pSparklineGroup)
+{
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 0598a24858e0..d75d9885fba6 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -84,6 +84,7 @@ ScColumn::ScColumn(ScSheetLimits const & rSheetLimits) :
     maCellNotes(rSheetLimits.GetMaxRowCount()),
     maBroadcasters(rSheetLimits.GetMaxRowCount()),
     maCells(sc::CellStoreEvent(this)),
+    maSparklines(rSheetLimits.GetMaxRowCount()),
     mnBlkCountFormula(0),
     nCol( 0 ),
     nTab( 0 ),
@@ -776,6 +777,9 @@ void ScColumn::InsertRow( SCROW nStartRow, SCSIZE nSize )
     maCellNotes.insert_empty(nStartRow, nSize);
     maCellNotes.resize(GetDoc().GetMaxRowCount());
 
+    maSparklines.insert_empty(nStartRow, nSize);
+    maSparklines.resize(GetDoc().GetSheetLimits().GetMaxRowCount());
+
     maBroadcasters.insert_empty(nStartRow, nSize);
     maBroadcasters.resize(GetDoc().GetMaxRowCount());
 
@@ -1872,6 +1876,7 @@ void ScColumn::SwapCol(ScColumn& rCol)
     maCells.swap(rCol.maCells);
     maCellTextAttrs.swap(rCol.maCellTextAttrs);
     maCellNotes.swap(rCol.maCellNotes);
+    maSparklines.swap(rCol.maSparklines);
 
     // Swap all CellStoreEvent mdds event_func related.
     maCells.event_handler().swap(rCol.maCells.event_handler());
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index bf1b43d10f39..3eabc08a387c 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1970,6 +1970,16 @@ void ScColumn::PrepareBroadcastersForDestruction()
     }
 }
 
+sc::Sparkline* ScColumn::GetSparkline(SCROW nRow)
+{
+    return maSparklines.get<sc::Sparkline*>(nRow);
+}
+
+void ScColumn::SetSparkline(SCROW nRow, std::unique_ptr<sc::Sparkline> 
pSparkline)
+{
+    maSparklines.set(nRow, pSparkline.release());
+}
+
 namespace
 {
 struct BroadcasterNoListenersPredicate
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 31903287cd48..8d38fa54ea45 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -150,6 +150,7 @@ void ScColumn::Delete( SCROW nRow )
     DeleteContent(nRow, false);
     maCellTextAttrs.set_empty(nRow, nRow);
     maCellNotes.set_empty(nRow, nRow);
+    maSparklines.set_empty(nRow, nRow);
 
     Broadcast(nRow);
     CellStorageModified();
@@ -167,6 +168,8 @@ void ScColumn::FreeAll()
     maCellTextAttrs.resize(maxRowCount);
     maCellNotes.clear();
     maCellNotes.resize(maxRowCount);
+    maSparklines.clear();
+    maSparklines.resize(maxRowCount);
     CellStorageModified();
 }
 
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 5973bf913366..3ec08575a713 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -6514,6 +6514,33 @@ bool ScDocument::IsInVBAMode() const
     return false;
 }
 
+sc::Sparkline* ScDocument::GetSparkline(ScAddress const& rPosition)
+{
+    SCTAB nTab = rPosition.Tab();
+    SCCOL nCol = rPosition.Col();
+
+    if (ValidTab(nTab) && nTab < SCTAB(maTabs.size()) &&
+        nCol < maTabs[nTab]->GetAllocatedColumnsCount())
+    {
+        SCROW nRow = rPosition.Row();
+        return maTabs[nTab]->aCol[nCol].GetSparkline(nRow);
+    }
+    return nullptr;
+}
+
+sc::Sparkline* ScDocument::CreateSparkline(ScAddress const & rPosition, 
std::shared_ptr<sc::SparklineGroup> & pSparklineGroup)
+{
+    std::unique_ptr<sc::Sparkline> pSparkline(new 
sc::Sparkline(pSparklineGroup));
+    sc::Sparkline* pCreated = pSparkline.get();
+
+    SCTAB nTab = rPosition.Tab();
+    SCCOL nCol = rPosition.Col();
+    SCROW nRow = rPosition.Row();
+    maTabs[nTab]->CreateColumnIfNotExists(nCol).SetSparkline(nRow, 
std::move(pSparkline));
+
+    return pCreated;
+}
+
 ScPostIt* ScDocument::GetNote(const ScAddress& rPos)
 {
     return GetNote(rPos.Col(), rPos.Row(), rPos.Tab());

Reply via email to