Rebased ref, commits from common ancestor:
commit 00eaa360c99df1b539e7f1d70ff385468cf758e7
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Tue Mar 15 15:18:16 2022 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Tue Mar 15 15:18:16 2022 +0900

    sc: support deleting a Sparkline with 'Clear Content' function
    
    Change-Id: Ida61b402170238fb0505c777e49954c15d376cf0

diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 5472419e2297..91bb18b4813b 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -619,6 +619,8 @@ public:
     // Spaklines
     sc::SparklineCell* GetSparklineCell(SCROW nRow);
     void CreateSparklineCell(SCROW nRow, std::shared_ptr<sc::Sparkline> const& 
pSparkline);
+    void DeleteSparklineCells(sc::ColumnBlockPosition& rBlockPos, SCROW nRow1, 
SCROW nRow2);
+    bool DeleteSparkline(SCROW nRow);
 
     // cell notes
     ScPostIt* GetCellNote( SCROW nRow );
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 1b86695ba94b..c101612ab2dc 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1246,6 +1246,7 @@ public:
     SC_DLLPUBLIC sc::Sparkline* GetSparkline(ScAddress const & rPosition);
     SC_DLLPUBLIC sc::Sparkline* CreateSparkline(ScAddress const & rPosition, 
std::shared_ptr<sc::SparklineGroup> & pSparklineGroup);
     SC_DLLPUBLIC sc::SparklineList* GetSparklineList(SCTAB nTab);
+    SC_DLLPUBLIC bool DeleteSparkline(ScAddress const& rPosition);
 
     /** Notes **/
     SC_DLLPUBLIC ScPostIt*       GetNote(const ScAddress& rPos);
diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx
index 283231ddf5f1..5f1b5179cdd9 100644
--- a/sc/inc/global.hxx
+++ b/sc/inc/global.hxx
@@ -157,19 +157,20 @@ enum class InsertDeleteFlags : sal_uInt16
     OBJECTS          = 0x0080,   /// Drawing objects.
     EDITATTR         = 0x0100,   /// Rich-text attributes.
     OUTLINE          = 0x0800,   /// Sheet / outlining (grouping) information
+    SPARKLINES       = 0x4000,   /// Sparklines in a cell.
     NOCAPTIONS       = 0x0200,   /// Internal use only (undo etc.): do not 
copy/delete caption objects of cell notes.
     ADDNOTES         = 0x0400,   /// Internal use only (copy from clip): do 
not delete existing cell contents when pasting notes.
     SPECIAL_BOOLEAN  = 0x1000,
     FORGETCAPTIONS   = 0x2000,   /// Internal use only (d&d undo): do not 
delete caption objects of cell notes.
     ATTRIB           = HARDATTR | STYLES,
-    CONTENTS         = VALUE | DATETIME | STRING | NOTE | FORMULA | OUTLINE,
-    ALL              = CONTENTS | ATTRIB | OBJECTS,
+    CONTENTS         = VALUE | DATETIME | STRING | NOTE | FORMULA | OUTLINE | 
SPARKLINES,
+    ALL              = CONTENTS | ATTRIB | OBJECTS | SPARKLINES,
     /// Copy flags for auto/series fill functions: do not touch notes and 
drawing objects.
     AUTOFILL         = ALL & ~(NOTE | OBJECTS)
 };
 namespace o3tl
 {
-    template<> struct typed_flags<InsertDeleteFlags> : 
is_typed_flags<InsertDeleteFlags, 0x3fff> {};
+    template<> struct typed_flags<InsertDeleteFlags> : 
is_typed_flags<InsertDeleteFlags, 0x7fff> {};
 }
 // This doesn't work at the moment, perhaps when we have constexpr we can 
modify InsertDeleteFlags to make it work.
 //static_assert((InsertDeleteFlags::ATTRIB & InsertDeleteFlags::CONTENTS) == 
InsertDeleteFlags::NONE, "these must match");
diff --git a/sc/inc/mtvelements.hxx b/sc/inc/mtvelements.hxx
index ee669c0a6e6b..72f65d2b72ff 100644
--- a/sc/inc/mtvelements.hxx
+++ b/sc/inc/mtvelements.hxx
@@ -142,6 +142,7 @@ typedef mdds::mtv::soa::multi_type_vector<CellFunc, 
CellStoreTrait> CellStoreTyp
 struct ColumnBlockPosition
 {
     CellNoteStoreType::iterator miCellNotePos;
+    SparklineStoreType::iterator miSparklinePos;
     BroadcasterStoreType::iterator miBroadcasterPos;
     CellTextAttrStoreType::iterator miCellTextAttrPos;
     CellStoreType::iterator miCellPos;
@@ -152,6 +153,7 @@ struct ColumnBlockPosition
 struct ColumnBlockConstPosition
 {
     CellNoteStoreType::const_iterator miCellNotePos;
+    SparklineStoreType::const_iterator miSparklinePos;
     CellTextAttrStoreType::const_iterator miCellTextAttrPos;
     CellStoreType::const_iterator miCellPos;
 
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 39cc4736d12d..2393f8ace994 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -477,6 +477,7 @@ public:
 
     sc::Sparkline* GetSparkline(SCCOL nCol, SCROW nRow);
     sc::Sparkline* CreateSparkline(SCCOL nCol, SCROW nRow, 
std::shared_ptr<sc::SparklineGroup> & pSparklineGroup);
+    bool DeleteSparkline(SCCOL nCol, SCROW nRow);
 
     sc::SparklineList& GetSparklineList();
 
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index cccd2af0fb34..c7e2dd5d8006 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1979,6 +1979,8 @@ void ScColumn::PrepareBroadcastersForDestruction()
     }
 }
 
