summaryrefslogtreecommitdiffstats
path: root/sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx')
-rw-r--r--sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx231
1 files changed, 231 insertions, 0 deletions
diff --git a/sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx b/sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx
new file mode 100644
index 0000000000..5a1e192ef3
--- /dev/null
+++ b/sc/source/ui/StatisticsDialogs/FourierAnalysisDialog.cxx
@@ -0,0 +1,231 @@
+/* -*- 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 <docsh.hxx>
+#include <reffact.hxx>
+#include <TableFillingAndNavigationTools.hxx>
+#include <FourierAnalysisDialog.hxx>
+#include <scresid.hxx>
+#include <strings.hrc>
+#include <o3tl/safeint.hxx>
+
+ScFourierAnalysisDialog::ScFourierAnalysisDialog(SfxBindings* pSfxBindings,
+ SfxChildWindow* pChildWindow,
+ weld::Window* pParent, ScViewData& rViewData)
+ : ScStatisticsInputOutputDialog(pSfxBindings, pChildWindow, pParent, rViewData,
+ "modules/scalc/ui/fourieranalysisdialog.ui",
+ "FourierAnalysisDialog")
+ , maLabelAddr(ScAddress::INITIALIZE_INVALID)
+ , maActualInputRange(ScAddress::INITIALIZE_INVALID)
+ , mnLen(0)
+ , mfMinMag(0.0)
+ , mbUse3DAddresses(false)
+ , mbGroupedByColumn(true)
+ , mbWithLabels(false)
+ , mbInverse(false)
+ , mbPolar(false)
+ , mxWithLabelsCheckBox(m_xBuilder->weld_check_button("withlabels-check"))
+ , mxInverseCheckBox(m_xBuilder->weld_check_button("inverse-check"))
+ , mxPolarCheckBox(m_xBuilder->weld_check_button("polar-check"))
+ , mxMinMagnitudeField(m_xBuilder->weld_spin_button("minmagnitude-spin"))
+ , mxErrorMessage(m_xBuilder->weld_label("error-message"))
+{
+ m_xDialog->set_title(ScResId(STR_FOURIER_ANALYSIS));
+
+ mxWithLabelsCheckBox->connect_toggled(LINK(this, ScFourierAnalysisDialog, CheckBoxHdl));
+}
+
+ScFourierAnalysisDialog::~ScFourierAnalysisDialog() {}
+
+void ScFourierAnalysisDialog::Close()
+{
+ DoClose(ScFourierAnalysisDialogWrapper::GetChildWindowId());
+}
+
+TranslateId ScFourierAnalysisDialog::GetUndoNameId() { return STR_FOURIER_ANALYSIS_UNDO_NAME; }
+
+ScRange ScFourierAnalysisDialog::ApplyOutput(ScDocShell* pDocShell)
+{
+ getOptions();
+ AddressWalkerWriter aOutput(mOutputAddress, pDocShell, mDocument,
+ formula::FormulaGrammar::mergeToGrammar(
+ formula::FormulaGrammar::GRAM_ENGLISH, mAddressDetails.eConv));
+ FormulaTemplate aTemplate(&mDocument);
+ aTemplate.autoReplaceUses3D(mbUse3DAddresses);
+
+ aOutput.writeBoldString(mbInverse ? ScResId(STR_INVERSE_FOURIER_TRANSFORM)
+ : ScResId(STR_FOURIER_TRANSFORM));
+ aOutput.newLine();
+ OUString aLabel;
+ getDataLabel(aLabel);
+ if (aLabel.startsWith("="))
+ aOutput.writeFormula(aLabel);
+ else
+ aOutput.writeString(aLabel);
+
+ aOutput.newLine();
+ // Components header
+ if (!mbPolar)
+ {
+ aOutput.writeString(ScResId(STR_REAL_PART));
+ aOutput.nextColumn();
+ aOutput.writeString(ScResId(STR_IMAGINARY_PART));
+ }
+ else
+ {
+ aOutput.writeString(ScResId(STR_MAGNITUDE_PART));
+ aOutput.nextColumn();
+ aOutput.writeString(ScResId(STR_PHASE_PART));
+ }
+
+ aOutput.newLine();
+ aTemplate.autoReplaceRange("%INPUTRANGE%", maActualInputRange);
+
+ OUString aFormula;
+ genFormula(aFormula);
+
+ aTemplate.setTemplate(aFormula);
+ aOutput.writeMatrixFormula(aTemplate.getTemplate(), 2, mnLen);
+
+ return ScRange(aOutput.mMinimumAddress, aOutput.mMaximumAddress);
+}
+
+bool ScFourierAnalysisDialog::InputRangesValid()
+{
+ if (!mInputRange.IsValid())
+ {
+ mxErrorMessage->set_label(ScResId(STR_MESSAGE_INVALID_INPUT_RANGE));
+ return false;
+ }
+
+ if (!mOutputAddress.IsValid())
+ {
+ mxErrorMessage->set_label(ScResId(STR_MESSAGE_INVALID_OUTPUT_ADDR));
+ return false;
+ }
+
+ mInputRange.PutInOrder();
+
+ mbGroupedByColumn = mGroupedBy == BY_COLUMN;
+ mbWithLabels = mxWithLabelsCheckBox->get_active();
+
+ mbUse3DAddresses = mInputRange.aStart.Tab() != mOutputAddress.Tab();
+
+ SCSIZE nRows = mInputRange.aEnd.Row() - mInputRange.aStart.Row() + 1;
+ SCSIZE nCols = mInputRange.aEnd.Col() - mInputRange.aStart.Col() + 1;
+
+ SCSIZE nLen = mbGroupedByColumn ? nRows : nCols;
+ SCSIZE nComponents = mbGroupedByColumn ? nCols : nRows;
+
+ if (nComponents > 2)
+ {
+ OUString aMsg = mbGroupedByColumn ? ScResId(STR_MESSAGE_INVALID_NUMCOLS)
+ : ScResId(STR_MESSAGE_INVALID_NUMROWS);
+ mxErrorMessage->set_label(aMsg);
+ return false;
+ }
+
+ if (mbWithLabels && nLen < 2)
+ {
+ mxErrorMessage->set_label(ScResId(STR_MESSAGE_NODATA_IN_RANGE));
+ return false;
+ }
+
+ // Include space for writing the title, label and Real/Imaginary/Magnitude/Phase heading.
+ SCSIZE nLastOutputRow = mOutputAddress.Row() + nLen + 2;
+ if (mbWithLabels)
+ --nLastOutputRow;
+
+ if (nLastOutputRow > o3tl::make_unsigned(mDocument.MaxRow()))
+ {
+ mxErrorMessage->set_label(ScResId(STR_MESSAGE_OUTPUT_TOO_LONG));
+ return false;
+ }
+
+ ScAddress aActualStart(mInputRange.aStart);
+
+ if (mbWithLabels)
+ {
+ if (mbGroupedByColumn)
+ aActualStart.IncRow();
+ else
+ aActualStart.IncCol();
+
+ if (nComponents == 1)
+ maLabelAddr = mInputRange.aStart;
+ else
+ mbWithLabels = false;
+
+ mnLen = nLen - 1;
+ }
+ else
+ {
+ mnLen = nLen;
+ }
+
+ maActualInputRange = ScRange(aActualStart, mInputRange.aEnd);
+ mxErrorMessage->set_label("");
+
+ return true;
+}
+
+void ScFourierAnalysisDialog::getOptions()
+{
+ mbInverse = mxInverseCheckBox->get_active();
+ mbPolar = mxPolarCheckBox->get_active();
+
+ sal_Int32 nDeciBels = static_cast<sal_Int32>(mxMinMagnitudeField->get_value());
+ if (nDeciBels <= -150)
+ mfMinMag = 0.0;
+ else
+ mfMinMag = pow(10.0, static_cast<double>(nDeciBels) / 10.0);
+}
+
+void ScFourierAnalysisDialog::getDataLabel(OUString& rLabel)
+{
+ if (mbWithLabels)
+ {
+ rLabel = "="
+ + maLabelAddr.Format(mbUse3DAddresses ? ScRefFlags::ADDR_ABS_3D
+ : ScRefFlags::ADDR_ABS,
+ &mDocument, mAddressDetails);
+
+ return;
+ }
+
+ OUString aDataSrc(mInputRange.Format(
+ mDocument, mbUse3DAddresses ? ScRefFlags::RANGE_ABS_3D : ScRefFlags::RANGE_ABS,
+ mAddressDetails));
+
+ rLabel = ScResId(STR_INPUT_DATA_RANGE) + " : " + aDataSrc;
+ return;
+}
+
+void ScFourierAnalysisDialog::genFormula(OUString& rFormula)
+{
+ static constexpr OUString aSep(u";"_ustr);
+
+ if (!mbPolar)
+ {
+ rFormula = "FOURIER(%INPUTRANGE%;" + OUString::boolean(mbGroupedByColumn) + aSep
+ + OUString::boolean(mbInverse) + ")";
+ return;
+ }
+
+ rFormula = "FOURIER(%INPUTRANGE%;" + OUString::boolean(mbGroupedByColumn) + aSep
+ + OUString::boolean(mbInverse) + ";true;" + OUString::number(mfMinMag) + ")";
+}
+
+IMPL_LINK_NOARG(ScFourierAnalysisDialog, CheckBoxHdl, weld::Toggleable&, void)
+{
+ ValidateDialogInput();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */