diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2022-04-09 14:30:22 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2022-04-10 15:27:36 +0200 |
commit | a08f9ed2341bc60faae6b86538661fea40417ace (patch) | |
tree | d0e2ed53550d01b4e418eec55276ad358b4b54c7 /sc | |
parent | 655b6c2f46a73d9893ba8e6b572731a5890a4f72 (diff) |
sc: add UI, undo/redo and test to change sparkline data range
This adds a "edit sparkline" action to the context menu and a
dialog to change the data range of a sparkline. To change a
sparkline using undo/redo, a new class UndoEditSparkline was
added, which allows to change the attributes of a sparkline and
revert back the old attributes when undoing. This is then used in
the Dialog when setting the changed data range of a sparkline.
To make sure that undo/redo works correctly, a simple unit tests
was added.
Change-Id: I08af1813fa288278bc0d33b0540660b325b17235
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132748
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/Library_sc.mk | 2 | ||||
-rw-r--r-- | sc/UIConfig_scalc.mk | 1 | ||||
-rw-r--r-- | sc/inc/globstr.hrc | 1 | ||||
-rw-r--r-- | sc/inc/sc.hrc | 4 | ||||
-rw-r--r-- | sc/qa/unit/SparklineTest.cxx | 64 | ||||
-rw-r--r-- | sc/sdi/cellsh.sdi | 1 | ||||
-rw-r--r-- | sc/sdi/scalc.sdi | 17 | ||||
-rw-r--r-- | sc/source/ui/app/scdll.cxx | 1 | ||||
-rw-r--r-- | sc/source/ui/dialogs/SparklineDataRangeDialog.cxx | 202 | ||||
-rw-r--r-- | sc/source/ui/docshell/docfunc.cxx | 12 | ||||
-rw-r--r-- | sc/source/ui/inc/SparklineDataRangeDialog.hxx | 66 | ||||
-rw-r--r-- | sc/source/ui/inc/docfunc.hxx | 2 | ||||
-rw-r--r-- | sc/source/ui/inc/reffact.hxx | 7 | ||||
-rw-r--r-- | sc/source/ui/inc/undo/UndoEditSparkline.hxx | 47 | ||||
-rw-r--r-- | sc/source/ui/undo/UndoEditSparkline.cxx | 63 | ||||
-rw-r--r-- | sc/source/ui/view/cellsh.cxx | 6 | ||||
-rw-r--r-- | sc/source/ui/view/cellsh1.cxx | 10 | ||||
-rw-r--r-- | sc/source/ui/view/tabvwsh.cxx | 1 | ||||
-rw-r--r-- | sc/source/ui/view/tabvwshc.cxx | 6 | ||||
-rw-r--r-- | sc/uiconfig/scalc/popupmenu/cell.xml | 1 | ||||
-rw-r--r-- | sc/uiconfig/scalc/ui/sparklinedatarangedialog.ui | 148 |
21 files changed, 660 insertions, 2 deletions
diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 519daa881530..bd69b9e57c24 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -421,6 +421,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/ui/dbgui/validate \ sc/source/ui/dialogs/searchresults \ sc/source/ui/dialogs/SparklineDialog \ + sc/source/ui/dialogs/SparklineDataRangeDialog \ sc/source/ui/docshell/arealink \ sc/source/ui/docshell/autostyl \ sc/source/ui/docshell/datastream \ @@ -561,6 +562,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ sc/source/ui/undo/UndoDeleteSparklineGroup \ sc/source/ui/undo/UndoUngroupSparklines \ sc/source/ui/undo/UndoGroupSparklines \ + sc/source/ui/undo/UndoEditSparkline \ sc/source/ui/unoobj/ChartRangeSelectionListener \ sc/source/ui/unoobj/addruno \ sc/source/ui/unoobj/afmtuno \ diff --git a/sc/UIConfig_scalc.mk b/sc/UIConfig_scalc.mk index 302f08ff3fb3..643645ee7432 100644 --- a/sc/UIConfig_scalc.mk +++ b/sc/UIConfig_scalc.mk @@ -245,6 +245,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/scalc,\ sc/uiconfig/scalc/ui/sortoptionspage \ sc/uiconfig/scalc/ui/sortwarning \ sc/uiconfig/scalc/ui/sparklinedialog \ + sc/uiconfig/scalc/ui/sparklinedatarangedialog \ sc/uiconfig/scalc/ui/splitcolumnentry \ sc/uiconfig/scalc/ui/subtotaldialog \ sc/uiconfig/scalc/ui/subtotaloptionspage \ diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc index 96d2dca307a5..7f2bcb28b0ba 100644 --- a/sc/inc/globstr.hrc +++ b/sc/inc/globstr.hrc @@ -545,6 +545,7 @@ #define STR_UNDO_EDIT_SPARKLINE_GROUP NC_("STR_UNDO_EDIT_SPARKLINE_GROUP", "Edit Sparkline Group") #define STR_UNDO_GROUP_SPARKLINES NC_("STR_UNDO_GROUP_SPARKLINES", "Group Sparklines") #define STR_UNDO_UNGROUP_SPARKLINES NC_("STR_UNDO_UNGROUP_SPARKLINES", "Ungroup Sparklines") +#define STR_UNDO_EDIT_SPARKLINE NC_("STR_UNDO_EDIT_SPARKLINE", "Edit Sparkline") #endif diff --git a/sc/inc/sc.hrc b/sc/inc/sc.hrc index 207dc4224e53..a02df6204ad5 100644 --- a/sc/inc/sc.hrc +++ b/sc/inc/sc.hrc @@ -239,6 +239,7 @@ class SvxZoomSliderItem; #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) +#define SID_SPARKLINE_DATA_RANGE_DIALOG (SC_MESSAGE_START + 90) // functions @@ -314,7 +315,8 @@ class SvxZoomSliderItem; #define SID_DELETE_SPARKLINE_GROUP (INSERT_MENU_START + 28) #define SID_GROUP_SPARKLINES (INSERT_MENU_START + 29) #define SID_UNGROUP_SPARKLINES (INSERT_MENU_START + 30) -#define INSERT_MENU_END (INSERT_MENU_START + 31) +#define SID_EDIT_SPARKLINE (INSERT_MENU_START + 31) +#define INSERT_MENU_END (INSERT_MENU_START + 32) #define FORMAT_MENU_START (INSERT_MENU_END) #define FID_CELL_FORMAT (FORMAT_MENU_START) diff --git a/sc/qa/unit/SparklineTest.cxx b/sc/qa/unit/SparklineTest.cxx index f8d07edc53e6..9c52ab1d1c65 100644 --- a/sc/qa/unit/SparklineTest.cxx +++ b/sc/qa/unit/SparklineTest.cxx @@ -58,6 +58,7 @@ public: void testUndoRedoEditSparklineGroup(); void testUndoRedoUngroupSparklines(); void testUndoRedoGroupSparklines(); + void testUndoRedoEditSparkline(); void testSparklineList(); CPPUNIT_TEST_SUITE(SparklineTest); @@ -72,6 +73,7 @@ public: CPPUNIT_TEST(testUndoRedoEditSparklineGroup); CPPUNIT_TEST(testUndoRedoUngroupSparklines); CPPUNIT_TEST(testUndoRedoGroupSparklines); + CPPUNIT_TEST(testUndoRedoEditSparkline); CPPUNIT_TEST(testSparklineList); CPPUNIT_TEST_SUITE_END(); }; @@ -867,6 +869,68 @@ void SparklineTest::testUndoRedoGroupSparklines() xDocSh->DoClose(); } +void SparklineTest::testUndoRedoEditSparkline() +{ + ScDocShellRef xDocSh = loadEmptyDocument(); + CPPUNIT_ASSERT(xDocSh); + + ScDocument& rDocument = xDocSh->GetDocument(); + ScTabViewShell* pViewShell = xDocSh->GetBestViewShell(false); + CPPUNIT_ASSERT(pViewShell); + + auto& rDocFunc = xDocSh->GetDocFunc(); + + // Try to delete sparkline that doesn't exist - returns false + CPPUNIT_ASSERT(!rDocFunc.DeleteSparkline(ScAddress(0, 6, 0))); + + // insert test data - A1:A6 + insertTestData(rDocument); + + // Sparkline range + ScAddress aAddress(0, 6, 0); + ScRange aRange(aAddress); + + // Check Sparkline at cell A7 doesn't exists + auto pSparkline = rDocument.GetSparkline(aAddress); + CPPUNIT_ASSERT(!pSparkline); + + auto pSparklineGroup = std::make_shared<sc::SparklineGroup>(); + CPPUNIT_ASSERT(rDocFunc.InsertSparklines(ScRange(0, 0, 0, 0, 5, 0), aRange, pSparklineGroup)); + + // Check Sparkline at cell A7 + pSparkline = rDocument.GetSparkline(aAddress); + CPPUNIT_ASSERT(pSparkline); + CPPUNIT_ASSERT_EQUAL(size_t(1), pSparkline->getInputRange().size()); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, 0, 0, 5, 0), pSparkline->getInputRange()[0]); + + // Change Sparkline + CPPUNIT_ASSERT( + rDocFunc.ChangeSparkline(pSparkline, SCTAB(0), ScRangeList(ScRange(0, 1, 0, 0, 4, 0)))); + + pSparkline = rDocument.GetSparkline(aAddress); + CPPUNIT_ASSERT(pSparkline); + CPPUNIT_ASSERT_EQUAL(size_t(1), pSparkline->getInputRange().size()); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 1, 0, 0, 4, 0), pSparkline->getInputRange()[0]); + + // Undo + rDocument.GetUndoManager()->Undo(); + + pSparkline = rDocument.GetSparkline(aAddress); + CPPUNIT_ASSERT(pSparkline); + CPPUNIT_ASSERT_EQUAL(size_t(1), pSparkline->getInputRange().size()); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, 0, 0, 5, 0), pSparkline->getInputRange()[0]); + + // Redo + rDocument.GetUndoManager()->Redo(); + + pSparkline = rDocument.GetSparkline(aAddress); + CPPUNIT_ASSERT(pSparkline); + CPPUNIT_ASSERT_EQUAL(size_t(1), pSparkline->getInputRange().size()); + CPPUNIT_ASSERT_EQUAL(ScRange(0, 1, 0, 0, 4, 0), pSparkline->getInputRange()[0]); + + xDocSh->DoClose(); +} + void SparklineTest::testSparklineList() { ScDocShellRef xDocSh = loadEmptyDocument(); diff --git a/sc/sdi/cellsh.sdi b/sc/sdi/cellsh.sdi index 8fb939d9bf74..38eb86cb27b9 100644 --- a/sc/sdi/cellsh.sdi +++ b/sc/sdi/cellsh.sdi @@ -238,6 +238,7 @@ interface CellSelection SID_INSERT_SPARKLINE [ ExecMethod = ExecuteEdit; StateMethod = GetBlockState; ] SID_DELETE_SPARKLINE [ ExecMethod = ExecuteEdit; StateMethod = GetBlockState; ] SID_EDIT_SPARKLINE_GROUP [ ExecMethod = ExecuteEdit; StateMethod = GetBlockState; ] + SID_EDIT_SPARKLINE [ ExecMethod = ExecuteEdit; StateMethod = GetBlockState; ] SID_DELETE_SPARKLINE_GROUP [ ExecMethod = ExecuteEdit; StateMethod = GetBlockState; ] SID_GROUP_SPARKLINES [ ExecMethod = ExecuteEdit; StateMethod = GetBlockState; ] SID_UNGROUP_SPARKLINES [ ExecMethod = ExecuteEdit; StateMethod = GetBlockState; ] diff --git a/sc/sdi/scalc.sdi b/sc/sdi/scalc.sdi index ef823941d37a..a84b7da1348b 100644 --- a/sc/sdi/scalc.sdi +++ b/sc/sdi/scalc.sdi @@ -2321,6 +2321,23 @@ SfxVoidItem DeleteSparkline SID_DELETE_SPARKLINE GroupId = SfxGroupId::Edit; ] +SfxVoidItem EditSparkline SID_EDIT_SPARKLINE +() +[ + AutoUpdate = FALSE, + FastCall = FALSE, + ReadOnlyDoc = TRUE, + Toggle = FALSE, + Container = FALSE, + RecordAbsolute = FALSE, + RecordPerSet; + + AccelConfig = TRUE, + MenuConfig = TRUE, + ToolBoxConfig = TRUE, + GroupId = SfxGroupId::Edit; +] + SfxVoidItem EditSparklineGroup SID_EDIT_SPARKLINE_GROUP () [ diff --git a/sc/source/ui/app/scdll.cxx b/sc/source/ui/app/scdll.cxx index a0bdf08b16c0..58efb29ecb9a 100644 --- a/sc/source/ui/app/scdll.cxx +++ b/sc/source/ui/app/scdll.cxx @@ -207,6 +207,7 @@ void ScDLL::Init() ScChiSquareTestDialogWrapper ::RegisterChildWindow(false, pMod); ScFourierAnalysisDialogWrapper ::RegisterChildWindow(false, pMod); sc::SparklineDialogWrapper ::RegisterChildWindow(false, pMod); + sc::SparklineDataRangeDialogWrapper ::RegisterChildWindow(false, pMod); // Redlining Window ScAcceptChgDlgWrapper ::RegisterChildWindow(false, pMod); diff --git a/sc/source/ui/dialogs/SparklineDataRangeDialog.cxx b/sc/source/ui/dialogs/SparklineDataRangeDialog.cxx new file mode 100644 index 000000000000..f085e737c77c --- /dev/null +++ b/sc/source/ui/dialogs/SparklineDataRangeDialog.cxx @@ -0,0 +1,202 @@ +/* -*- 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 <SparklineDataRangeDialog.hxx> +#include <Sparkline.hxx> +#include <reffact.hxx> +#include <docfunc.hxx> + +namespace sc +{ +SparklineDataRangeDialog::SparklineDataRangeDialog(SfxBindings* pBindings, + SfxChildWindow* pChildWindow, + weld::Window* pWindow, ScViewData& rViewData) + : ScAnyRefDlgController(pBindings, pChildWindow, pWindow, + u"modules/scalc/ui/sparklinedatarangedialog.ui", + "SparklineDataRangeDialog") + , mrViewData(rViewData) + , mrDocument(rViewData.GetDocument()) + , mpActiveEdit(nullptr) + , mbDialogLostFocus(false) + , mxButtonOk(m_xBuilder->weld_button("ok")) + , mxButtonCancel(m_xBuilder->weld_button("cancel")) + , mxDataRangeLabel(m_xBuilder->weld_label("cell-range-label")) + , mxDataRangeEdit(new formula::RefEdit(m_xBuilder->weld_entry("cell-range-edit"))) + , mxDataRangeButton(new formula::RefButton(m_xBuilder->weld_button("cell-range-button"))) + +{ + mxDataRangeEdit->SetReferences(this, mxDataRangeLabel.get()); + mxDataRangeButton->SetReferences(this, mxDataRangeEdit.get()); + + mxButtonCancel->connect_clicked(LINK(this, SparklineDataRangeDialog, ButtonClicked)); + mxButtonOk->connect_clicked(LINK(this, SparklineDataRangeDialog, ButtonClicked)); + + mxButtonOk->set_sensitive(false); + + Link<formula::RefEdit&, void> aEditLink + = LINK(this, SparklineDataRangeDialog, EditFocusHandler); + mxDataRangeEdit->SetGetFocusHdl(aEditLink); + aEditLink = LINK(this, SparklineDataRangeDialog, LoseEditFocusHandler); + mxDataRangeEdit->SetLoseFocusHdl(aEditLink); + + Link<formula::RefButton&, void> aButtonLink + = LINK(this, SparklineDataRangeDialog, ButtonFocusHandler); + mxDataRangeButton->SetGetFocusHdl(aButtonLink); + aButtonLink = LINK(this, SparklineDataRangeDialog, LoseButtonFocusHandler); + mxDataRangeButton->SetLoseFocusHdl(aButtonLink); + + Link<formula::RefEdit&, void> aModifyLink + = LINK(this, SparklineDataRangeDialog, RefInputModifyHandler); + mxDataRangeEdit->SetModifyHdl(aModifyLink); + + setupValues(); + + mxDataRangeEdit->GrabFocus(); +} + +SparklineDataRangeDialog::~SparklineDataRangeDialog() = default; + +void SparklineDataRangeDialog::setupValues() +{ + ScAddress aCurrentAddress = mrViewData.GetCurPos(); + mpSparkline = mrDocument.GetSparkline(aCurrentAddress); + + if (mpSparkline) + { + ScRangeList aRangeList(mpSparkline->getInputRange()); + if (!aRangeList.empty()) + { + maDataRange = aRangeList[0]; + OUString aString + = maDataRange.Format(mrDocument, ScRefFlags::VALID | ScRefFlags::TAB_3D, + mrDocument.GetAddressConvention()); + mxDataRangeEdit->SetRefString(aString); + mxButtonOk->set_sensitive(true); + } + } +} + +void SparklineDataRangeDialog::Close() +{ + DoClose(sc::SparklineDataRangeDialogWrapper::GetChildWindowId()); +} + +void SparklineDataRangeDialog::SetActive() +{ + if (mbDialogLostFocus) + { + mbDialogLostFocus = false; + if (mpActiveEdit) + mpActiveEdit->GrabFocus(); + } + else + { + m_xDialog->grab_focus(); + } + RefInputDone(); +} + +void SparklineDataRangeDialog::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 == mxDataRangeEdit.get()) + { + maDataRange = rReferenceRange; + aString = maDataRange.Format(rDocument, eFlags, eAddressConvention); + mxDataRangeEdit->SetRefString(aString); + } + } +} + +IMPL_LINK(SparklineDataRangeDialog, EditFocusHandler, formula::RefEdit&, rEdit, void) +{ + if (mxDataRangeEdit.get() == &rEdit) + mpActiveEdit = mxDataRangeEdit.get(); + else + mpActiveEdit = nullptr; + + if (mpActiveEdit) + mpActiveEdit->SelectAll(); +} + +IMPL_LINK(SparklineDataRangeDialog, ButtonFocusHandler, formula::RefButton&, rButton, void) +{ + if (mxDataRangeButton.get() == &rButton) + mpActiveEdit = mxDataRangeEdit.get(); + else + mpActiveEdit = nullptr; + + if (mpActiveEdit) + mpActiveEdit->SelectAll(); +} + +IMPL_LINK_NOARG(SparklineDataRangeDialog, LoseEditFocusHandler, formula::RefEdit&, void) +{ + mbDialogLostFocus = !m_xDialog->has_toplevel_focus(); +} + +IMPL_LINK_NOARG(SparklineDataRangeDialog, LoseButtonFocusHandler, formula::RefButton&, void) +{ + mbDialogLostFocus = !m_xDialog->has_toplevel_focus(); +} + +IMPL_LINK_NOARG(SparklineDataRangeDialog, RefInputModifyHandler, formula::RefEdit&, void) +{ + if (mpActiveEdit) + { + if (mpActiveEdit == mxDataRangeEdit.get()) + { + ScRangeList aRangeList; + bool bValid = ParseWithNames(aRangeList, mxDataRangeEdit->GetText(), mrDocument); + const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr; + if (pRange) + { + maDataRange = *pRange; + mxDataRangeEdit->StartUpdateData(); + } + else + { + maDataRange = ScRange(ScAddress::INITIALIZE_INVALID); + } + } + } +} + +IMPL_LINK(SparklineDataRangeDialog, ButtonClicked, weld::Button&, rButton, void) +{ + if (mxButtonOk.get() == &rButton) + { + perform(); + response(RET_OK); + } + else + { + response(RET_CANCEL); + } +} + +void SparklineDataRangeDialog::perform() +{ + ScRangeList aList{ maDataRange }; + + auto& rDocFunc = mrViewData.GetDocShell()->GetDocFunc(); + rDocFunc.ChangeSparkline(mpSparkline, mrViewData.GetTabNo(), aList); +} + +} // end sc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index 411658e1136a..eee39e0e81f5 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -104,6 +104,7 @@ #include <undo/UndoEditSparklineGroup.hxx> #include <undo/UndoUngroupSparklines.hxx> #include <undo/UndoGroupSparklines.hxx> +#include <undo/UndoEditSparkline.hxx> #include <config_features.h> #include <memory> @@ -5893,7 +5894,7 @@ bool ScDocFunc::ChangeSparklineGroupAttributes(std::shared_ptr<sc::SparklineGrou bool ScDocFunc::GroupSparklines(ScRange const& rRange, std::shared_ptr<sc::SparklineGroup> const& rpGroup) { auto pUndo = std::make_unique<sc::UndoGroupSparklines>(rDocShell, rRange, rpGroup); - // ungroup sparklines by "redoing" + // group sparklines by "redoing" pUndo->Redo(); rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); return true; @@ -5908,4 +5909,13 @@ bool ScDocFunc::UngroupSparklines(ScRange const& rRange) return true; } +bool ScDocFunc::ChangeSparkline(std::shared_ptr<sc::Sparkline> const& rpSparkline, SCTAB nTab, ScRangeList const& rDataRange) +{ + auto pUndo = std::make_unique<sc::UndoEditSparkline>(rDocShell, rpSparkline, nTab, rDataRange); + // change sparkline by "redoing" + pUndo->Redo(); + rDocShell.GetUndoManager()->AddUndoAction(std::move(pUndo)); + return true; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/SparklineDataRangeDialog.hxx b/sc/source/ui/inc/SparklineDataRangeDialog.hxx new file mode 100644 index 000000000000..41d882c8bc40 --- /dev/null +++ b/sc/source/ui/inc/SparklineDataRangeDialog.hxx @@ -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/. + */ + +#pragma once + +#include <address.hxx> +#include "anyrefdg.hxx" +#include "viewdata.hxx" + +#include <SparklineGroup.hxx> +#include <SparklineAttributes.hxx> + +class ColorListBox; + +namespace sc +{ +class SparklineDataRangeDialog : public ScAnyRefDlgController +{ +private: + ScViewData& mrViewData; + ScDocument& mrDocument; + + std::shared_ptr<sc::Sparkline> mpSparkline; + + ScRange maDataRange; + + formula::RefEdit* mpActiveEdit; + bool mbDialogLostFocus; + + std::unique_ptr<weld::Button> mxButtonOk; + std::unique_ptr<weld::Button> mxButtonCancel; + + std::unique_ptr<weld::Label> mxDataRangeLabel; + std::unique_ptr<formula::RefEdit> mxDataRangeEdit; + std::unique_ptr<formula::RefButton> mxDataRangeButton; + + 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 setupValues(); + + void perform(); + bool checkValidInputOutput(); + +public: + SparklineDataRangeDialog(SfxBindings* pBindings, SfxChildWindow* pChildWindow, + weld::Window* pWindow, ScViewData& rViewData); + virtual ~SparklineDataRangeDialog() override; + + void SetReference(const ScRange& rRef, ScDocument& rDocument) override; + void SetActive() override; + void Close() override; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/docfunc.hxx b/sc/source/ui/inc/docfunc.hxx index 938f96835b4d..f7ca3e422bc8 100644 --- a/sc/source/ui/inc/docfunc.hxx +++ b/sc/source/ui/inc/docfunc.hxx @@ -56,6 +56,7 @@ namespace sc struct ColRowSpan; class SparklineAttributes; class SparklineGroup; + class Sparkline; } class ScDocFunc @@ -246,6 +247,7 @@ public: sc::SparklineAttributes const& rNewAttributes); SC_DLLPUBLIC bool GroupSparklines(ScRange const& rRange, std::shared_ptr<sc::SparklineGroup> const& rpGroup); SC_DLLPUBLIC bool UngroupSparklines(ScRange const& rRange); + SC_DLLPUBLIC bool ChangeSparkline(std::shared_ptr<sc::Sparkline> const& rpSparkline, SCTAB nTab, ScRangeList const& rDataRange); private: void ProtectDocument(const ScDocProtection& rProtect); diff --git a/sc/source/ui/inc/reffact.hxx b/sc/source/ui/inc/reffact.hxx index 4bf1254b4556..1394418ffa85 100644 --- a/sc/source/ui/inc/reffact.hxx +++ b/sc/source/ui/inc/reffact.hxx @@ -157,6 +157,13 @@ private: SparklineDialogWrapper() = delete; }; +class SparklineDataRangeDialogWrapper : + public ChildControllerWrapper<SID_SPARKLINE_DATA_RANGE_DIALOG> +{ +private: + SparklineDataRangeDialogWrapper() = delete; +}; + } class ScAcceptChgDlgWrapper : public SfxChildWindow diff --git a/sc/source/ui/inc/undo/UndoEditSparkline.hxx b/sc/source/ui/inc/undo/UndoEditSparkline.hxx new file mode 100644 index 000000000000..4e33eaa1f5df --- /dev/null +++ b/sc/source/ui/inc/undo/UndoEditSparkline.hxx @@ -0,0 +1,47 @@ +/* -*- 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 <undobase.hxx> +#include <address.hxx> +#include <rangelst.hxx> +#include <memory> + +namespace sc +{ +class Sparkline; +struct SparklineData; + +/** Undo action for editing a Sparkline */ +class UndoEditSparkline : public ScSimpleUndo +{ +private: + std::shared_ptr<sc::Sparkline> mpSparkline; + SCTAB mnTab; + ScRangeList maOldDataRange; + ScRangeList maNewDataRange; + +public: + UndoEditSparkline(ScDocShell& rDocShell, std::shared_ptr<sc::Sparkline> const& rpSparkline, + SCTAB nTab, ScRangeList const& rDataRange); + + virtual ~UndoEditSparkline() override; + + void Undo() override; + void Redo() override; + bool CanRepeat(SfxRepeatTarget& rTarget) const override; + void Repeat(SfxRepeatTarget& rTarget) override; + OUString GetComment() const override; +}; + +} // namespace sc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/undo/UndoEditSparkline.cxx b/sc/source/ui/undo/UndoEditSparkline.cxx new file mode 100644 index 000000000000..b1f6f38f5dc4 --- /dev/null +++ b/sc/source/ui/undo/UndoEditSparkline.cxx @@ -0,0 +1,63 @@ +/* -*- 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 <undo/UndoEditSparkline.hxx> +#include <globstr.hrc> +#include <scresid.hxx> + +#include <Sparkline.hxx> +#include <SparklineGroup.hxx> + +namespace sc +{ +UndoEditSparkline::UndoEditSparkline(ScDocShell& rDocShell, + std::shared_ptr<sc::Sparkline> const& rpSparkline, SCTAB nTab, + ScRangeList const& rDataRange) + : ScSimpleUndo(&rDocShell) + , mpSparkline(rpSparkline) + , mnTab(nTab) + , maOldDataRange(mpSparkline->getInputRange()) + , maNewDataRange(rDataRange) +{ +} + +UndoEditSparkline::~UndoEditSparkline() = default; + +void UndoEditSparkline::Undo() +{ + BeginUndo(); + + mpSparkline->setInputRange(maOldDataRange); + + pDocShell->PostPaintCell(ScAddress(mpSparkline->getColumn(), mpSparkline->getRow(), mnTab)); + + EndUndo(); +} + +void UndoEditSparkline::Redo() +{ + BeginRedo(); + + mpSparkline->setInputRange(maNewDataRange); + + pDocShell->PostPaintCell(ScAddress(mpSparkline->getColumn(), mpSparkline->getRow(), mnTab)); + + EndRedo(); +} + +void UndoEditSparkline::Repeat(SfxRepeatTarget& /*rTarget*/) {} + +bool UndoEditSparkline::CanRepeat(SfxRepeatTarget& /*rTarget*/) const { return false; } + +OUString UndoEditSparkline::GetComment() const { return ScResId(STR_UNDO_EDIT_SPARKLINE); } + +} // end sc namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx index 0824054c676b..215587cfa0e5 100644 --- a/sc/source/ui/view/cellsh.cxx +++ b/sc/source/ui/view/cellsh.cxx @@ -194,6 +194,12 @@ void ScCellShell::GetBlockState( SfxItemSet& rSet ) } break; + case SID_EDIT_SPARKLINE: + { + bDisable = !rDoc.HasSparkline(GetViewData().GetCurPos()); + } + break; + case SID_DELETE_SPARKLINE: case SID_EDIT_SPARKLINE_GROUP: case SID_DELETE_SPARKLINE_GROUP: diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx index fc221645a5d6..943df5b926ff 100644 --- a/sc/source/ui/view/cellsh1.cxx +++ b/sc/source/ui/view/cellsh1.cxx @@ -1063,6 +1063,16 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) } break; + case SID_EDIT_SPARKLINE: + { + sal_uInt16 nId = sc::SparklineDataRangeDialogWrapper::GetChildWindowId(); + SfxViewFrame* pViewFrame = pTabViewShell->GetViewFrame(); + SfxChildWindow* pWindow = pViewFrame->GetChildWindow(nId); + pScMod->SetRefDialog(nId, pWindow == nullptr); + rReq.Done(); + } + break; + case SID_DELETE_SPARKLINE: { pTabViewShell->DeleteContents(InsertDeleteFlags::SPARKLINES); diff --git a/sc/source/ui/view/tabvwsh.cxx b/sc/source/ui/view/tabvwsh.cxx index 7337b5cc2f0d..669c7554f3bd 100644 --- a/sc/source/ui/view/tabvwsh.cxx +++ b/sc/source/ui/view/tabvwsh.cxx @@ -98,6 +98,7 @@ void ScTabViewShell::InitInterface_Impl() GetStaticInterface()->RegisterChildWindow(ScFourierAnalysisDialogWrapper::GetChildWindowId()); GetStaticInterface()->RegisterChildWindow(ScCondFormatDlgWrapper::GetChildWindowId()); GetStaticInterface()->RegisterChildWindow(sc::SparklineDialogWrapper::GetChildWindowId()); + GetStaticInterface()->RegisterChildWindow(sc::SparklineDataRangeDialogWrapper::GetChildWindowId()); } SFX_IMPL_NAMED_VIEWFACTORY( ScTabViewShell, "Default" ) diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx index 667992e57da9..5ea8701a0dbe 100644 --- a/sc/source/ui/view/tabvwshc.cxx +++ b/sc/source/ui/view/tabvwshc.cxx @@ -70,6 +70,7 @@ #include <PivotLayoutDialog.hxx> #include <SparklineDialog.hxx> +#include <SparklineDataRangeDialog.hxx> #include <comphelper/lok.hxx> #include <o3tl/make_shared.hxx> @@ -242,6 +243,11 @@ std::shared_ptr<SfxModelessDialogController> ScTabViewShell::CreateRefDialogCont xResult = std::make_shared<sc::SparklineDialog>(pB, pCW, pParent, GetViewData()); break; } + case SID_SPARKLINE_DATA_RANGE_DIALOG: + { + xResult = std::make_shared<sc::SparklineDataRangeDialog>(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 1de462b89fe1..fb7f4ff9ecd8 100644 --- a/sc/uiconfig/scalc/popupmenu/cell.xml +++ b/sc/uiconfig/scalc/popupmenu/cell.xml @@ -69,6 +69,7 @@ <menu:menuitem menu:id=".uno:DeleteSparkline"/> <menu:menuitem menu:id=".uno:DeleteSparklineGroup"/> <menu:menuitem menu:id=".uno:EditSparklineGroup"/> + <menu:menuitem menu:id=".uno:EditSparkline"/> <menu:menuitem menu:id=".uno:GroupSparklines"/> <menu:menuitem menu:id=".uno:UngroupSparklines"/> </menu:menupopup> diff --git a/sc/uiconfig/scalc/ui/sparklinedatarangedialog.ui b/sc/uiconfig/scalc/ui/sparklinedatarangedialog.ui new file mode 100644 index 000000000000..1e1412e01981 --- /dev/null +++ b/sc/uiconfig/scalc/ui/sparklinedatarangedialog.ui @@ -0,0 +1,148 @@ +<?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="SparklineDataRangeDialog"> + <property name="can-focus">False</property> + <property name="border-width">6</property> + <property name="title" translatable="yes" context="SparklineDialog">Sparkline Data Range Dialog</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">2</property> + </packing> + </child> + <child> + <!-- n-columns=3 n-rows=1 --> + <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="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="GtkLabel" id="cell-range-label"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes" context="SparklineDataRangeDialog|cell-range-label">Data 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> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</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> |