+// Sparklines
+
 sc::SparklineCell* ScColumn::GetSparklineCell(SCROW nRow)
 {
     return maSparklines.get<sc::SparklineCell*>(nRow);
@@ -1989,6 +1991,22 @@ void ScColumn::CreateSparklineCell(SCROW nRow, 
std::shared_ptr<sc::Sparkline> co
     maSparklines.set(nRow, new sc::SparklineCell(pSparkline));
 }
 
+void ScColumn::DeleteSparklineCells(sc::ColumnBlockPosition& rBlockPos, SCROW 
nRow1, SCROW nRow2)
+{
+    rBlockPos.miSparklinePos = 
maSparklines.set_empty(rBlockPos.miSparklinePos, nRow1, nRow2);
+}
+
+bool ScColumn::DeleteSparkline(SCROW nRow)
+{
+    if (!GetDoc().ValidRow(nRow))
+        return false;
+
+    maSparklines.set_empty(nRow, nRow);
+    return true;
+}
+
+// Notes
+
 ScPostIt* ScColumn::GetCellNote(SCROW nRow)
 {
     return maCellNotes.get<ScPostIt*>(nRow);
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 793797cb1c79..dc6a68420a6f 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -1022,6 +1022,11 @@ void ScColumn::DeleteArea(
         DeleteCellNotes(aBlockPos, nStartRow, nEndRow, 
bForgetCaptionOwnership);
     }
 
+    if (nDelFlag & InsertDeleteFlags::SPARKLINES)
+    {
+        DeleteSparklineCells(aBlockPos, nStartRow, nEndRow);
+    }
+
     if ( nDelFlag & InsertDeleteFlags::EDITATTR )
     {
         OSL_ENSURE( nContFlag == InsertDeleteFlags::NONE, "DeleteArea: Wrong 
Flags" );
@@ -1050,6 +1055,7 @@ void ScColumn::InitBlockPosition( 
sc::ColumnBlockPosition& rBlockPos )
     rBlockPos.miCellNotePos = maCellNotes.begin();
     rBlockPos.miCellTextAttrPos = maCellTextAttrs.begin();
     rBlockPos.miCellPos = maCells.begin();
+    rBlockPos.miSparklinePos = maSparklines.begin();
 }
 
 void ScColumn::InitBlockPosition( sc::ColumnBlockConstPosition& rBlockPos ) 
const
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index e0b1037c8d3e..03f468520a03 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -6529,9 +6529,21 @@ sc::Sparkline* ScDocument::CreateSparkline(ScAddress 
const & rPosition, std::sha
     return nullptr;
 }
 
+bool ScDocument::DeleteSparkline(ScAddress const & rPosition)
+{
+     SCTAB nTab = rPosition.Tab();
+
+    if (TableExists(nTab))
+    {
+        return maTabs[nTab]->DeleteSparkline(rPosition.Col(), rPosition.Row());
+    }
+
+    return false;
+}
+
 sc::SparklineList* ScDocument::GetSparklineList(SCTAB nTab)
 {
-    if (ValidTab(nTab) && nTab < SCTAB(maTabs.size()))
+    if (TableExists(nTab))
     {
         return &maTabs[nTab]->GetSparklineList();
     }
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index aa218ee44cec..88f9a4e8ee97 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1839,6 +1839,16 @@ sc::Sparkline* ScTable::CreateSparkline(SCCOL nCol, 
SCROW nRow, std::shared_ptr<
     return pSparkline.get();
 }
 
+bool ScTable::DeleteSparkline(SCCOL nCol, SCROW nRow)
+{
+    if (!ValidCol(nCol) || nCol >= GetAllocatedColumnsCount())
+        return false;
+
+    aCol[nCol].DeleteSparkline(nRow);
+
+    return true;
+}
+
 sc::SparklineList& ScTable::GetSparklineList()
 {
     return maSparklineList;
commit f8d1bedd8bfc47d9bfc26bf55ceb45d23ece3a0e
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Sat Mar 12 23:30:40 2022 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Mon Mar 14 13:52:32 2022 +0900

    sc: SparklineDialog add type, colors and properties
    
    Change-Id: Ie8243985d61cc719fd0444b0e1aaf18f43489d5c

diff --git a/sc/inc/SparklineGroup.hxx b/sc/inc/SparklineGroup.hxx
index f87475559547..ec3a8c8a971f 100644
--- a/sc/inc/SparklineGroup.hxx
+++ b/sc/inc/SparklineGroup.hxx
@@ -76,13 +76,13 @@ public:
 
     SparklineGroup()
         : m_aColorSeries(COL_BLUE)
-        , m_aColorNegative(COL_TRANSPARENT)
-        , m_aColorAxis(COL_TRANSPARENT)
-        , m_aColorMarkers(COL_TRANSPARENT)
-        , m_aColorFirst(COL_TRANSPARENT)
-        , m_aColorLast(COL_TRANSPARENT)
-        , m_aColorHigh(COL_TRANSPARENT)
-        , m_aColorLow(COL_TRANSPARENT)
+        , m_aColorNegative(COL_RED)
+        , m_aColorAxis(COL_RED)
+        , m_aColorMarkers(COL_RED)
+        , m_aColorFirst(COL_RED)
+        , m_aColorLast(COL_RED)
+        , m_aColorHigh(COL_RED)
+        , m_aColorLow(COL_RED)
         , m_eMinAxisType(AxisType::Individual)
         , m_eMaxAxisType(AxisType::Individual)
         , m_fLineWeight(0.75)
diff --git a/sc/source/ui/dialogs/SparklineDialog.cxx 
b/sc/source/ui/dialogs/SparklineDialog.cxx
index 5a167fe8b7c1..fac1d8274be5 100644
--- a/sc/source/ui/dialogs/SparklineDialog.cxx
+++ b/sc/source/ui/dialogs/SparklineDialog.cxx
@@ -12,6 +12,8 @@
 #include <Sparkline.hxx>
 #include <reffact.hxx>
 
+#include <svx/colorbox.hxx>
+
 namespace sc
 {
 SparklineDialog::SparklineDialog(SfxBindings* pBindings, SfxChildWindow* 
pChildWindow,
@@ -30,6 +32,30 @@ SparklineDialog::SparklineDialog(SfxBindings* pBindings, 
SfxChildWindow* pChildW
     , mxOutputRangeLabel(m_xBuilder->weld_label("output-range-label"))
     , mxOutputRangeEdit(new 
formula::RefEdit(m_xBuilder->weld_entry("output-range-edit")))
     , mxOutputRangeButton(new 
formula::RefButton(m_xBuilder->weld_button("output-range-button")))
+    , mxColorSeries(new 
ColorListBox(m_xBuilder->weld_menu_button("color-button-series"),
+                                     [pWindow] { return pWindow; }))
+    , mxColorNegative(new 
ColorListBox(m_xBuilder->weld_menu_button("color-button-negative"),
+                                       [pWindow] { return pWindow; }))
+    , mxColorMarker(new 
ColorListBox(m_xBuilder->weld_menu_button("color-button-marker"),
+                                     [pWindow] { return pWindow; }))
+    , mxColorHigh(new 
ColorListBox(m_xBuilder->weld_menu_button("color-button-high"),
+                                   [pWindow] { return pWindow; }))
+    , mxColorLow(new 
ColorListBox(m_xBuilder->weld_menu_button("color-button-low"),
+                                  [pWindow] { return pWindow; }))
+    , mxColorFirst(new 
ColorListBox(m_xBuilder->weld_menu_button("color-button-first"),
+                                    [pWindow] { return pWindow; }))
+    , mxColorLast(new 
ColorListBox(m_xBuilder->weld_menu_button("color-button-last"),
+                                   [pWindow] { return pWindow; }))
+    , mxCheckButtonNegative(m_xBuilder->weld_check_button("check-negative"))
+    , mxCheckButtonMarker(m_xBuilder->weld_check_button("check-marker"))
+    , mxCheckButtonHigh(m_xBuilder->weld_check_button("check-high"))
+    , mxCheckButtonLow(m_xBuilder->weld_check_button("check-low"))
+    , mxCheckButtonFirst(m_xBuilder->weld_check_button("check-first"))
+    , mxCheckButtonLast(m_xBuilder->weld_check_button("check-last"))
+    , mxRadioLine(m_xBuilder->weld_radio_button("line-radiobutton"))
+    , mxRadioColumn(m_xBuilder->weld_radio_button("column-radiobutton"))
+    , mxRadioStacked(m_xBuilder->weld_radio_button("stacked-radiobutton"))
+    , mpLocalSparklineGroup(new sc::SparklineGroup())
 {
     mxInputRangeEdit->SetReferences(this, mxInputRangeText.get());
     mxInputRangeButton->SetReferences(this, mxInputRangeEdit.get());
@@ -59,13 +85,60 @@ SparklineDialog::SparklineDialog(SfxBindings* pBindings, 
SfxChildWindow* pChildW
     mxInputRangeEdit->SetModifyHdl(aModifyLink);
     mxOutputRangeEdit->SetModifyHdl(aModifyLink);
 
-    mxOutputRangeEdit->GrabFocus();
+    Link<weld::Toggleable&, void> aRadioButtonLink
+        = LINK(this, SparklineDialog, SelectSparklineType);
+    mxRadioLine->connect_toggled(aRadioButtonLink);
+    mxRadioColumn->connect_toggled(aRadioButtonLink);
+    mxRadioStacked->connect_toggled(aRadioButtonLink);
+
+    Link<weld::Toggleable&, void> aLink = LINK(this, SparklineDialog, 
ToggleHandler);
+    mxCheckButtonNegative->connect_toggled(aLink);
+    mxCheckButtonMarker->connect_toggled(aLink);
+    mxCheckButtonHigh->connect_toggled(aLink);
+    mxCheckButtonLow->connect_toggled(aLink);
+    mxCheckButtonFirst->connect_toggled(aLink);
+    mxCheckButtonLast->connect_toggled(aLink);
+
+    setupValues(mpLocalSparklineGroup);
 
     GetRangeFromSelection();
+
+    mxOutputRangeEdit->GrabFocus();
 }
 
 SparklineDialog::~SparklineDialog() {}
 
+void SparklineDialog::setupValues(std::shared_ptr<sc::SparklineGroup> const& 
pSparklineGroup)
+{
+    switch (pSparklineGroup->m_eType)
+    {
+        case sc::SparklineType::Line:
+            mxRadioLine->set_active(true);
+            break;
+        case sc::SparklineType::Column:
+            mxRadioColumn->set_active(true);
+            break;
+        case sc::SparklineType::Stacked:
+            mxRadioStacked->set_active(true);
+            break;
+    }
+
+    mxColorSeries->SelectEntry(pSparklineGroup->m_aColorSeries);
+    mxColorNegative->SelectEntry(pSparklineGroup->m_aColorNegative);
+    mxColorMarker->SelectEntry(pSparklineGroup->m_aColorMarkers);
+    mxColorHigh->SelectEntry(pSparklineGroup->m_aColorHigh);
+    mxColorLow->SelectEntry(pSparklineGroup->m_aColorLow);
+    mxColorFirst->SelectEntry(pSparklineGroup->m_aColorFirst);
+    mxColorLast->SelectEntry(pSparklineGroup->m_aColorLast);
+
+    mxCheckButtonNegative->set_active(pSparklineGroup->m_bNegative);
+    mxCheckButtonMarker->set_active(pSparklineGroup->m_bMarkers);
+    mxCheckButtonHigh->set_active(pSparklineGroup->m_bHigh);
+    mxCheckButtonLow->set_active(pSparklineGroup->m_bLow);
+    mxCheckButtonFirst->set_active(pSparklineGroup->m_bFirst);
+    mxCheckButtonLast->set_active(pSparklineGroup->m_bLast);
+}
+
 void SparklineDialog::Close() { 
DoClose(sc::SparklineDialogWrapper::GetChildWindowId()); }
 
 void SparklineDialog::SetActive()
@@ -211,6 +284,32 @@ IMPL_LINK(SparklineDialog, ButtonClicked, weld::Button&, 
rButton, void)
     }
 }
 
+IMPL_LINK(SparklineDialog, ToggleHandler, weld::Toggleable&, rToggle, void)
+{
+    if (mxCheckButtonNegative.get() == &rToggle)
+        mpLocalSparklineGroup->m_bNegative = 
mxCheckButtonNegative->get_active();
+    if (mxCheckButtonMarker.get() == &rToggle)
+        mpLocalSparklineGroup->m_bMarkers = mxCheckButtonMarker->get_active();
+    if (mxCheckButtonHigh.get() == &rToggle)
+        mpLocalSparklineGroup->m_bHigh = mxCheckButtonHigh->get_active();
+    if (mxCheckButtonLow.get() == &rToggle)
+        mpLocalSparklineGroup->m_bLow = mxCheckButtonLow->get_active();
+    if (mxCheckButtonFirst.get() == &rToggle)
+        mpLocalSparklineGroup->m_bFirst = mxCheckButtonFirst->get_active();
+    if (mxCheckButtonLast.get() == &rToggle)
+        mpLocalSparklineGroup->m_bLast = mxCheckButtonLast->get_active();
+}
+
+IMPL_LINK_NOARG(SparklineDialog, SelectSparklineType, weld::Toggleable&, void)
+{
+    if (mxRadioLine->get_active())
+        mpLocalSparklineGroup->m_eType = sc::SparklineType::Line;
+    else if (mxRadioColumn->get_active())
+        mpLocalSparklineGroup->m_eType = sc::SparklineType::Column;
+    else if (mxRadioStacked->get_active())
+        mpLocalSparklineGroup->m_eType = sc::SparklineType::Stacked;
+}
+
 namespace
 {
 enum class RangeOrientation
@@ -257,7 +356,13 @@ bool SparklineDialog::checkValidInputOutput()
 
 void SparklineDialog::perform()
 {
-    auto pSparklineGroup = std::make_shared<sc::SparklineGroup>();
+    mpLocalSparklineGroup->m_aColorSeries = 
mxColorSeries->GetSelectEntryColor();
+    mpLocalSparklineGroup->m_aColorNegative = 
mxColorNegative->GetSelectEntryColor();
+    mpLocalSparklineGroup->m_aColorMarkers = 
mxColorMarker->GetSelectEntryColor();
+    mpLocalSparklineGroup->m_aColorHigh = mxColorHigh->GetSelectEntryColor();
+    mpLocalSparklineGroup->m_aColorLow = mxColorLow->GetSelectEntryColor();
+    mpLocalSparklineGroup->m_aColorFirst = mxColorFirst->GetSelectEntryColor();
+    mpLocalSparklineGroup->m_aColorLast = mxColorLast->GetSelectEntryColor();
 
     if (maOutputRange.aStart.Col() == maOutputRange.aEnd.Col())
     {
@@ -283,7 +388,7 @@ void SparklineDialog::perform()
                 aInputRangeSlice.aStart.SetCol(maInputRange.aStart.Col() + 
nIndex);
                 aInputRangeSlice.aEnd.SetCol(maInputRange.aStart.Col() + 
nIndex);
             }
-            auto* pCreated = mrDocument.CreateSparkline(aAddress, 
pSparklineGroup);
+            auto* pCreated = mrDocument.CreateSparkline(aAddress, 
mpLocalSparklineGroup);
             pCreated->setInputRange(aInputRangeSlice);
             nIndex++;
         }
@@ -313,7 +418,7 @@ void SparklineDialog::perform()
                 aInputRangeSlice.aStart.SetCol(maInputRange.aStart.Col() + 
nIndex);
                 aInputRangeSlice.aEnd.SetCol(maInputRange.aStart.Col() + 
nIndex);
             }
-            auto* pCreated = mrDocument.CreateSparkline(aAddress, 
pSparklineGroup);
+            auto* pCreated = mrDocument.CreateSparkline(aAddress, 
mpLocalSparklineGroup);
             pCreated->setInputRange(aInputRangeSlice);
             nIndex++;
         }
diff --git a/sc/source/ui/inc/SparklineDialog.hxx 
b/sc/source/ui/inc/SparklineDialog.hxx
index a4a03f33491d..1fe2616a4c59 100644
--- a/sc/source/ui/inc/SparklineDialog.hxx
+++ b/sc/source/ui/inc/SparklineDialog.hxx
@@ -13,6 +13,8 @@
 #include "anyrefdg.hxx"
 #include <viewdata.hxx>
 
+class ColorListBox;
+
 namespace sc
 {
 class SparklineDialog : public ScAnyRefDlgController
@@ -38,6 +40,25 @@ private:
     std::unique_ptr<formula::RefEdit> mxOutputRangeEdit;
     std::unique_ptr<formula::RefButton> mxOutputRangeButton;
 
+    std::unique_ptr<ColorListBox> mxColorSeries;
+    std::unique_ptr<ColorListBox> mxColorNegative;
+    std::unique_ptr<ColorListBox> mxColorMarker;
+    std::unique_ptr<ColorListBox> mxColorHigh;
+    std::unique_ptr<ColorListBox> mxColorLow;
+    std::unique_ptr<ColorListBox> mxColorFirst;
+    std::unique_ptr<ColorListBox> mxColorLast;
+
+    std::unique_ptr<weld::CheckButton> mxCheckButtonNegative;
+    std::unique_ptr<weld::CheckButton> mxCheckButtonMarker;
+    std::unique_ptr<weld::CheckButton> mxCheckButtonHigh;
+    std::unique_ptr<weld::CheckButton> mxCheckButtonLow;
+    std::unique_ptr<weld::CheckButton> mxCheckButtonFirst;
+    std::unique_ptr<weld::CheckButton> mxCheckButtonLast;
+
+    std::unique_ptr<weld::RadioButton> mxRadioLine;
+    std::unique_ptr<weld::RadioButton> mxRadioColumn;
+    std::unique_ptr<weld::RadioButton> mxRadioStacked;
+
     void GetRangeFromSelection();
 
     DECL_LINK(ButtonClicked, weld::Button&, void);
@@ -46,7 +67,12 @@ private:
     DECL_LINK(LoseEditFocusHandler, formula::RefEdit&, void);
     DECL_LINK(LoseButtonFocusHandler, formula::RefButton&, void);
     DECL_LINK(RefInputModifyHandler, formula::RefEdit&, void);
+    DECL_LINK(ToggleHandler, weld::Toggleable&, void);
+    DECL_LINK(SelectSparklineType, weld::Toggleable&, void);
+
+    std::shared_ptr<sc::SparklineGroup> mpLocalSparklineGroup;
 
+    void setupValues(std::shared_ptr<sc::SparklineGroup> const& 
pSparklineGroup);
     void perform();
     bool checkValidInputOutput();
 
diff --git a/sc/uiconfig/scalc/ui/sparklinedialog.ui 
b/sc/uiconfig/scalc/ui/sparklinedialog.ui
index 9070ce2cd86e..8c2119ca2c63 100644
--- a/sc/uiconfig/scalc/ui/sparklinedialog.ui
+++ b/sc/uiconfig/scalc/ui/sparklinedialog.ui
@@ -70,7 +70,7 @@
             <property name="expand">False</property>
             <property name="fill">True</property>
             <property name="pack-type">end</property>
-            <property name="position">0</property>
+            <property name="position">2</property>
           </packing>
         </child>
         <child>
@@ -84,10 +84,10 @@
               <object class="GtkGrid">
                 <property name="visible">True</property>
                 <property name="can-focus">False</property>
-                <property name="margin-start">6</property>
+                <property name="margin-start">12</property>
                 <property name="margin-end">6</property>
                 <property name="margin-top">6</property>
-                <property name="margin-bottom">7</property>
+                <property name="margin-bottom">6</property>
                 <property name="row-spacing">6</property>
                 <property name="column-spacing">6</property>
                 <child>
@@ -201,10 +201,501 @@
               </object>
             </child>
             <child type="label">
-              <object class="GtkLabel" id="label1">
+              <object class="GtkLabel" id="label-data">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes" 
context="SparklineDialog|label-data">Data</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="frame-properties">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label-xalign">0</property>
+            <property name="shadow-type">none</property>
+            <child>
+              <!-- n-columns=6 n-rows=5 -->
+              <object class="GtkGrid">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="margin-start">12</property>
+                <property name="margin-end">6</property>
+                <property name="margin-top">6</property>
+                <property name="margin-bottom">6</property>
+                <property name="row-spacing">6</property>
+                <property name="column-spacing">6</property>
+                <child>
+                  <object class="GtkLabel" id="label-series">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="SparklineDialog|label-series">Series:</property>
+                    <property name="xalign">0</property>
+                    <accessibility>
+                      <relation type="label-for" target="color-button-series"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label-negative">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="SparklineDialog|label-negative">Negative Points:</property>
+                    <property name="xalign">0</property>
+                    <accessibility>
+                      <relation type="label-for" 
target="color-button-negative"/>
+                      <relation type="label-for" target="check-negative"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkMenuButton" id="color-button-series">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-series"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">2</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkMenuButton" id="color-button-negative">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-negative"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">2</property>
+                    <property name="top-attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="check-negative">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="image-position">right</property>
+                    <property name="always-show-image">True</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-negative"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label-low">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="SparklineDialog|label-low">Low Points:</property>
+                    <property name="xalign">0</property>
+                    <accessibility>
+                      <relation type="label-for" target="color-button-low"/>
+                      <relation type="label-for" target="check-low"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkMenuButton" id="color-button-high">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-high"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">2</property>
+                    <property name="top-attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkMenuButton" id="color-button-low">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-low"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">2</property>
+                    <property name="top-attach">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="check-low">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="image-position">right</property>
+                    <property name="always-show-image">True</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-low"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label-high">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="SparklineDialog|label-high">High Points:</property>
+                    <property name="xalign">0</property>
+                    <accessibility>
+                      <relation type="label-for" target="color-button-high"/>
+                      <relation type="label-for" target="check-high"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="check-high">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="image-position">right</property>
+                    <property name="always-show-image">True</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-high"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label-marker">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="SparklineDialog|label-marker">Marker:</property>
+                    <property name="xalign">0</property>
+                    <accessibility>
+                      <relation type="label-for" target="check-marker"/>
+                      <relation type="label-for" target="color-button-marker"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">3</property>
+                    <property name="top-attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="check-marker">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="image-position">right</property>
+                    <property name="always-show-image">True</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-marker"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">4</property>
+                    <property name="top-attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkMenuButton" id="color-button-marker">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-marker"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">5</property>
+                    <property name="top-attach">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkMenuButton" id="color-button-first">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-first"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">5</property>
+                    <property name="top-attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkMenuButton" id="color-button-last">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-last"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">5</property>
+                    <property name="top-attach">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="check-first">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="image-position">right</property>
+                    <property name="always-show-image">True</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-first"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">4</property>
+                    <property name="top-attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="check-last">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">False</property>
+                    <property name="image-position">right</property>
+                    <property name="always-show-image">True</property>
+                    <property name="draw-indicator">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <accessibility>
+                      <relation type="labelled-by" target="label-last"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">4</property>
+                    <property name="top-attach">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label-first">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="SparklineDialog|label-first">First Points:</property>
+                    <property name="xalign">0</property>
+                    <accessibility>
+                      <relation type="label-for" target="color-button-first"/>
+                      <relation type="label-for" target="check-first"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">3</property>
+                    <property name="top-attach">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label-last">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="SparklineDialog|label-last">Last Points:</property>
+                    <property name="xalign">0</property>
+                    <accessibility>
+                      <relation type="label-for" target="color-button-last"/>
+                      <relation type="label-for" target="check-last"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">3</property>
+                    <property name="top-attach">4</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="label-type">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="SparklineDialog|label-type">Type:</property>
+                    <property name="xalign">0</property>
+                    <accessibility>
+                      <relation type="label-for" target="line-radiobutton"/>
+                      <relation type="label-for" target="column-radiobutton"/>
+                      <relation type="label-for" target="stacked-radiobutton"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <object class="GtkRadioButton" id="line-radiobutton">
+                        <property name="label" translatable="yes" 
context="SparklineDialog|line-radiobutton">Line</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="active">True</property>
+                        <property name="draw-indicator">True</property>
+                        <accessibility>
+                          <relation type="labelled-by" target="label-type"/>
+                        </accessibility>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="column-radiobutton">
+                        <property name="label" translatable="yes" 
context="SparklineDialog|column-radiobutton">Column</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="draw-indicator">True</property>
+                        <property name="group">line-radiobutton</property>
+                        <accessibility>
+                          <relation type="labelled-by" target="label-type"/>
+                        </accessibility>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkRadioButton" id="stacked-radiobutton">
+                        <property name="label" translatable="yes" 
context="SparklineDialog|stacked-radiobutton">Stacked</property>
+                        <property name="visible">True</property>
+                        <property name="can-focus">True</property>
+                        <property name="receives-default">False</property>
+                        <property name="hexpand">True</property>
+                        <property name="draw-indicator">True</property>
+                        <property name="group">line-radiobutton</property>
+                        <accessibility>
+                          <relation type="labelled-by" target="label-type"/>
+                        </accessibility>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">0</property>
+                    <property name="width">5</property>
+                  </packing>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label-properties">
                 <property name="visible">True</property>
                 <property name="can-focus">False</property>
-                <property name="label" translatable="yes" 
context="randomnumbergenerator|label1">Data</property>
+                <property name="label" translatable="yes" 
context="SparklineDialog|label-properties">Properties</property>
                 <attributes>
                   <attribute name="weight" value="bold"/>
                 </attributes>
commit f799202447a4206da495a693a0521f7ae2053332
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Fri Mar 11 20:49:09 2022 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Mon Mar 14 13:52:31 2022 +0900

    sc: SparklineDialog and "Insert Sparkline" to context menu
    
    This adds a SparklineDialog, which is used to add/edit the
    Sparkline input/output ranges. The command for the context menu
    "Insert Sparkline" calls the SparklineDialog for inserting a new
    sparkline into cells. Currently the SparklineDialog include the
    properties for the SparklineGroup, which will be added in a later
    commit.
    
    Change-Id: I9036d788fdf2a035f1ce10fc7413327a92144137

diff --git a/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu 
b/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu
index c7bfe5e55577..0d539ab76b68 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu
@@ -1074,6 +1074,14 @@
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:InsertSparkline" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Insert Sparkline...</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+      </node>
       <node oor:name=".uno:EditHeaderAndFooter" oor:op="replace">
         <prop oor:name="Label" oor:type="xs:string">
           <value xml:lang="en-US">~Headers and Footers...</value>
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 62ab22a797c4..f145d3a7fbf2 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -418,6 +418,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/ui/dbgui/sfiltdlg \
     sc/source/ui/dbgui/validate \
     sc/source/ui/dialogs/searchresults \
+    sc/source/ui/dialogs/SparklineDialog \
     sc/source/ui/docshell/arealink \
     sc/source/ui/docshell/autostyl \
     sc/source/ui/docshell/datastream \
diff --git a/sc/UIConfig_scalc.mk b/sc/UIConfig_scalc.mk
index bc320cc44fd7..302f08ff3fb3 100644
--- a/sc/UIConfig_scalc.mk
+++ b/sc/UIConfig_scalc.mk
@@ -244,6 +244,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/scalc,\
        sc/uiconfig/scalc/ui/sortkey \
        sc/uiconfig/scalc/ui/sortoptionspage \
        sc/uiconfig/scalc/ui/sortwarning \
+       sc/uiconfig/scalc/ui/sparklinedialog \
        sc/uiconfig/scalc/ui/splitcolumnentry \
        sc/uiconfig/scalc/ui/subtotaldialog \
        sc/uiconfig/scalc/ui/subtotaloptionspage \
diff --git a/sc/inc/sc.hrc b/sc/inc/sc.hrc
index f391e618357b..b9dc48169235 100644
--- a/sc/inc/sc.hrc
+++ b/sc/inc/sc.hrc
@@ -238,6 +238,8 @@ class SvxZoomSliderItem;
 #define SID_COLUMN_OPERATIONS               (SC_MESSAGE_START + 86)
 #define SID_ROW_OPERATIONS                  (SC_MESSAGE_START + 87)
 #define SID_FOURIER_ANALYSIS_DIALOG         (SC_MESSAGE_START + 88)
+#define SID_SPARKLINE_DIALOG                (SC_MESSAGE_START + 89)
+
 
 // functions
 
@@ -306,7 +308,8 @@ class SvxZoomSliderItem;
 #define FID_INS_ROWS_BEFORE     (INSERT_MENU_START + 22)
 #define FID_INS_COLUMNS_BEFORE  (INSERT_MENU_START + 23)
 #define FID_DEFINE_CURRENT_NAME (INSERT_MENU_START + 24)
-#define INSERT_MENU_END         (INSERT_MENU_START + 25)
+#define SID_INSERT_SPARKLINE    (INSERT_MENU_START + 25)
+#define INSERT_MENU_END         (INSERT_MENU_START + 26)
 
 #define FORMAT_MENU_START       (INSERT_MENU_END)
 #define FID_CELL_FORMAT         (FORMAT_MENU_START)
diff --git a/sc/sdi/cellsh.sdi b/sc/sdi/cellsh.sdi
index c9eed43d665b..8feaf0c590e0 100644
--- a/sc/sdi/cellsh.sdi
+++ b/sc/sdi/cellsh.sdi
@@ -235,6 +235,7 @@ interface CellSelection
     SID_SELECT_VISIBLE_ROWS             [ ExecMethod = ExecuteEdit;]
     SID_SELECT_VISIBLE_COLUMNS          [ ExecMethod = ExecuteEdit;]
     SID_CURRENT_FORMULA_RANGE           [ ExecMethod = ExecuteEdit;]
+    SID_INSERT_SPARKLINE                [ ExecMethod = ExecuteEdit; 
StateMethod = GetBlockState; ]
 
     SID_THESAURUS   [ ExecMethod = ExecuteEdit; StateMethod = GetCellState; ]
     SID_SPELL_DIALOG [ ExecMethod = ExecuteEdit; StateMethod = GetState; ]
diff --git a/sc/sdi/scalc.sdi b/sc/sdi/scalc.sdi
index 8457654946fd..4a8d8747cc14 100644
--- a/sc/sdi/scalc.sdi
+++ b/sc/sdi/scalc.sdi
@@ -2287,6 +2287,23 @@ SfxVoidItem SolverDialog SID_OPENDLG_OPTSOLVER
     GroupId = SfxGroupId::Options;
 ]
 
+SfxVoidItem InsertSparkline SID_INSERT_SPARKLINE
+()
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = TRUE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    ToolBoxConfig = TRUE,
+    GroupId = SfxGroupId::Insert;
+]
+
 SfxVoidItem SearchResultsDialog SID_SEARCH_RESULTS_DIALOG
 (SfxBoolItem Visible SID_SEARCH_RESULTS_DIALOG)
 [
diff --git a/sc/source/ui/app/scdll.cxx b/sc/source/ui/app/scdll.cxx
index b7f58002f71b..a0bdf08b16c0 100644
--- a/sc/source/ui/app/scdll.cxx
+++ b/sc/source/ui/app/scdll.cxx
@@ -206,6 +206,7 @@ void ScDLL::Init()
     ScZTestDialogWrapper                ::RegisterChildWindow(false, pMod);
     ScChiSquareTestDialogWrapper        ::RegisterChildWindow(false, pMod);
     ScFourierAnalysisDialogWrapper      ::RegisterChildWindow(false, pMod);
+    sc::SparklineDialogWrapper          ::RegisterChildWindow(false, pMod);
 
     // Redlining Window
     ScAcceptChgDlgWrapper       ::RegisterChildWindow(false, pMod);
diff --git a/sc/source/ui/dialogs/SparklineDialog.cxx 
b/sc/source/ui/dialogs/SparklineDialog.cxx
new file mode 100644
index 000000000000..5a167fe8b7c1
--- /dev/null
+++ b/sc/source/ui/dialogs/SparklineDialog.cxx
@@ -0,0 +1,324 @@
+/* -*- 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 <SparklineDialog.hxx>
+#include <SparklineGroup.hxx>
+#include <Sparkline.hxx>
+#include <reffact.hxx>
+
+namespace sc
+{
+SparklineDialog::SparklineDialog(SfxBindings* pBindings, SfxChildWindow* 
pChildWindow,
+                                 weld::Window* pWindow, ScViewData& rViewData)
+    : ScAnyRefDlgController(pBindings, pChildWindow, pWindow,
+                            u"modules/scalc/ui/sparklinedialog.ui", 
"SparklineDialog")
+    , mrViewData(rViewData)
+    , mrDocument(rViewData.GetDocument())
+    , mpActiveEdit(nullptr)
+    , mbDialogLostFocus(false)
+    , mxButtonOk(m_xBuilder->weld_button("ok"))
+    , mxButtonCancel(m_xBuilder->weld_button("cancel"))
+    , mxInputRangeText(m_xBuilder->weld_label("cell-range-label"))
+    , mxInputRangeEdit(new 
formula::RefEdit(m_xBuilder->weld_entry("cell-range-edit")))
+    , mxInputRangeButton(new 
formula::RefButton(m_xBuilder->weld_button("cell-range-button")))
+    , mxOutputRangeLabel(m_xBuilder->weld_label("output-range-label"))
+    , mxOutputRangeEdit(new 
formula::RefEdit(m_xBuilder->weld_entry("output-range-edit")))
+    , mxOutputRangeButton(new 
formula::RefButton(m_xBuilder->weld_button("output-range-button")))
+{
+    mxInputRangeEdit->SetReferences(this, mxInputRangeText.get());
+    mxInputRangeButton->SetReferences(this, mxInputRangeEdit.get());
+
+    mxOutputRangeEdit->SetReferences(this, mxOutputRangeLabel.get());
+    mxOutputRangeButton->SetReferences(this, mxOutputRangeEdit.get());
+
+    mxButtonCancel->connect_clicked(LINK(this, SparklineDialog, 
ButtonClicked));
+    mxButtonOk->connect_clicked(LINK(this, SparklineDialog, ButtonClicked));
+    mxButtonOk->set_sensitive(false);
+
+    Link<formula::RefEdit&, void> aEditLink = LINK(this, SparklineDialog, 
EditFocusHandler);
+    mxInputRangeEdit->SetGetFocusHdl(aEditLink);
+    mxOutputRangeEdit->SetGetFocusHdl(aEditLink);
+    aEditLink = LINK(this, SparklineDialog, LoseEditFocusHandler);
+    mxInputRangeEdit->SetLoseFocusHdl(aEditLink);
+    mxOutputRangeEdit->SetLoseFocusHdl(aEditLink);
+
+    Link<formula::RefButton&, void> aButtonLink = LINK(this, SparklineDialog, 
ButtonFocusHandler);
+    mxInputRangeButton->SetGetFocusHdl(aButtonLink);
+    mxOutputRangeButton->SetGetFocusHdl(aButtonLink);
+    aButtonLink = LINK(this, SparklineDialog, LoseButtonFocusHandler);
+    mxInputRangeButton->SetLoseFocusHdl(aButtonLink);
+    mxOutputRangeButton->SetLoseFocusHdl(aButtonLink);
+
+    Link<formula::RefEdit&, void> aModifyLink = LINK(this, SparklineDialog, 
RefInputModifyHandler);
+    mxInputRangeEdit->SetModifyHdl(aModifyLink);
+    mxOutputRangeEdit->SetModifyHdl(aModifyLink);
+
+    mxOutputRangeEdit->GrabFocus();
+
+    GetRangeFromSelection();
+}
+
+SparklineDialog::~SparklineDialog() {}
+
+void SparklineDialog::Close() { 
DoClose(sc::SparklineDialogWrapper::GetChildWindowId()); }
+
+void SparklineDialog::SetActive()
+{
+    if (mbDialogLostFocus)
+    {
+        mbDialogLostFocus = false;
+        if (mpActiveEdit)
+            mpActiveEdit->GrabFocus();
+    }
+    else
+    {
+        m_xDialog->grab_focus();
+    }
+    RefInputDone();
+}
+
+void SparklineDialog::GetRangeFromSelection()
+{
+    mrViewData.GetSimpleArea(maInputRange);
+    OUString aString = maInputRange.Format(mrDocument, ScRefFlags::VALID | 
ScRefFlags::TAB_3D,
+                                           mrDocument.GetAddressConvention());
+    mxInputRangeEdit->SetRefString(aString);
+}
+
+void SparklineDialog::SetReference(const ScRange& rReferenceRange, ScDocument& 
rDocument)
+{
+    if (mpActiveEdit)
+    {
+        if (rReferenceRange.aStart != rReferenceRange.aEnd)
+            RefInputStart(mpActiveEdit);
+
+        OUString aString;
+        const ScRefFlags eFlags = ScRefFlags::VALID | ScRefFlags::TAB_3D;
+        auto eAddressConvention = rDocument.GetAddressConvention();
+
+        if (mpActiveEdit == mxInputRangeEdit.get())
+        {
+            maInputRange = rReferenceRange;
+            aString = maInputRange.Format(rDocument, eFlags, 
eAddressConvention);
+            mxInputRangeEdit->SetRefString(aString);
+        }
+        else if (mpActiveEdit == mxOutputRangeEdit.get())
+        {
+            maOutputRange = rReferenceRange;
+            aString = maOutputRange.Format(rDocument, eFlags, 
eAddressConvention);
+            mxOutputRangeEdit->SetRefString(aString);
+        }
+    }
+
+    mxButtonOk->set_sensitive(checkValidInputOutput());
+}
+
+IMPL_LINK(SparklineDialog, EditFocusHandler, formula::RefEdit&, rEdit, void)
+{
+    auto* pEdit = &rEdit;
+
+    if (mxInputRangeEdit.get() == pEdit)
+        mpActiveEdit = mxInputRangeEdit.get();
+    else if (mxOutputRangeEdit.get() == pEdit)
+        mpActiveEdit = mxOutputRangeEdit.get();
+    else
+        mpActiveEdit = nullptr;
+
+    if (mpActiveEdit)
+        mpActiveEdit->SelectAll();
+}
+
+IMPL_LINK(SparklineDialog, ButtonFocusHandler, formula::RefButton&, rButton, 
void)
+{
+    auto* pButton = &rButton;
+
+    if (mxInputRangeButton.get() == pButton)
+        mpActiveEdit = mxInputRangeEdit.get();
+    else if (mxOutputRangeButton.get() == pButton)
+        mpActiveEdit = mxOutputRangeEdit.get();
+    else
+        mpActiveEdit = nullptr;
+
+    if (mpActiveEdit)
+        mpActiveEdit->SelectAll();
+}
+
+IMPL_LINK_NOARG(SparklineDialog, LoseEditFocusHandler, formula::RefEdit&, void)
+{
+    mbDialogLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+IMPL_LINK_NOARG(SparklineDialog, LoseButtonFocusHandler, formula::RefButton&, 
void)
+{
+    mbDialogLostFocus = !m_xDialog->has_toplevel_focus();
+}
+
+IMPL_LINK_NOARG(SparklineDialog, RefInputModifyHandler, formula::RefEdit&, 
void)
+{
+    if (mpActiveEdit)
+    {
+        if (mpActiveEdit == mxInputRangeEdit.get())
+        {
+            ScRangeList aRangeList;
+            bool bValid = ParseWithNames(aRangeList, 
mxInputRangeEdit->GetText(), mrDocument);
+            const ScRange* pRange = (bValid && aRangeList.size() == 1) ? 
&aRangeList[0] : nullptr;
+            if (pRange)
+            {
+                maInputRange = *pRange;
+                mxInputRangeEdit->StartUpdateData();
+            }
+            else
+            {
+                maInputRange = ScRange(ScAddress::INITIALIZE_INVALID);
+            }
+        }
+        else if (mpActiveEdit == mxOutputRangeEdit.get())
+        {
+            ScRangeList aRangeList;
+            bool bValid = ParseWithNames(aRangeList, 
mxOutputRangeEdit->GetText(), mrDocument);
+            const ScRange* pRange = (bValid && aRangeList.size() == 1) ? 
&aRangeList[0] : nullptr;
+            if (pRange)
+            {
+                maOutputRange = *pRange;
+                mxOutputRangeEdit->StartUpdateData();
+            }
+            else
+            {
+                maOutputRange = ScRange(ScAddress::INITIALIZE_INVALID);
+            }
+        }
+    }
+
+    mxButtonOk->set_sensitive(checkValidInputOutput());
+}
+
+IMPL_LINK(SparklineDialog, ButtonClicked, weld::Button&, rButton, void)
+{
+    if (mxButtonOk.get() == &rButton)
+    {
+        perform();
+        response(RET_OK);
+    }
+    else
+    {
+        response(RET_CANCEL);
+    }
+}
+
+namespace
+{
+enum class RangeOrientation
+{
+    Unknown,
+    Row,
+    Col
+};
+
+RangeOrientation calculateOrientation(sal_Int32 nOutputSize, ScRange const& 
rInputRange)
+{
+    sal_Int32 nRowSize = rInputRange.aEnd.Row() - rInputRange.aStart.Row();
+    sal_Int32 nColSize = rInputRange.aEnd.Col() - rInputRange.aStart.Col();
+
+    auto eInputOrientation = RangeOrientation::Unknown;
+    if (nOutputSize == nRowSize)
+        eInputOrientation = RangeOrientation::Row;
+    else if (nOutputSize == nColSize)
+        eInputOrientation = RangeOrientation::Col;
+    return eInputOrientation;
+}
+
+} // end anonymous namespace
+
+bool SparklineDialog::checkValidInputOutput()
+{
+    if (!maInputRange.IsValid() || !maOutputRange.IsValid())
+        return false;
+
+    RangeOrientation eInputOrientation = RangeOrientation::Unknown;
+    if (maOutputRange.aStart.Col() == maOutputRange.aEnd.Col())
+    {
+        sal_Int32 nOutputRowSize = maOutputRange.aEnd.Row() - 
maOutputRange.aStart.Row();
+        eInputOrientation = calculateOrientation(nOutputRowSize, maInputRange);
+    }
+    else if (maOutputRange.aStart.Row() == maOutputRange.aEnd.Row())
+    {
+        sal_Int32 nOutputColSize = maOutputRange.aEnd.Col() - 
maOutputRange.aStart.Col();
+        eInputOrientation = calculateOrientation(nOutputColSize, maInputRange);
+    }
+
+    return eInputOrientation != RangeOrientation::Unknown;
+}
+
+void SparklineDialog::perform()
+{
+    auto pSparklineGroup = std::make_shared<sc::SparklineGroup>();
+
+    if (maOutputRange.aStart.Col() == maOutputRange.aEnd.Col())
+    {
+        sal_Int32 nOutputRowSize = maOutputRange.aEnd.Row() - 
maOutputRange.aStart.Row();
+
+        auto eInputOrientation = calculateOrientation(nOutputRowSize, 
maInputRange);
+
+        if (eInputOrientation == RangeOrientation::Unknown)
+            return;
+
+        sal_Int32 nIndex = 0;
+        for (ScAddress aAddress = maOutputRange.aStart; aAddress.Row() <= 
maOutputRange.aEnd.Row();
+             aAddress.IncRow())
+        {
+            ScRange aInputRangeSlice = maInputRange;
+            if (eInputOrientation == RangeOrientation::Row)
+            {
+                aInputRangeSlice.aStart.SetRow(maInputRange.aStart.Row() + 
nIndex);
+                aInputRangeSlice.aEnd.SetRow(maInputRange.aStart.Row() + 
nIndex);
+            }
+            else
+            {
+                aInputRangeSlice.aStart.SetCol(maInputRange.aStart.Col() + 
nIndex);
+                aInputRangeSlice.aEnd.SetCol(maInputRange.aStart.Col() + 
nIndex);
+            }
+            auto* pCreated = mrDocument.CreateSparkline(aAddress, 
pSparklineGroup);
+            pCreated->setInputRange(aInputRangeSlice);
+            nIndex++;
+        }
+    }
+    else if (maOutputRange.aStart.Row() == maOutputRange.aEnd.Row())
+    {
+        sal_Int32 nOutputColSize = maOutputRange.aEnd.Col() - 
maOutputRange.aStart.Col();
+
+        auto eInputOrientation = calculateOrientation(nOutputColSize, 
maInputRange);
+
+        if (eInputOrientation == RangeOrientation::Unknown)
+            return;
+
+        sal_Int32 nIndex = 0;
+
+        for (ScAddress aAddress = maOutputRange.aStart; aAddress.Col() <= 
maOutputRange.aEnd.Col();
+             aAddress.IncCol())
+        {
+            ScRange aInputRangeSlice = maInputRange;
+            if (eInputOrientation == RangeOrientation::Row)
+            {
+                aInputRangeSlice.aStart.SetRow(maInputRange.aStart.Row() + 
nIndex);
+                aInputRangeSlice.aEnd.SetRow(maInputRange.aStart.Row() + 
nIndex);
+            }
+            else
+            {
+                aInputRangeSlice.aStart.SetCol(maInputRange.aStart.Col() + 
nIndex);
+                aInputRangeSlice.aEnd.SetCol(maInputRange.aStart.Col() + 
nIndex);
+            }
+            auto* pCreated = mrDocument.CreateSparkline(aAddress, 
pSparklineGroup);
+            pCreated->setInputRange(aInputRangeSlice);
+            nIndex++;
+        }
+    }
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/SparklineDialog.hxx 
b/sc/source/ui/inc/SparklineDialog.hxx
new file mode 100644
index 000000000000..a4a03f33491d
--- /dev/null
+++ b/sc/source/ui/inc/SparklineDialog.hxx
@@ -0,0 +1,64 @@
+/* -*- 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 <address.hxx>
+#include "anyrefdg.hxx"
+#include <viewdata.hxx>
+
+namespace sc
+{
+class SparklineDialog : public ScAnyRefDlgController
+{
+private:
+    ScViewData& mrViewData;
+    ScDocument& mrDocument;
+
+    ScRange maInputRange;
+    ScRange maOutputRange;
+
+    formula::RefEdit* mpActiveEdit;
+    bool mbDialogLostFocus;
+
+    std::unique_ptr<weld::Button> mxButtonOk;
+    std::unique_ptr<weld::Button> mxButtonCancel;
+
+    std::unique_ptr<weld::Label> mxInputRangeText;
+    std::unique_ptr<formula::RefEdit> mxInputRangeEdit;
+    std::unique_ptr<formula::RefButton> mxInputRangeButton;
+
+    std::unique_ptr<weld::Label> mxOutputRangeLabel;
+    std::unique_ptr<formula::RefEdit> mxOutputRangeEdit;
+    std::unique_ptr<formula::RefButton> mxOutputRangeButton;
+
+    void GetRangeFromSelection();
+
+    DECL_LINK(ButtonClicked, weld::Button&, void);
+    DECL_LINK(EditFocusHandler, formula::RefEdit&, void);
+    DECL_LINK(ButtonFocusHandler, formula::RefButton&, void);
+    DECL_LINK(LoseEditFocusHandler, formula::RefEdit&, void);
+    DECL_LINK(LoseButtonFocusHandler, formula::RefButton&, void);
+    DECL_LINK(RefInputModifyHandler, formula::RefEdit&, void);
+
+    void perform();
+    bool checkValidInputOutput();
+
+public:
+    SparklineDialog(SfxBindings* pBindings, SfxChildWindow* pChildWindow, 
weld::Window* pWindow,
+                    ScViewData& rViewData);
+    virtual ~SparklineDialog() override;
+
+    virtual void SetReference(const ScRange& rRef, ScDocument& rDocument) 
override;
+    virtual void SetActive() override;
+    virtual void Close() override;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/reffact.hxx b/sc/source/ui/inc/reffact.hxx
index c1b73606eb7f..4bf1254b4556 100644
--- a/sc/source/ui/inc/reffact.hxx
+++ b/sc/source/ui/inc/reffact.hxx
@@ -147,6 +147,18 @@ private:
     ScFourierAnalysisDialogWrapper() = delete;
 };
 
+namespace sc
+{
+
+class SparklineDialogWrapper :
+    public ChildControllerWrapper<SID_SPARKLINE_DIALOG>
+{
+private:
+    SparklineDialogWrapper() = delete;
+};
+
+}
+
 class ScAcceptChgDlgWrapper : public SfxChildWindow
 {
 public:
diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx
index 1a5f697a0a99..13d4430a956a 100644
--- a/sc/source/ui/view/cellsh.cxx
+++ b/sc/source/ui/view/cellsh.cxx
@@ -179,6 +179,7 @@ void ScCellShell::GetBlockState( SfxItemSet& rSet )
             case SID_ANALYSIS_OF_VARIANCE_DIALOG:
             case SID_CORRELATION_DIALOG:
             case SID_COVARIANCE_DIALOG:
+            case SID_INSERT_SPARKLINE:
             {
                 bDisable = !bSimpleArea;
             }
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index 7314ee15413c..44c640eb8aed 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -1051,6 +1051,15 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
         }
         break;
 
+        case SID_INSERT_SPARKLINE:
+        {
+            sal_uInt16 nId  = sc::SparklineDialogWrapper::GetChildWindowId();
+            SfxViewFrame* pViewFrame = pTabViewShell->GetViewFrame();
+            SfxChildWindow* pWindow = pViewFrame->GetChildWindow(nId);
+            pScMod->SetRefDialog(nId, pWindow == nullptr);
+        }
+        break;
+
         //  disposal (Outlines)
         //  SID_AUTO_OUTLINE, SID_OUTLINE_DELETEALL in Execute (in docsh.idl)
 
diff --git a/sc/source/ui/view/tabvwsh.cxx b/sc/source/ui/view/tabvwsh.cxx
index d8e48596f3f6..7337b5cc2f0d 100644
--- a/sc/source/ui/view/tabvwsh.cxx
+++ b/sc/source/ui/view/tabvwsh.cxx
@@ -97,6 +97,7 @@ void ScTabViewShell::InitInterface_Impl()
     
GetStaticInterface()->RegisterChildWindow(ScChiSquareTestDialogWrapper::GetChildWindowId());
     
GetStaticInterface()->RegisterChildWindow(ScFourierAnalysisDialogWrapper::GetChildWindowId());
     
GetStaticInterface()->RegisterChildWindow(ScCondFormatDlgWrapper::GetChildWindowId());
+    
GetStaticInterface()->RegisterChildWindow(sc::SparklineDialogWrapper::GetChildWindowId());
 }
 
 SFX_IMPL_NAMED_VIEWFACTORY( ScTabViewShell, "Default" )
diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx
index e43cb2ff31bc..667992e57da9 100644
--- a/sc/source/ui/view/tabvwshc.cxx
+++ b/sc/source/ui/view/tabvwshc.cxx
@@ -69,6 +69,7 @@
 #include <FourierAnalysisDialog.hxx>
 
 #include <PivotLayoutDialog.hxx>
+#include <SparklineDialog.hxx>
 
 #include <comphelper/lok.hxx>
 #include <o3tl/make_shared.hxx>
@@ -236,6 +237,11 @@ std::shared_ptr<SfxModelessDialogController> 
ScTabViewShell::CreateRefDialogCont
         case SID_RANDOM_NUMBER_GENERATOR_DIALOG:
             xResult = std::make_shared<ScRandomNumberGeneratorDialog>(pB, pCW, 
pParent, GetViewData());
             break;
+        case SID_SPARKLINE_DIALOG:
+        {
+            xResult = std::make_shared<sc::SparklineDialog>(pB, pCW, pParent, 
GetViewData());
+            break;
+        }
         case SID_DEFINE_DBNAME:
         {
             // when called for an existing range, then mark
diff --git a/sc/uiconfig/scalc/popupmenu/cell.xml 
b/sc/uiconfig/scalc/popupmenu/cell.xml
index fd086d0af975..135cfb2e742e 100644
--- a/sc/uiconfig/scalc/popupmenu/cell.xml
+++ b/sc/uiconfig/scalc/popupmenu/cell.xml
@@ -63,6 +63,8 @@
   <menu:menuitem menu:id=".uno:ShowNote"/>
   <menu:menuitem menu:id=".uno:HideNote"/>
   <menu:menuseparator/>
+  <menu:menuitem menu:id=".uno:InsertSparkline"/>
+  <menu:menuseparator/>
   <menu:menuitem menu:id=".uno:CurrentConditionalFormatDialog"/>
   <menu:menuitem menu:id=".uno:CurrentConditionalFormatManagerDialog"/>
   <menu:menuitem menu:id=".uno:FormatCellDialog"/>
diff --git a/sc/uiconfig/scalc/ui/sparklinedialog.ui 
b/sc/uiconfig/scalc/ui/sparklinedialog.ui
new file mode 100644
index 000000000000..9070ce2cd86e
--- /dev/null
+++ b/sc/uiconfig/scalc/ui/sparklinedialog.ui
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="sc">
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkDialog" id="SparklineDialog">
+    <property name="can-focus">False</property>
+    <property name="border-width">6</property>
+    <property name="title" translatable="yes" 
context="randomnumbergenerator|RandomNumberGeneratorDialog">Sparkline 
Dialog</property>
+    <property name="resizable">False</property>
+    <property name="default-width">0</property>
+    <property name="default-height">0</property>
+    <property name="type-hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can-focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">12</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="can-focus">False</property>
+            <property name="layout-style">end</property>
+            <child>
+              <object class="GtkButton" id="ok">
+                <property name="label" translatable="yes" 
context="stock">_OK</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="can-default">True</property>
+                <property name="has-default">True</property>
+                <property name="receives-default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="cancel">
+                <property name="label" translatable="yes" 
context="stock">_Close</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="can-default">True</property>
+                <property name="receives-default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="help">
+                <property name="label" translatable="yes" 
context="stock">_Help</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">True</property>
+                <property name="use-underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">3</property>
+                <property name="secondary">True</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack-type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkFrame" id="frame-data">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label-xalign">0</property>
+            <property name="shadow-type">none</property>
+            <child>
+              <!-- n-columns=3 n-rows=2 -->
+              <object class="GtkGrid">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="margin-start">6</property>
+                <property name="margin-end">6</property>
+                <property name="margin-top">6</property>
+                <property name="margin-bottom">7</property>
+                <property name="row-spacing">6</property>
+                <property name="column-spacing">6</property>
+                <child>
+                  <object class="GtkButton" id="cell-range-button">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">True</property>
+                    <accessibility>
+                      <relation type="labelled-by" target="cell-range-label"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">2</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="cell-range-edit">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="valign">center</property>
+                    <property name="hexpand">True</property>
+                    <property name="activates-default">True</property>
+                    <property name="width-chars">30</property>
+                    <property name="truncate-multiline">True</property>
+                    <accessibility>
+                      <relation type="labelled-by" target="cell-range-label"/>
+                    </accessibility>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" id="cell-range-edit-atkobject">
+                        <property name="AtkObject::accessible-description" 
translatable="yes" 
context="randomnumbergenerator|extended_tip|cell-range-edit">Define the range 
of cells to fill with random numbers. If you have previously selected a range, 
it will be displayed here.</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="output-range-button">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="receives-default">True</property>
+                    <accessibility>
+                      <relation type="labelled-by" 
target="output-range-label"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">2</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="output-range-edit">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="valign">center</property>
+                    <property name="hexpand">True</property>
+                    <property name="activates-default">True</property>
+                    <property name="width-chars">30</property>
+                    <property name="truncate-multiline">True</property>
+                    <accessibility>
+                      <relation type="labelled-by" 
target="output-range-label"/>
+                    </accessibility>
+                    <child internal-child="accessible">
+                      <object class="AtkObject" 
id="output-range-edit-atkobject">
+                        <property name="AtkObject::accessible-description" 
translatable="yes" 
context="randomnumbergenerator|extended_tip|cell-range-edit">Define the range 
of cells to fill with random numbers. If you have previously selected a range, 
it will be displayed here.</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left-attach">1</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="cell-range-label">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="randomnumbergenerator|cell-range-label">Input range:</property>
+                    <property name="use-underline">True</property>
+                    <property name="xalign">0</property>
+                    <accessibility>
+                      <relation type="label-for" target="cell-range-button"/>
+                      <relation type="label-for" target="cell-range-edit"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="output-range-label">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="label" translatable="yes" 
context="randomnumbergenerator|cell-range-label">Output range:</property>
+                    <property name="use-underline">True</property>
+                    <property name="xalign">0</property>
+                    <accessibility>
+                      <relation type="label-for" target="output-range-button"/>
+                      <relation type="label-for" target="output-range-edit"/>
+                    </accessibility>
+                  </object>
+                  <packing>
+                    <property name="left-attach">0</property>
+                    <property name="top-attach">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="label" translatable="yes" 
context="randomnumbergenerator|label1">Data</property>
+                <attributes>
+                  <attribute name="weight" value="bold"/>
+                </attributes>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-5">ok</action-widget>
+      <action-widget response="-6">cancel</action-widget>
+      <action-widget response="-11">help</action-widget>
+    </action-widgets>
+    <child internal-child="accessible">
+      <object class="AtkObject" id="SparklineDialog-atkobject">
+        <property name="AtkObject::accessible-description" translatable="yes" 
context="randomnumbergenerator|extended_tip|RandomNumberGeneratorDialog">Populate
 a cell range with automatically generated pseudo random numbers with the 
selected distribution function and its parameters.</property>
+      </object>
+    </child>
+  </object>
+</interface>
commit 77411e89cfa7667db3ead3bf81b3c01957254805
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Thu Mar 10 14:08:35 2022 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Mon Mar 14 13:52:31 2022 +0900

    sc: simple unit test for adding a new Sparkline to a new document
    
    Change-Id: Ifb42167300dadd0e6c48bf178b7e8902985db3d1

diff --git a/sc/CppunitTest_sc_sparkline_test.mk 
b/sc/CppunitTest_sc_sparkline_test.mk
index 30513b273791..499eaaf4ea38 100644
--- a/sc/CppunitTest_sc_sparkline_test.mk
+++ b/sc/CppunitTest_sc_sparkline_test.mk
@@ -15,6 +15,7 @@ $(eval $(call 
gb_CppunitTest_use_common_precompiled_header,sc_sparkline_test))
 
 $(eval $(call gb_CppunitTest_add_exception_objects,sc_sparkline_test, \
     sc/qa/unit/SparklineImportExportTest \
+    sc/qa/unit/SparklineTest \
 ))
 
 $(eval $(call gb_CppunitTest_use_libraries,sc_sparkline_test, \
diff --git a/sc/qa/unit/SparklineTest.cxx b/sc/qa/unit/SparklineTest.cxx
new file mode 100644
index 000000000000..d4a8d2d119a8
--- /dev/null
+++ b/sc/qa/unit/SparklineTest.cxx
@@ -0,0 +1,66 @@
+/* -*- 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 "helper/qahelper.hxx"
+#include <docsh.hxx>
+#include <Sparkline.hxx>
+#include <SparklineGroup.hxx>
+
+using namespace css;
+
+class SparklineTest : public ScBootstrapFixture
+{
+private:
+    uno::Reference<uno::XInterface> m_xCalcComponent;
+
+public:
+    SparklineTest()
+        : ScBootstrapFixture("sc/qa/unit/data")
+    {
+    }
+
+    virtual void setUp() override
+    {
+        test::BootstrapFixture::setUp();
+
+        // This is a bit of a fudge, we do this to ensure that 
ScGlobals::ensure,
+        // which is a private symbol to us, gets called
+        m_xCalcComponent = getMultiServiceFactory()->createInstance(
+            "com.sun.star.comp.Calc.SpreadsheetDocument");
+        CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent.is());
+    }
+
+    virtual void tearDown() override
+    {
+        uno::Reference<lang::XComponent>(m_xCalcComponent, 
uno::UNO_QUERY_THROW)->dispose();
+        test::BootstrapFixture::tearDown();
+    }
+
+    void testAddSparkline();
+
+    CPPUNIT_TEST_SUITE(SparklineTest);
+    CPPUNIT_TEST(testAddSparkline);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+void SparklineTest::testAddSparkline()
+{
+    ScDocShellRef xDocSh = loadEmptyDocument();
+    CPPUNIT_ASSERT(xDocSh);
+
+    ScDocument& rDocument = xDocSh->GetDocument();
+    auto pSparklineGroup = std::make_shared<sc::SparklineGroup>();
+
+    sc::Sparkline* pSparkline = rDocument.CreateSparkline(ScAddress(0, 0, 0), 
pSparklineGroup);
+    CPPUNIT_ASSERT(pSparkline);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SparklineTest);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 8aef68130b58055a5ad5b0d158f5a077654027a1
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Thu Mar 10 14:05:41 2022 +0900
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Mon Mar 14 13:52:20 2022 +0900

    sc: use forward decl. instead of include for SparklineGroup
    
    Shouldn't trigger large rebuilding when SparklineGroup.hxx is
    changed.
    
    Change-Id: I9c5d265e94dd92d9f23e86e3fc75ca0644991339

diff --git a/sc/inc/Sparkline.hxx b/sc/inc/Sparkline.hxx
index ad4688f33a5e..7b7785f3169a 100644
--- a/sc/inc/Sparkline.hxx
+++ b/sc/inc/Sparkline.hxx
@@ -11,12 +11,13 @@
 #pragma once
 
 #include "scdllapi.h"
-#include "SparklineGroup.hxx"
 #include "rangelst.hxx"
 #include <memory>
 
 namespace sc
 {
+class SparklineGroup;
+
 class SC_DLLPUBLIC Sparkline
 {
     SCCOL m_nColumn;
diff --git a/sc/qa/unit/SparklineImportExportTest.cxx 
b/sc/qa/unit/SparklineImportExportTest.cxx
index 2b8de3e34c29..650a45b89c6f 100644
--- a/sc/qa/unit/SparklineImportExportTest.cxx
+++ b/sc/qa/unit/SparklineImportExportTest.cxx
@@ -12,6 +12,7 @@
 #include <com/sun/star/lang/XComponent.hpp>
 #include <docsh.hxx>
 #include <Sparkline.hxx>
+#include <SparklineGroup.hxx>
 
 using namespace css;
 
@@ -52,7 +53,6 @@ public:
 
 namespace
 {
-
 void checkSparklines(ScDocument& rDocument)
 {
     // Sparkline at Sheet1:A2
diff --git a/sc/source/filter/excel/export/SparklineExt.cxx 
b/sc/source/filter/excel/export/SparklineExt.cxx
index f1e97b2c62ed..883389572ef7 100644
--- a/sc/source/filter/excel/export/SparklineExt.cxx
+++ b/sc/source/filter/excel/export/SparklineExt.cxx
@@ -12,6 +12,7 @@
 #include <oox/export/utils.hxx>
 #include <oox/token/namespaces.hxx>
 #include <oox/token/tokens.hxx>
+#include <SparklineGroup.hxx>
 
 using namespace oox;
 
diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx
index a6f9e91ec8fa..17903c3a23fd 100644
--- a/sc/source/ui/view/output.cxx
+++ b/sc/source/ui/view/output.cxx
@@ -64,6 +64,7 @@
 
 #include <colorscale.hxx>
 #include <Sparkline.hxx>
+#include <SparklineGroup.hxx>
 
 #include <math.h>
 #include <memory>

Reply via email to