LibreOffice Module sc (master)  1
FourierAnalysisDialog.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  */
10 
11 #include <docsh.hxx>
12 #include <reffact.hxx>
15 #include <scresid.hxx>
16 #include <strings.hrc>
17 #include <o3tl/safeint.hxx>
18 
20  SfxChildWindow* pChildWindow,
21  weld::Window* pParent, ScViewData& rViewData)
22  : ScStatisticsInputOutputDialog(pSfxBindings, pChildWindow, pParent, rViewData,
23  "modules/scalc/ui/fourieranalysisdialog.ui",
24  "FourierAnalysisDialog")
25  , maLabelAddr(ScAddress::INITIALIZE_INVALID)
26  , maActualInputRange(ScAddress::INITIALIZE_INVALID)
27  , mnLen(0)
28  , mfMinMag(0.0)
29  , mbUse3DAddresses(false)
30  , mbGroupedByColumn(true)
31  , mbWithLabels(false)
32  , mbInverse(false)
33  , mbPolar(false)
34  , mxWithLabelsCheckBox(m_xBuilder->weld_check_button("withlabels-check"))
35  , mxInverseCheckBox(m_xBuilder->weld_check_button("inverse-check"))
36  , mxPolarCheckBox(m_xBuilder->weld_check_button("polar-check"))
37  , mxMinMagnitudeField(m_xBuilder->weld_spin_button("minmagnitude-spin"))
38  , mxErrorMessage(m_xBuilder->weld_label("error-message"))
39 {
40  m_xDialog->set_title(ScResId(STR_FOURIER_ANALYSIS));
41 
42  mxWithLabelsCheckBox->connect_toggled(LINK(this, ScFourierAnalysisDialog, CheckBoxHdl));
43 }
44 
46 
48 {
50 }
51 
52 const char* ScFourierAnalysisDialog::GetUndoNameId() { return STR_FOURIER_ANALYSIS; }
53 
55 {
56  getOptions();
57  AddressWalkerWriter aOutput(mOutputAddress, pDocShell, mDocument,
60  FormulaTemplate aTemplate(&mDocument);
62 
63  aOutput.writeBoldString(mbInverse ? ScResId(STR_INVERSE_FOURIER_TRANSFORM)
64  : ScResId(STR_FOURIER_TRANSFORM));
65  aOutput.newLine();
66  OUString aLabel;
67  getDataLabel(aLabel);
68  if (aLabel.startsWith("="))
69  aOutput.writeFormula(aLabel);
70  else
71  aOutput.writeString(aLabel);
72 
73  aOutput.newLine();
74  // Components header
75  if (!mbPolar)
76  {
77  aOutput.writeString(ScResId(STR_REAL_PART));
78  aOutput.nextColumn();
79  aOutput.writeString(ScResId(STR_IMAGINARY_PART));
80  }
81  else
82  {
83  aOutput.writeString(ScResId(STR_MAGNITUDE_PART));
84  aOutput.nextColumn();
85  aOutput.writeString(ScResId(STR_PHASE_PART));
86  }
87 
88  aOutput.newLine();
89  aTemplate.autoReplaceRange("%INPUTRANGE%", maActualInputRange);
90 
91  OUString aFormula;
92  genFormula(aFormula);
93 
94  aTemplate.setTemplate(aFormula);
95  aOutput.writeMatrixFormula(aTemplate.getTemplate(), 2, mnLen);
96 
97  return ScRange(aOutput.mMinimumAddress, aOutput.mMaximumAddress);
98 }
99 
101 {
102  if (!mInputRange.IsValid())
103  {
104  mxErrorMessage->set_label(ScResId(STR_MESSAGE_INVALID_INPUT_RANGE));
105  return false;
106  }
107 
108  if (!mOutputAddress.IsValid())
109  {
110  mxErrorMessage->set_label(ScResId(STR_MESSAGE_INVALID_OUTPUT_ADDR));
111  return false;
112  }
113 
115 
117  mbWithLabels = mxWithLabelsCheckBox->get_active();
118 
120 
121  SCSIZE nRows = mInputRange.aEnd.Row() - mInputRange.aStart.Row() + 1;
122  SCSIZE nCols = mInputRange.aEnd.Col() - mInputRange.aStart.Col() + 1;
123 
124  SCSIZE nLen = mbGroupedByColumn ? nRows : nCols;
125  SCSIZE nComponents = mbGroupedByColumn ? nCols : nRows;
126 
127  if (nComponents > 2)
128  {
129  OUString aMsg = mbGroupedByColumn ? ScResId(STR_MESSAGE_INVALID_NUMCOLS)
130  : ScResId(STR_MESSAGE_INVALID_NUMROWS);
131  mxErrorMessage->set_label(aMsg);
132  return false;
133  }
134 
135  if (mbWithLabels && nLen < 2)
136  {
137  mxErrorMessage->set_label(ScResId(STR_MESSAGE_NODATA_IN_RANGE));
138  return false;
139  }
140 
141  // Include space for writing the title, label and Real/Imaginary/Magnitude/Phase heading.
142  SCSIZE nLastOutputRow = mOutputAddress.Row() + nLen + 2;
143  if (mbWithLabels)
144  --nLastOutputRow;
145 
146  if (nLastOutputRow > o3tl::make_unsigned(mDocument.MaxRow()))
147  {
148  mxErrorMessage->set_label(ScResId(STR_MESSAGE_OUTPUT_TOO_LONG));
149  return false;
150  }
151 
152  ScAddress aActualStart(mInputRange.aStart);
153 
154  if (mbWithLabels)
155  {
156  if (mbGroupedByColumn)
157  aActualStart.IncRow();
158  else
159  aActualStart.IncCol();
160 
161  if (nComponents == 1)
163  else
164  mbWithLabels = false;
165 
166  mnLen = nLen - 1;
167  }
168  else
169  {
170  mnLen = nLen;
171  }
172 
173  maActualInputRange = ScRange(aActualStart, mInputRange.aEnd);
174  mxErrorMessage->set_label("");
175 
176  return true;
177 }
178 
180 {
181  mbInverse = mxInverseCheckBox->get_active();
182  mbPolar = mxPolarCheckBox->get_active();
183 
184  sal_Int32 nDeciBels = static_cast<sal_Int32>(mxMinMagnitudeField->get_value());
185  if (nDeciBels <= -150)
186  mfMinMag = 0.0;
187  else
188  mfMinMag = pow(10.0, static_cast<double>(nDeciBels) / 10.0);
189 }
190 
192 {
193  if (mbWithLabels)
194  {
195  rLabel = "="
199 
200  return;
201  }
202 
203  OUString aDataSrc(mInputRange.Format(
205  mAddressDetails));
206 
207  rLabel = ScResId(STR_INPUT_DATA_RANGE) + " : " + aDataSrc;
208  return;
209 }
210 
211 void ScFourierAnalysisDialog::genFormula(OUString& rFormula)
212 {
213  static constexpr OUStringLiteral aSep(u";");
214 
215  if (!mbPolar)
216  {
217  rFormula = "FOURIER(%INPUTRANGE%;" + OUString::boolean(mbGroupedByColumn) + aSep
218  + OUString::boolean(mbInverse) + ")";
219  return;
220  }
221 
222  rFormula = "FOURIER(%INPUTRANGE%;" + OUString::boolean(mbGroupedByColumn) + aSep
223  + OUString::boolean(mbInverse) + ";true;" + OUString::number(mfMinMag) + ")";
224 }
225 
227 {
228  ValidateDialogInput();
229 }
230 
231 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2116
ScAddress aStart
Definition: address.hxx:500
std::unique_ptr< weld::Label > mxErrorMessage
void writeFormula(const OUString &aFormula)
SCROW Row() const
Definition: address.hxx:262
void writeString(const OUString &aString)
std::unique_ptr< weld::CheckButton > mxInverseCheckBox
void getDataLabel(OUString &rLabel)
ScAddress aEnd
Definition: address.hxx:501
std::unique_ptr< weld::CheckButton > mxPolarCheckBox
std::unique_ptr< weld::CheckButton > mxWithLabelsCheckBox
formula::FormulaGrammar::AddressConvention eConv
Definition: address.hxx:213
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:870
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:45
void writeBoldString(const OUString &aString)
void writeMatrixFormula(const OUString &aFormula, SCCOL nCols=1, SCROW nRows=1)
static Grammar mergeToGrammar(const Grammar eGrammar, const AddressConvention eConv)
SCTAB Tab() const
Definition: address.hxx:271
bool IsValid() const
Definition: address.hxx:293
virtual ScRange ApplyOutput(ScDocShell *pDocShell) override
void genFormula(OUString &rFormula)
void IncCol(SCCOL nDelta=1)
Definition: address.hxx:304
virtual void Close() override
SC_DLLPUBLIC OUString Format(const ScDocument &rDocument, ScRefFlags nFlags=ScRefFlags::ZERO, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, bool bFullAddressNotation=false) const
Returns string with formatted cell range from aStart to aEnd, according to provided address conventio...
Definition: address.cxx:2212
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
void IncRow(SCROW nDelta=1)
Definition: address.hxx:300
float u
OUString ScResId(const char *pId)
Definition: scdll.cxx:89
void autoReplaceRange(const OUString &aVariable, const ScRange &rRange)
bool IsValid() const
Definition: address.hxx:547
SCCOL Col() const
Definition: address.hxx:267
SC_DLLPUBLIC void PutInOrder()
Definition: address.cxx:1582
virtual const char * GetUndoNameId() override
std::unique_ptr< weld::SpinButton > mxMinMagnitudeField
Reference< XExecutableDialog > m_xDialog
OUString aLabel
IMPL_LINK_NOARG(ScFourierAnalysisDialog, CheckBoxHdl, weld::ToggleButton &, void)
ScFourierAnalysisDialog(SfxBindings *pB, SfxChildWindow *pCW, weld::Window *pParent, ScViewData &rViewData)
void setTemplate(const OUString &aTemplate)
bool DoClose(sal_uInt16 nId)
Definition: anyrefdg.cxx:694
virtual ~ScFourierAnalysisDialog() override
virtual bool InputRangesValid() override