1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
11 #include <sfx2/dispatch.hxx>
12 #include <svl/zforlist.hxx>
13 #include <svl/undo.hxx>
14 #include <rtl/math.hxx>
16 #include "rangelst.hxx"
17 #include "scitems.hxx"
19 #include "document.hxx"
20 #include "uiitems.hxx"
21 #include "reffact.hxx"
22 #include "strload.hxx"
23 #include "docfunc.hxx"
24 #include "StatisticsDialogs.hrc"
26 #include <boost/random.hpp>
27 #include <boost/random/uniform_real_distribution.hpp>
28 #include <boost/random/uniform_int_distribution.hpp>
29 #include <boost/random/binomial_distribution.hpp>
30 #include <boost/random/normal_distribution.hpp>
31 #include <boost/random/cauchy_distribution.hpp>
32 #include <boost/random/bernoulli_distribution.hpp>
33 #include <boost/random/chi_squared_distribution.hpp>
34 #include <boost/random/geometric_distribution.hpp>
35 #include <boost/random/negative_binomial_distribution.hpp>
37 #include "RandomNumberGeneratorDialog.hxx"
42 const sal_Int64 DIST_UNIFORM
= 0;
43 const sal_Int64 DIST_NORMAL
= 1;
44 const sal_Int64 DIST_CAUCHY
= 2;
45 const sal_Int64 DIST_BERNOULLI
= 3;
46 const sal_Int64 DIST_BINOMIAL
= 4;
47 const sal_Int64 DIST_CHI_SQUARED
= 5;
48 const sal_Int64 DIST_GEOMETRIC
= 6;
49 const sal_Int64 DIST_NEGATIVE_BINOMIAL
= 7;
50 const sal_Int64 DIST_UNIFORM_INTEGER
= 8;
52 const sal_Int64 PERCISION
= 10000;
53 const sal_Int64 DIGITS
= 4;
57 ScRandomNumberGeneratorDialog::ScRandomNumberGeneratorDialog(
58 SfxBindings
* pSfxBindings
, SfxChildWindow
* pChildWindow
,
59 Window
* pParent
, ScViewData
* pViewData
) :
60 ScAnyRefDlg ( pSfxBindings
, pChildWindow
, pParent
,
61 "RandomNumberGeneratorDialog", "modules/scalc/ui/randomnumbergenerator.ui" ),
62 mpViewData ( pViewData
),
63 mpDoc( pViewData
->GetDocument() ),
64 mbDialogLostFocus( false )
66 get(mpInputRangeText
, "cell-range-label");
67 get(mpInputRangeEdit
, "cell-range-edit");
68 get(mpInputRangeButton
, "cell-range-button");
69 mpInputRangeEdit
->SetReferences(this, mpInputRangeText
);
70 mpInputRangeButton
->SetReferences(this, mpInputRangeEdit
);
72 get(mpParameter1Value
, "parameter1-spin");
73 get(mpParameter1Text
, "parameter1-label");
74 get(mpParameter2Value
, "parameter2-spin");
75 get(mpParameter2Text
, "parameter2-label");
77 get(mpEnableSeed
, "enable-seed-check");
78 get(mpSeed
, "seed-spin");
80 get(mpEnableRounding
, "enable-rounding-check");
81 get(mpDecimalPlaces
, "decimal-places-spin");
83 get(mpDistributionCombo
, "distribution-combo");
85 get(mpButtonOk
, "ok");
86 get(mpButtonApply
, "apply");
87 get(mpButtonClose
, "close");
90 GetRangeFromSelection();
93 void ScRandomNumberGeneratorDialog::Init()
95 mpButtonOk
->SetClickHdl( LINK( this, ScRandomNumberGeneratorDialog
, OkClicked
) );
96 mpButtonClose
->SetClickHdl( LINK( this, ScRandomNumberGeneratorDialog
, CloseClicked
) );
97 mpButtonApply
->SetClickHdl( LINK( this, ScRandomNumberGeneratorDialog
, ApplyClicked
) );
99 Link aLink
= LINK( this, ScRandomNumberGeneratorDialog
, GetFocusHandler
);
100 mpInputRangeEdit
->SetGetFocusHdl( aLink
);
101 mpInputRangeButton
->SetGetFocusHdl( aLink
);
103 aLink
= LINK( this, ScRandomNumberGeneratorDialog
, LoseFocusHandler
);
104 mpInputRangeEdit
->SetLoseFocusHdl ( aLink
);
105 mpInputRangeButton
->SetLoseFocusHdl ( aLink
);
107 mpParameter1Value
->SetModifyHdl( LINK( this, ScRandomNumberGeneratorDialog
, Parameter1ValueModified
));
108 mpParameter2Value
->SetModifyHdl( LINK( this, ScRandomNumberGeneratorDialog
, Parameter2ValueModified
));
110 mpDistributionCombo
->SetSelectHdl( LINK( this, ScRandomNumberGeneratorDialog
, DistributionChanged
));
112 mpEnableSeed
->SetToggleHdl( LINK( this, ScRandomNumberGeneratorDialog
, CheckChanged
));
113 mpEnableRounding
->SetToggleHdl( LINK( this, ScRandomNumberGeneratorDialog
, CheckChanged
));
115 DistributionChanged(NULL
);
119 void ScRandomNumberGeneratorDialog::GetRangeFromSelection()
121 mpViewData
->GetSimpleArea(maInputRange
);
122 OUString
aCurrentString(maInputRange
.Format(SCR_ABS_3D
, mpDoc
, mpDoc
->GetAddressConvention()));
123 mpInputRangeEdit
->SetText( aCurrentString
);
126 ScRandomNumberGeneratorDialog::~ScRandomNumberGeneratorDialog()
129 void ScRandomNumberGeneratorDialog::SetActive()
131 if ( mbDialogLostFocus
)
133 mbDialogLostFocus
= false;
134 if( mpInputRangeEdit
)
135 mpInputRangeEdit
->GrabFocus();
144 bool ScRandomNumberGeneratorDialog::Close()
146 return DoClose( ScRandomNumberGeneratorDialogWrapper::GetChildWindowId() );
149 void ScRandomNumberGeneratorDialog::SetReference( const ScRange
& rReferenceRange
, ScDocument
* pDoc
)
151 if ( mpInputRangeEdit
->IsEnabled() )
153 if ( rReferenceRange
.aStart
!= rReferenceRange
.aEnd
)
154 RefInputStart( mpInputRangeEdit
);
156 maInputRange
= rReferenceRange
;
158 OUString
aReferenceString(maInputRange
.Format(SCR_ABS_3D
, pDoc
, pDoc
->GetAddressConvention()));
159 mpInputRangeEdit
->SetRefString( aReferenceString
);
163 void ScRandomNumberGeneratorDialog::SelectGeneratorAndGenerateNumbers()
165 sal_Int16 aSelectedIndex
= mpDistributionCombo
-> GetSelectEntryPos();
166 sal_Int64 aSelectedId
= (sal_Int64
) mpDistributionCombo
->GetEntryData(aSelectedIndex
);
168 sal_uInt32 seedValue
;
170 if( mpEnableSeed
->IsChecked() )
172 seedValue
= mpSeed
->GetValue();
177 osl_getSystemTime(&now
);
178 seedValue
= now
.Nanosec
;
181 boost::mt19937
seed(seedValue
);
183 sal_Int64 parameterInteger1
= mpParameter1Value
->GetValue();
184 sal_Int64 parameterInteger2
= mpParameter2Value
->GetValue();
186 double parameter1
= parameterInteger1
/ static_cast<double>(PERCISION
);
187 double parameter2
= parameterInteger2
/ static_cast<double>(PERCISION
);
189 boost::optional
<sal_Int8
> aDecimalPlaces
;
190 if (mpEnableRounding
->IsChecked())
192 aDecimalPlaces
= static_cast<sal_Int8
>(mpDecimalPlaces
->GetValue());
199 boost::random::uniform_real_distribution
<> distribution(parameter1
, parameter2
);
200 boost::variate_generator
<boost::mt19937
&, boost::random::uniform_real_distribution
<> > rng(seed
, distribution
);
201 GenerateNumbers(rng
, STR_DISTRIBUTION_UNIFORM_REAL
, aDecimalPlaces
);
204 case DIST_UNIFORM_INTEGER
:
206 boost::random::uniform_int_distribution
<> distribution(parameterInteger1
, parameterInteger2
);
207 boost::variate_generator
<boost::mt19937
&, boost::random::uniform_int_distribution
<> > rng(seed
, distribution
);
208 GenerateNumbers(rng
, STR_DISTRIBUTION_UNIFORM_INTEGER
, aDecimalPlaces
);
213 boost::random::normal_distribution
<> distribution(parameter1
, parameter2
);
214 boost::variate_generator
<boost::mt19937
&, boost::random::normal_distribution
<> > rng(seed
, distribution
);
215 GenerateNumbers(rng
, STR_DISTRIBUTION_NORMAL
, aDecimalPlaces
);
220 boost::random::cauchy_distribution
<> distribution(parameter1
);
221 boost::variate_generator
<boost::mt19937
&, boost::random::cauchy_distribution
<> > rng(seed
, distribution
);
222 GenerateNumbers(rng
, STR_DISTRIBUTION_CAUCHY
, aDecimalPlaces
);
227 boost::random::bernoulli_distribution
<> distribution(parameter1
);
228 boost::variate_generator
<boost::mt19937
&, boost::random::bernoulli_distribution
<> > rng(seed
, distribution
);
229 GenerateNumbers(rng
, STR_DISTRIBUTION_BERNOULLI
, aDecimalPlaces
);
234 boost::random::binomial_distribution
<> distribution(parameterInteger2
, parameter1
);
235 boost::variate_generator
<boost::mt19937
&, boost::random::binomial_distribution
<> > rng(seed
, distribution
);
236 GenerateNumbers(rng
, STR_DISTRIBUTION_BINOMIAL
, aDecimalPlaces
);
239 case DIST_NEGATIVE_BINOMIAL
:
241 boost::random::negative_binomial_distribution
<> distribution(parameterInteger2
, parameter1
);
242 boost::variate_generator
<boost::mt19937
&, boost::random::negative_binomial_distribution
<> > rng(seed
, distribution
);
243 GenerateNumbers(rng
, STR_DISTRIBUTION_NEGATIVE_BINOMIAL
, aDecimalPlaces
);
246 case DIST_CHI_SQUARED
:
248 boost::random::chi_squared_distribution
<> distribution(parameter1
);
249 boost::variate_generator
<boost::mt19937
&, boost::random::chi_squared_distribution
<> > rng(seed
, distribution
);
250 GenerateNumbers(rng
, STR_DISTRIBUTION_CHI_SQUARED
, aDecimalPlaces
);
255 boost::random::geometric_distribution
<> distribution(parameter1
);
256 boost::variate_generator
<boost::mt19937
&, boost::random::geometric_distribution
<> > rng(seed
, distribution
);
257 GenerateNumbers(rng
, STR_DISTRIBUTION_GEOMETRIC
, aDecimalPlaces
);
264 void ScRandomNumberGeneratorDialog::GenerateNumbers(RNG randomGenerator
, const sal_Int16 aDistributionStringId
, boost::optional
<sal_Int8
> aDecimalPlaces
)
266 OUString aUndo
= SC_STRLOAD(RID_STATISTICS_DLGS
, STR_UNDO_DISTRIBUTION_TEMPLATE
);
267 OUString aDistributionName
= SC_STRLOAD(RID_STATISTICS_DLGS
, aDistributionStringId
);
268 aUndo
= aUndo
.replaceAll("$(DISTRIBUTION)", aDistributionName
);
270 ScDocShell
* pDocShell
= mpViewData
->GetDocShell();
271 svl::IUndoManager
* pUndoManager
= pDocShell
->GetUndoManager();
272 pUndoManager
->EnterListAction( aUndo
, aUndo
);
274 SCROW nRowStart
= maInputRange
.aStart
.Row();
275 SCROW nRowEnd
= maInputRange
.aEnd
.Row();
276 SCCOL nColStart
= maInputRange
.aStart
.Col();
277 SCCOL nColEnd
= maInputRange
.aEnd
.Col();
278 SCTAB nTabStart
= maInputRange
.aStart
.Tab();
279 SCTAB nTabEnd
= maInputRange
.aEnd
.Tab();
281 std::vector
<double> aVals
;
282 aVals
.reserve(nRowEnd
- nRowStart
+ 1);
284 for (SCROW nTab
= nTabStart
; nTab
<= nTabEnd
; ++nTab
)
286 for (SCCOL nCol
= nColStart
; nCol
<= nColEnd
; ++nCol
)
290 ScAddress
aPos(nCol
, nRowStart
, nTab
);
291 for (SCROW nRow
= nRowStart
; nRow
<= nRowEnd
; ++nRow
)
295 aVals
.push_back(rtl::math::round(randomGenerator(), *aDecimalPlaces
));
297 aVals
.push_back(randomGenerator());
300 pDocShell
->GetDocFunc().SetValueCells(aPos
, aVals
, true);
304 pUndoManager
->LeaveListAction();
306 pDocShell
->PostPaint( maInputRange
, PAINT_GRID
);
309 IMPL_LINK( ScRandomNumberGeneratorDialog
, OkClicked
, PushButton
*, /*pButton*/ )
317 IMPL_LINK( ScRandomNumberGeneratorDialog
, ApplyClicked
, PushButton
*, /*pButton*/ )
319 SelectGeneratorAndGenerateNumbers();
323 IMPL_LINK( ScRandomNumberGeneratorDialog
, CloseClicked
, PushButton
*, /*pButton*/ )
329 IMPL_LINK( ScRandomNumberGeneratorDialog
, GetFocusHandler
, Control
*, pCtrl
)
333 if( (pCtrl
== (Control
*) mpInputRangeEdit
) || (pCtrl
== (Control
*) mpInputRangeButton
) )
334 pEdit
= mpInputRangeEdit
;
337 pEdit
->SetSelection( Selection( 0, SELECTION_MAX
) );
342 IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog
, LoseFocusHandler
)
344 mbDialogLostFocus
= !IsActive();
348 IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog
, Parameter1ValueModified
)
350 sal_Int16 aSelectedIndex
= mpDistributionCombo
-> GetSelectEntryPos();
351 sal_Int64 aSelectedId
= (sal_Int64
) mpDistributionCombo
->GetEntryData(aSelectedIndex
);
352 if (aSelectedId
== DIST_UNIFORM
||
353 aSelectedId
== DIST_UNIFORM_INTEGER
)
355 sal_Int64 min
= mpParameter1Value
->GetValue();
356 sal_Int64 max
= mpParameter2Value
->GetValue();
359 mpParameter2Value
->SetValue(min
);
365 IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog
, Parameter2ValueModified
)
367 sal_Int16 aSelectedIndex
= mpDistributionCombo
-> GetSelectEntryPos();
368 sal_Int64 aSelectedId
= (sal_Int64
) mpDistributionCombo
->GetEntryData(aSelectedIndex
);
369 if (aSelectedId
== DIST_UNIFORM
||
370 aSelectedId
== DIST_UNIFORM_INTEGER
)
372 sal_Int64 min
= mpParameter1Value
->GetValue();
373 sal_Int64 max
= mpParameter2Value
->GetValue();
376 mpParameter1Value
->SetValue(max
);
382 IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog
, CheckChanged
)
384 mpSeed
->Enable(mpEnableSeed
->IsChecked());
385 mpDecimalPlaces
->Enable(mpEnableRounding
->IsChecked());
389 IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog
, DistributionChanged
)
391 sal_Int16 aSelectedIndex
= mpDistributionCombo
-> GetSelectEntryPos();
392 sal_Int64 aSelectedId
= (sal_Int64
) mpDistributionCombo
->GetEntryData(aSelectedIndex
);
394 mpParameter1Value
->SetMin(SAL_MIN_INT64
);
395 mpParameter1Value
->SetMax(SAL_MAX_INT64
);
396 mpParameter2Value
->SetMin(SAL_MIN_INT64
);
397 mpParameter2Value
->SetMax(SAL_MAX_INT64
);
399 mpParameter1Value
->SetDecimalDigits(DIGITS
);
400 mpParameter1Value
->SetSpinSize(PERCISION
);
402 mpParameter2Value
->SetDecimalDigits(DIGITS
);
403 mpParameter2Value
->SetSpinSize(PERCISION
);
409 mpParameter1Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_MINIMUM
));
410 mpParameter2Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_MAXIMUM
));
411 mpParameter2Text
->Show();
412 mpParameter2Value
->Show();
415 case DIST_UNIFORM_INTEGER
:
417 mpParameter1Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_MINIMUM
));
418 mpParameter1Value
->SetDecimalDigits(0);
419 mpParameter1Value
->SetSpinSize(1);
421 mpParameter2Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_MAXIMUM
));
422 mpParameter2Value
->SetDecimalDigits(0);
423 mpParameter2Value
->SetSpinSize(1);
425 mpParameter2Text
->Show();
426 mpParameter2Value
->Show();
431 mpParameter1Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_MEAN
));
432 mpParameter2Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_STANDARD_DEVIATION
));
433 mpParameter2Text
->Show();
434 mpParameter2Value
->Show();
439 mpParameter1Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_STANDARD_MEDIAN
));
440 mpParameter2Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_STANDARD_SIGMA
));
441 mpParameter2Text
->Show();
442 mpParameter2Value
->Show();
448 mpParameter1Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_STANDARD_PROBABILITY
));
449 mpParameter1Value
->SetMin( 0 );
450 mpParameter1Value
->SetMax( PERCISION
);
451 mpParameter1Value
->SetSpinSize(1000);
453 mpParameter2Text
->Hide();
454 mpParameter2Value
->Hide();
458 case DIST_NEGATIVE_BINOMIAL
:
460 mpParameter1Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_STANDARD_PROBABILITY
));
461 mpParameter1Value
->SetMin( 0 );
462 mpParameter1Value
->SetMax( PERCISION
);
463 mpParameter1Value
->SetSpinSize(1000);
465 mpParameter2Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_STANDARD_NUMBER_OF_TRIALS
));
466 mpParameter2Value
->SetDecimalDigits(0);
467 mpParameter2Value
->SetSpinSize(1);
468 mpParameter2Value
->SetMin(0);
470 mpParameter2Text
->Show();
471 mpParameter2Value
->Show();
474 case DIST_CHI_SQUARED
:
476 mpParameter1Text
->SetText( SC_STRLOAD( RID_STATISTICS_DLGS
, STR_RNG_PARAMETER_STANDARD_NU_VALUE
));
478 mpParameter2Text
->Hide();
479 mpParameter2Value
->Hide();
486 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */