231 lines
7.1 KiB
C++
231 lines
7.1 KiB
C++
/* -*- 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,
|
|
u"modules/scalc/ui/fourieranalysisdialog.ui"_ustr,
|
|
u"FourierAnalysisDialog"_ustr)
|
|
, 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(u"withlabels-check"_ustr))
|
|
, mxInverseCheckBox(m_xBuilder->weld_check_button(u"inverse-check"_ustr))
|
|
, mxPolarCheckBox(m_xBuilder->weld_check_button(u"polar-check"_ustr))
|
|
, mxMinMagnitudeField(m_xBuilder->weld_spin_button(u"minmagnitude-spin"_ustr))
|
|
, mxErrorMessage(m_xBuilder->weld_label(u"error-message"_ustr))
|
|
{
|
|
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(u"%INPUTRANGE%"_ustr, 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(u""_ustr);
|
|
|
|
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: */
|