officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu | 8 sc/Library_sc.mk | 1 sc/UIConfig_scalc.mk | 1 sc/inc/sc.hrc | 5 sc/sdi/cellsh.sdi | 1 sc/sdi/scalc.sdi | 17 sc/source/ui/app/scdll.cxx | 1 sc/source/ui/dialogs/SparklineDialog.cxx | 324 ++++++++++ sc/source/ui/inc/SparklineDialog.hxx | 64 + sc/source/ui/inc/reffact.hxx | 12 sc/source/ui/view/cellsh.cxx | 1 sc/source/ui/view/cellsh1.cxx | 9 sc/source/ui/view/tabvwsh.cxx | 1 sc/source/ui/view/tabvwshc.cxx | 6 sc/uiconfig/scalc/popupmenu/cell.xml | 2 sc/uiconfig/scalc/ui/sparklinedialog.ui | 218 ++++++ 16 files changed, 670 insertions(+), 1 deletion(-)
New commits: commit c61aa2dea120cc083f3cd51f0347284f47a9d566 Author: Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk> AuthorDate: Fri Mar 11 20:49:09 2022 +0900 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Sun Apr 3 09:06:44 2022 +0200 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 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132465 Tested-by: Tomaž Vajngerl <qui...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/CalcCommands.xcu index 9d9abf01a239..e64af0f86161 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..85515462c323 --- /dev/null +++ b/sc/uiconfig/scalc/ui/sparklinedialog.ui @@ -0,0 +1,218 @@ +<?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="SparklineDialog">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> + </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> + </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="SparklineDialog|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="SparklineDialog|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="SparklineDialog|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> + </object> +</interface>