Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / StatisticsDialogs / RandomNumberGeneratorDialog.cxx
bloba8792e424debffecac4e30ca3d5529cee8facc91
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
9 */
11 #include <sfx2/dispatch.hxx>
12 #include <svl/zforlist.hxx>
13 #include <svl/undo.hxx>
15 #include "rangelst.hxx"
16 #include "scitems.hxx"
17 #include "docsh.hxx"
18 #include "document.hxx"
19 #include "uiitems.hxx"
20 #include "reffact.hxx"
21 #include "strload.hxx"
22 #include "random.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/binomial_distribution.hpp>
34 #include <boost/random/chi_squared_distribution.hpp>
35 #include <boost/random/geometric_distribution.hpp>
36 #include <boost/random/negative_binomial_distribution.hpp>
38 #include "RandomNumberGeneratorDialog.hxx"
40 namespace
43 static const sal_Int64 DIST_UNIFORM = 0;
44 static const sal_Int64 DIST_NORMAL = 1;
45 static const sal_Int64 DIST_CAUCHY = 2;
46 static const sal_Int64 DIST_BERNOULLI = 3;
47 static const sal_Int64 DIST_BINOMIAL = 4;
48 static const sal_Int64 DIST_CHI_SQUARED = 5;
49 static const sal_Int64 DIST_GEOMETRIC = 6;
50 static const sal_Int64 DIST_NEGATIVE_BINOMIAL = 7;
51 static const sal_Int64 DIST_UNIFORM_INTEGER = 8;
53 static const sal_Int64 PERCISION = 10000;
54 static 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 mViewData ( pViewData ),
63 mDocument ( pViewData->GetDocument() ),
64 mAddressDetails ( mDocument->GetAddressConvention(), 0, 0 ),
65 mDialogLostFocus( false )
67 get(mpInputRangeText, "cell-range-label");
68 get(mpInputRangeEdit, "cell-range-edit");
69 get(mpInputRangeButton, "cell-range-button");
70 mpInputRangeEdit->SetReferences(this, mpInputRangeText);
71 mpInputRangeButton->SetReferences(this, mpInputRangeEdit);
73 get(mpParameter1Value, "parameter1-spin");
74 get(mpParameter1Text, "parameter1-label");
75 get(mpParameter2Value, "parameter2-spin");
76 get(mpParameter2Text, "parameter2-label");
78 get(mpEnableSeed, "enable-seed-check");
79 get(mpSeed, "seed-spin");
81 get(mpDistributionCombo, "distribution-combo");
83 get(mpButtonOk, "ok");
84 get(mpButtonApply, "apply");
85 get(mpButtonClose, "close");
87 Init();
88 GetRangeFromSelection();
91 void ScRandomNumberGeneratorDialog::Init()
93 mpButtonOk->SetClickHdl( LINK( this, ScRandomNumberGeneratorDialog, OkClicked ) );
94 mpButtonClose->SetClickHdl( LINK( this, ScRandomNumberGeneratorDialog, CloseClicked ) );
95 mpButtonApply->SetClickHdl( LINK( this, ScRandomNumberGeneratorDialog, ApplyClicked ) );
97 Link aLink = LINK( this, ScRandomNumberGeneratorDialog, GetFocusHandler );
98 mpInputRangeEdit->SetGetFocusHdl( aLink );
99 mpInputRangeButton->SetGetFocusHdl( aLink );
101 aLink = LINK( this, ScRandomNumberGeneratorDialog, LoseFocusHandler );
102 mpInputRangeEdit->SetLoseFocusHdl ( aLink );
103 mpInputRangeButton->SetLoseFocusHdl ( aLink );
105 mpParameter1Value->SetModifyHdl( LINK( this, ScRandomNumberGeneratorDialog, Parameter1ValueModified ));
106 mpParameter2Value->SetModifyHdl( LINK( this, ScRandomNumberGeneratorDialog, Parameter2ValueModified ));
108 mpDistributionCombo->SetSelectHdl( LINK( this, ScRandomNumberGeneratorDialog, DistributionChanged ));
110 mpEnableSeed->SetToggleHdl( LINK( this, ScRandomNumberGeneratorDialog, SeedCheckChanged ));
112 DistributionChanged(NULL);
113 SeedCheckChanged(NULL);
116 void ScRandomNumberGeneratorDialog::GetRangeFromSelection()
118 mViewData->GetSimpleArea(mInputRange);
119 OUString aCurrentString(mInputRange.Format(SCR_ABS_3D, mDocument, mAddressDetails));
120 mpInputRangeEdit->SetText( aCurrentString );
123 ScRandomNumberGeneratorDialog::~ScRandomNumberGeneratorDialog()
126 void ScRandomNumberGeneratorDialog::SetActive()
128 if ( mDialogLostFocus )
130 mDialogLostFocus = false;
131 if( mpInputRangeEdit )
132 mpInputRangeEdit->GrabFocus();
134 else
136 GrabFocus();
138 RefInputDone();
141 sal_Bool ScRandomNumberGeneratorDialog::Close()
143 return DoClose( ScRandomNumberGeneratorDialogWrapper::GetChildWindowId() );
146 void ScRandomNumberGeneratorDialog::SetReference( const ScRange& rReferenceRange, ScDocument* pDocument )
148 if ( mpInputRangeEdit->IsEnabled() )
150 if ( rReferenceRange.aStart != rReferenceRange.aEnd )
151 RefInputStart( mpInputRangeEdit );
153 mInputRange = rReferenceRange;
155 OUString aReferenceString(mInputRange.Format(SCR_ABS_3D, pDocument, mAddressDetails));
156 mpInputRangeEdit->SetRefString( aReferenceString );
160 void ScRandomNumberGeneratorDialog::SelectGeneratorAndGenerateNumbers()
162 sal_Int16 aSelectedIndex = mpDistributionCombo-> GetSelectEntryPos();
163 sal_Int64 aSelectedId = (sal_Int64) mpDistributionCombo->GetEntryData(aSelectedIndex);
165 sal_uInt32 seedValue;
167 if( mpEnableSeed->IsChecked() )
169 seedValue = mpSeed->GetValue();
171 else
173 TimeValue now;
174 osl_getSystemTime(&now);
175 seedValue = now.Nanosec;
178 boost::mt19937 seed(seedValue);
180 sal_Int64 parameterInteger1 = mpParameter1Value->GetValue();
181 sal_Int64 parameterInteger2 = mpParameter2Value->GetValue();
183 double parameter1 = parameterInteger1 / static_cast<double>(PERCISION);
184 double parameter2 = parameterInteger2 / static_cast<double>(PERCISION);
186 switch(aSelectedId)
188 case DIST_UNIFORM:
190 boost::random::uniform_real_distribution<> distribution(parameter1, parameter2);
191 boost::variate_generator<boost::mt19937&, boost::random::uniform_real_distribution<> > rng(seed, distribution);
192 GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_UNIFORM_REAL));
193 break;
195 case DIST_UNIFORM_INTEGER:
197 boost::random::uniform_int_distribution<> distribution(parameterInteger1, parameterInteger2);
198 boost::variate_generator<boost::mt19937&, boost::random::uniform_int_distribution<> > rng(seed, distribution);
199 GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_UNIFORM_INTEGER));
200 break;
202 case DIST_NORMAL:
204 boost::random::normal_distribution<> distribution(parameter1, parameter2);
205 boost::variate_generator<boost::mt19937&, boost::random::normal_distribution<> > rng(seed, distribution);
206 GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_NORMAL));
207 break;
209 case DIST_CAUCHY:
211 boost::random::cauchy_distribution<> distribution(parameter1);
212 boost::variate_generator<boost::mt19937&, boost::random::cauchy_distribution<> > rng(seed, distribution);
213 GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_CAUCHY));
214 break;
216 case DIST_BERNOULLI:
218 boost::random::bernoulli_distribution<> distribution(parameter1);
219 boost::variate_generator<boost::mt19937&, boost::random::bernoulli_distribution<> > rng(seed, distribution);
220 GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_BERNOULLI));
221 break;
223 case DIST_BINOMIAL:
225 boost::random::binomial_distribution<> distribution(parameterInteger2, parameter1);
226 boost::variate_generator<boost::mt19937&, boost::random::binomial_distribution<> > rng(seed, distribution);
227 GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_BINOMIAL));
228 break;
230 case DIST_NEGATIVE_BINOMIAL:
232 boost::random::negative_binomial_distribution<> distribution(parameterInteger2, parameter1);
233 boost::variate_generator<boost::mt19937&, boost::random::negative_binomial_distribution<> > rng(seed, distribution);
234 GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_NEGATIVE_BINOMIAL));
235 break;
237 case DIST_CHI_SQUARED:
239 boost::random::chi_squared_distribution<> distribution(parameter1);
240 boost::variate_generator<boost::mt19937&, boost::random::chi_squared_distribution<> > rng(seed, distribution);
241 GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_CHI_SQUARED));
242 break;
244 case DIST_GEOMETRIC:
246 boost::random::geometric_distribution<> distribution(parameter1);
247 boost::variate_generator<boost::mt19937&, boost::random::geometric_distribution<> > rng(seed, distribution);
248 GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_GEOMETRIC));
249 break;
254 template<class RNG>
255 void ScRandomNumberGeneratorDialog::GenerateNumbers(RNG randomGenerator, OUString aDistributionName)
257 OUString aUndo = SC_STRLOAD( RID_STATISTICS_DLGS, STR_UNDO_DISTRIBUTION_TEMPLATE);
258 aUndo = aUndo.replaceAll("$(DISTRIBUTION)", aDistributionName);
260 ScDocShell* pDocShell = mViewData->GetDocShell();
261 svl::IUndoManager* pUndoManager = pDocShell->GetUndoManager();
262 pUndoManager->EnterListAction( aUndo, aUndo );
264 SCROW nRowStart = mInputRange.aStart.Row();
265 SCROW nRowEnd = mInputRange.aEnd.Row();
266 SCCOL nColStart = mInputRange.aStart.Col();
267 SCCOL nColEnd = mInputRange.aEnd.Col();
268 SCTAB nTabStart = mInputRange.aStart.Tab();
269 SCTAB nTabEnd = mInputRange.aEnd.Tab();
271 for (SCROW nTab = nTabStart; nTab <= nTabEnd; nTab++)
273 for (SCROW nRow = nRowStart; nRow <= nRowEnd; nRow++)
275 for (SCCOL nCol = nColStart; nCol <= nColEnd; nCol++)
277 pDocShell->GetDocFunc().SetValueCell(ScAddress(nCol, nRow, nTab), randomGenerator(), true);
282 pUndoManager->LeaveListAction();
284 pDocShell->PostPaint( mInputRange, PAINT_GRID );
287 IMPL_LINK( ScRandomNumberGeneratorDialog, OkClicked, PushButton*, /*pButton*/ )
289 ApplyClicked(NULL);
290 CloseClicked(NULL);
291 return 0;
295 IMPL_LINK( ScRandomNumberGeneratorDialog, ApplyClicked, PushButton*, /*pButton*/ )
297 SelectGeneratorAndGenerateNumbers();
298 return 0;
301 IMPL_LINK( ScRandomNumberGeneratorDialog, CloseClicked, PushButton*, /*pButton*/ )
303 Close();
304 return 0;
307 IMPL_LINK( ScRandomNumberGeneratorDialog, GetFocusHandler, Control*, pCtrl )
309 Edit* pEdit = NULL;
311 if( (pCtrl == (Control*) mpInputRangeEdit) || (pCtrl == (Control*) mpInputRangeButton) )
312 pEdit = mpInputRangeEdit;
314 if( pEdit )
315 pEdit->SetSelection( Selection( 0, SELECTION_MAX ) );
317 return 0;
320 IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog, LoseFocusHandler)
322 mDialogLostFocus = !IsActive();
323 return 0;
326 IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog, Parameter1ValueModified)
328 sal_Int16 aSelectedIndex = mpDistributionCombo-> GetSelectEntryPos();
329 sal_Int64 aSelectedId = (sal_Int64) mpDistributionCombo->GetEntryData(aSelectedIndex);
330 if (aSelectedId == DIST_UNIFORM ||
331 aSelectedId == DIST_UNIFORM_INTEGER)
333 sal_Int64 min = mpParameter1Value->GetValue();
334 sal_Int64 max = mpParameter2Value->GetValue();
335 if(min > max)
337 mpParameter2Value->SetValue(min);
340 return 0;
343 IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog, Parameter2ValueModified)
345 sal_Int16 aSelectedIndex = mpDistributionCombo-> GetSelectEntryPos();
346 sal_Int64 aSelectedId = (sal_Int64) mpDistributionCombo->GetEntryData(aSelectedIndex);
347 if (aSelectedId == DIST_UNIFORM ||
348 aSelectedId == DIST_UNIFORM_INTEGER)
350 sal_Int64 min = mpParameter1Value->GetValue();
351 sal_Int64 max = mpParameter2Value->GetValue();
352 if(min > max)
354 mpParameter1Value->SetValue(max);
357 return 0;
360 IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog, SeedCheckChanged)
362 mpSeed->Enable(mpEnableSeed->IsChecked());
363 return 0;
366 IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog, DistributionChanged)
368 sal_Int16 aSelectedIndex = mpDistributionCombo-> GetSelectEntryPos();
369 sal_Int64 aSelectedId = (sal_Int64) mpDistributionCombo->GetEntryData(aSelectedIndex);
371 mpParameter1Value->SetMin( SAL_MIN_INT64 );
372 mpParameter1Value->SetMax( SAL_MAX_INT64 );
373 mpParameter2Value->SetMin( SAL_MIN_INT64 );
374 mpParameter2Value->SetMax( SAL_MAX_INT64 );
376 mpParameter1Value->SetDecimalDigits(DIGITS);
377 mpParameter1Value->SetSpinSize(PERCISION);
379 mpParameter2Value->SetDecimalDigits(DIGITS);
380 mpParameter2Value->SetSpinSize(PERCISION);
382 switch(aSelectedId)
384 case DIST_UNIFORM:
386 mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_MINIMUM));
387 mpParameter2Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_MAXIMUM));
388 mpParameter2Text->Show();
389 mpParameter2Value->Show();
390 break;
392 case DIST_UNIFORM_INTEGER:
394 mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_MINIMUM));
395 mpParameter1Value->SetDecimalDigits(0);
396 mpParameter1Value->SetSpinSize(1);
398 mpParameter2Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_MAXIMUM));
399 mpParameter2Value->SetDecimalDigits(0);
400 mpParameter2Value->SetSpinSize(1);
402 mpParameter2Text->Show();
403 mpParameter2Value->Show();
404 break;
406 case DIST_NORMAL:
408 mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_MEAN));
409 mpParameter2Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_DEVIATION));
410 mpParameter2Text->Show();
411 mpParameter2Value->Show();
412 break;
414 case DIST_CAUCHY:
416 mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_MEDIAN));
417 mpParameter2Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_SIGMA));
418 mpParameter2Text->Show();
419 mpParameter2Value->Show();
420 break;
422 case DIST_BERNOULLI:
423 case DIST_GEOMETRIC:
425 mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_PROBABILITY));
426 mpParameter1Value->SetMin( 0 );
427 mpParameter1Value->SetMax( PERCISION );
428 mpParameter1Value->SetSpinSize(1000);
430 mpParameter2Text->Hide();
431 mpParameter2Value->Hide();
432 break;
434 case DIST_BINOMIAL:
435 case DIST_NEGATIVE_BINOMIAL:
437 mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_PROBABILITY));
438 mpParameter1Value->SetMin( 0 );
439 mpParameter1Value->SetMax( PERCISION );
440 mpParameter1Value->SetSpinSize(1000);
442 mpParameter2Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_NUMBER_OF_TRIALS));
443 mpParameter2Value->SetDecimalDigits(0);
444 mpParameter2Value->SetSpinSize(1);
445 mpParameter2Value->SetMin(0);
447 mpParameter2Text->Show();
448 mpParameter2Value->Show();
449 break;
451 case DIST_CHI_SQUARED:
453 mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_NU_VALUE));
455 mpParameter2Text->Hide();
456 mpParameter2Value->Hide();
457 break;
460 return 0;
463 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */