Line data Source code
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 <sfx2/dispatch.hxx>
12 : #include <svl/zforlist.hxx>
13 : #include <svl/undo.hxx>
14 :
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"
25 :
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>
36 :
37 : #include "RandomNumberGeneratorDialog.hxx"
38 :
39 : namespace {
40 :
41 : const sal_Int64 DIST_UNIFORM = 0;
42 : const sal_Int64 DIST_NORMAL = 1;
43 : const sal_Int64 DIST_CAUCHY = 2;
44 : const sal_Int64 DIST_BERNOULLI = 3;
45 : const sal_Int64 DIST_BINOMIAL = 4;
46 : const sal_Int64 DIST_CHI_SQUARED = 5;
47 : const sal_Int64 DIST_GEOMETRIC = 6;
48 : const sal_Int64 DIST_NEGATIVE_BINOMIAL = 7;
49 : const sal_Int64 DIST_UNIFORM_INTEGER = 8;
50 :
51 : const sal_Int64 PERCISION = 10000;
52 : const sal_Int64 DIGITS = 4;
53 :
54 : }
55 :
56 0 : ScRandomNumberGeneratorDialog::ScRandomNumberGeneratorDialog(
57 : SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
58 : Window* pParent, ScViewData* pViewData ) :
59 : ScAnyRefDlg ( pSfxBindings, pChildWindow, pParent,
60 : "RandomNumberGeneratorDialog", "modules/scalc/ui/randomnumbergenerator.ui" ),
61 : mpViewData ( pViewData ),
62 0 : mpDoc( pViewData->GetDocument() ),
63 0 : mbDialogLostFocus( false )
64 : {
65 0 : get(mpInputRangeText, "cell-range-label");
66 0 : get(mpInputRangeEdit, "cell-range-edit");
67 0 : get(mpInputRangeButton, "cell-range-button");
68 0 : mpInputRangeEdit->SetReferences(this, mpInputRangeText);
69 0 : mpInputRangeButton->SetReferences(this, mpInputRangeEdit);
70 :
71 0 : get(mpParameter1Value, "parameter1-spin");
72 0 : get(mpParameter1Text, "parameter1-label");
73 0 : get(mpParameter2Value, "parameter2-spin");
74 0 : get(mpParameter2Text, "parameter2-label");
75 :
76 0 : get(mpEnableSeed, "enable-seed-check");
77 0 : get(mpSeed, "seed-spin");
78 :
79 0 : get(mpDistributionCombo, "distribution-combo");
80 :
81 0 : get(mpButtonOk, "ok");
82 0 : get(mpButtonApply, "apply");
83 0 : get(mpButtonClose, "close");
84 :
85 0 : Init();
86 0 : GetRangeFromSelection();
87 0 : }
88 :
89 0 : void ScRandomNumberGeneratorDialog::Init()
90 : {
91 0 : mpButtonOk->SetClickHdl( LINK( this, ScRandomNumberGeneratorDialog, OkClicked ) );
92 0 : mpButtonClose->SetClickHdl( LINK( this, ScRandomNumberGeneratorDialog, CloseClicked ) );
93 0 : mpButtonApply->SetClickHdl( LINK( this, ScRandomNumberGeneratorDialog, ApplyClicked ) );
94 :
95 0 : Link aLink = LINK( this, ScRandomNumberGeneratorDialog, GetFocusHandler );
96 0 : mpInputRangeEdit->SetGetFocusHdl( aLink );
97 0 : mpInputRangeButton->SetGetFocusHdl( aLink );
98 :
99 0 : aLink = LINK( this, ScRandomNumberGeneratorDialog, LoseFocusHandler );
100 0 : mpInputRangeEdit->SetLoseFocusHdl ( aLink );
101 0 : mpInputRangeButton->SetLoseFocusHdl ( aLink );
102 :
103 0 : mpParameter1Value->SetModifyHdl( LINK( this, ScRandomNumberGeneratorDialog, Parameter1ValueModified ));
104 0 : mpParameter2Value->SetModifyHdl( LINK( this, ScRandomNumberGeneratorDialog, Parameter2ValueModified ));
105 :
106 0 : mpDistributionCombo->SetSelectHdl( LINK( this, ScRandomNumberGeneratorDialog, DistributionChanged ));
107 :
108 0 : mpEnableSeed->SetToggleHdl( LINK( this, ScRandomNumberGeneratorDialog, SeedCheckChanged ));
109 :
110 0 : DistributionChanged(NULL);
111 0 : SeedCheckChanged(NULL);
112 0 : }
113 :
114 0 : void ScRandomNumberGeneratorDialog::GetRangeFromSelection()
115 : {
116 0 : mpViewData->GetSimpleArea(maInputRange);
117 0 : OUString aCurrentString(maInputRange.Format(SCR_ABS_3D, mpDoc, mpDoc->GetAddressConvention()));
118 0 : mpInputRangeEdit->SetText( aCurrentString );
119 0 : }
120 :
121 0 : ScRandomNumberGeneratorDialog::~ScRandomNumberGeneratorDialog()
122 0 : {}
123 :
124 0 : void ScRandomNumberGeneratorDialog::SetActive()
125 : {
126 0 : if ( mbDialogLostFocus )
127 : {
128 0 : mbDialogLostFocus = false;
129 0 : if( mpInputRangeEdit )
130 0 : mpInputRangeEdit->GrabFocus();
131 : }
132 : else
133 : {
134 0 : GrabFocus();
135 : }
136 0 : RefInputDone();
137 0 : }
138 :
139 0 : bool ScRandomNumberGeneratorDialog::Close()
140 : {
141 0 : return DoClose( ScRandomNumberGeneratorDialogWrapper::GetChildWindowId() );
142 : }
143 :
144 0 : void ScRandomNumberGeneratorDialog::SetReference( const ScRange& rReferenceRange, ScDocument* pDoc )
145 : {
146 0 : if ( mpInputRangeEdit->IsEnabled() )
147 : {
148 0 : if ( rReferenceRange.aStart != rReferenceRange.aEnd )
149 0 : RefInputStart( mpInputRangeEdit );
150 :
151 0 : maInputRange = rReferenceRange;
152 :
153 0 : OUString aReferenceString(maInputRange.Format(SCR_ABS_3D, pDoc, pDoc->GetAddressConvention()));
154 0 : mpInputRangeEdit->SetRefString( aReferenceString );
155 : }
156 0 : }
157 :
158 0 : void ScRandomNumberGeneratorDialog::SelectGeneratorAndGenerateNumbers()
159 : {
160 0 : sal_Int16 aSelectedIndex = mpDistributionCombo-> GetSelectEntryPos();
161 0 : sal_Int64 aSelectedId = (sal_Int64) mpDistributionCombo->GetEntryData(aSelectedIndex);
162 :
163 : sal_uInt32 seedValue;
164 :
165 0 : if( mpEnableSeed->IsChecked() )
166 : {
167 0 : seedValue = mpSeed->GetValue();
168 : }
169 : else
170 : {
171 : TimeValue now;
172 0 : osl_getSystemTime(&now);
173 0 : seedValue = now.Nanosec;
174 : }
175 :
176 0 : boost::mt19937 seed(seedValue);
177 :
178 0 : sal_Int64 parameterInteger1 = mpParameter1Value->GetValue();
179 0 : sal_Int64 parameterInteger2 = mpParameter2Value->GetValue();
180 :
181 0 : double parameter1 = parameterInteger1 / static_cast<double>(PERCISION);
182 0 : double parameter2 = parameterInteger2 / static_cast<double>(PERCISION);
183 :
184 0 : switch(aSelectedId)
185 : {
186 : case DIST_UNIFORM:
187 : {
188 0 : boost::random::uniform_real_distribution<> distribution(parameter1, parameter2);
189 0 : boost::variate_generator<boost::mt19937&, boost::random::uniform_real_distribution<> > rng(seed, distribution);
190 0 : GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_UNIFORM_REAL));
191 0 : break;
192 : }
193 : case DIST_UNIFORM_INTEGER:
194 : {
195 0 : boost::random::uniform_int_distribution<> distribution(parameterInteger1, parameterInteger2);
196 0 : boost::variate_generator<boost::mt19937&, boost::random::uniform_int_distribution<> > rng(seed, distribution);
197 0 : GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_UNIFORM_INTEGER));
198 0 : break;
199 : }
200 : case DIST_NORMAL:
201 : {
202 0 : boost::random::normal_distribution<> distribution(parameter1, parameter2);
203 0 : boost::variate_generator<boost::mt19937&, boost::random::normal_distribution<> > rng(seed, distribution);
204 0 : GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_NORMAL));
205 0 : break;
206 : }
207 : case DIST_CAUCHY:
208 : {
209 0 : boost::random::cauchy_distribution<> distribution(parameter1);
210 0 : boost::variate_generator<boost::mt19937&, boost::random::cauchy_distribution<> > rng(seed, distribution);
211 0 : GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_CAUCHY));
212 0 : break;
213 : }
214 : case DIST_BERNOULLI:
215 : {
216 0 : boost::random::bernoulli_distribution<> distribution(parameter1);
217 0 : boost::variate_generator<boost::mt19937&, boost::random::bernoulli_distribution<> > rng(seed, distribution);
218 0 : GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_BERNOULLI));
219 0 : break;
220 : }
221 : case DIST_BINOMIAL:
222 : {
223 0 : boost::random::binomial_distribution<> distribution(parameterInteger2, parameter1);
224 0 : boost::variate_generator<boost::mt19937&, boost::random::binomial_distribution<> > rng(seed, distribution);
225 0 : GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_BINOMIAL));
226 0 : break;
227 : }
228 : case DIST_NEGATIVE_BINOMIAL:
229 : {
230 0 : boost::random::negative_binomial_distribution<> distribution(parameterInteger2, parameter1);
231 0 : boost::variate_generator<boost::mt19937&, boost::random::negative_binomial_distribution<> > rng(seed, distribution);
232 0 : GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_NEGATIVE_BINOMIAL));
233 0 : break;
234 : }
235 : case DIST_CHI_SQUARED:
236 : {
237 0 : boost::random::chi_squared_distribution<> distribution(parameter1);
238 0 : boost::variate_generator<boost::mt19937&, boost::random::chi_squared_distribution<> > rng(seed, distribution);
239 0 : GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_CHI_SQUARED));
240 0 : break;
241 : }
242 : case DIST_GEOMETRIC:
243 : {
244 0 : boost::random::geometric_distribution<> distribution(parameter1);
245 0 : boost::variate_generator<boost::mt19937&, boost::random::geometric_distribution<> > rng(seed, distribution);
246 0 : GenerateNumbers(rng, SC_STRLOAD( RID_STATISTICS_DLGS, STR_DISTRIBUTION_GEOMETRIC));
247 0 : break;
248 : }
249 : }
250 0 : }
251 :
252 : template<class RNG>
253 0 : void ScRandomNumberGeneratorDialog::GenerateNumbers(RNG randomGenerator, const OUString& aDistributionName)
254 : {
255 0 : OUString aUndo = SC_STRLOAD( RID_STATISTICS_DLGS, STR_UNDO_DISTRIBUTION_TEMPLATE);
256 0 : aUndo = aUndo.replaceAll("$(DISTRIBUTION)", aDistributionName);
257 :
258 0 : ScDocShell* pDocShell = mpViewData->GetDocShell();
259 0 : svl::IUndoManager* pUndoManager = pDocShell->GetUndoManager();
260 0 : pUndoManager->EnterListAction( aUndo, aUndo );
261 :
262 0 : SCROW nRowStart = maInputRange.aStart.Row();
263 0 : SCROW nRowEnd = maInputRange.aEnd.Row();
264 0 : SCCOL nColStart = maInputRange.aStart.Col();
265 0 : SCCOL nColEnd = maInputRange.aEnd.Col();
266 0 : SCTAB nTabStart = maInputRange.aStart.Tab();
267 0 : SCTAB nTabEnd = maInputRange.aEnd.Tab();
268 :
269 0 : std::vector<double> aVals;
270 0 : aVals.reserve(nRowEnd-nRowStart+1);
271 :
272 0 : for (SCROW nTab = nTabStart; nTab <= nTabEnd; ++nTab)
273 : {
274 0 : for (SCCOL nCol = nColStart; nCol <= nColEnd; ++nCol)
275 : {
276 0 : aVals.clear();
277 :
278 0 : ScAddress aPos(nCol, nRowStart, nTab);
279 0 : for (SCROW nRow = nRowStart; nRow <= nRowEnd; ++nRow)
280 0 : aVals.push_back(randomGenerator());
281 :
282 0 : pDocShell->GetDocFunc().SetValueCells(aPos, aVals, true);
283 : }
284 : }
285 :
286 0 : pUndoManager->LeaveListAction();
287 :
288 0 : pDocShell->PostPaint( maInputRange, PAINT_GRID );
289 0 : }
290 :
291 0 : IMPL_LINK( ScRandomNumberGeneratorDialog, OkClicked, PushButton*, /*pButton*/ )
292 : {
293 0 : ApplyClicked(NULL);
294 0 : CloseClicked(NULL);
295 0 : return 0;
296 : }
297 :
298 :
299 0 : IMPL_LINK( ScRandomNumberGeneratorDialog, ApplyClicked, PushButton*, /*pButton*/ )
300 : {
301 0 : SelectGeneratorAndGenerateNumbers();
302 0 : return 0;
303 : }
304 :
305 0 : IMPL_LINK( ScRandomNumberGeneratorDialog, CloseClicked, PushButton*, /*pButton*/ )
306 : {
307 0 : Close();
308 0 : return 0;
309 : }
310 :
311 0 : IMPL_LINK( ScRandomNumberGeneratorDialog, GetFocusHandler, Control*, pCtrl )
312 : {
313 0 : Edit* pEdit = NULL;
314 :
315 0 : if( (pCtrl == (Control*) mpInputRangeEdit) || (pCtrl == (Control*) mpInputRangeButton) )
316 0 : pEdit = mpInputRangeEdit;
317 :
318 0 : if( pEdit )
319 0 : pEdit->SetSelection( Selection( 0, SELECTION_MAX ) );
320 :
321 0 : return 0;
322 : }
323 :
324 0 : IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog, LoseFocusHandler)
325 : {
326 0 : mbDialogLostFocus = !IsActive();
327 0 : return 0;
328 : }
329 :
330 0 : IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog, Parameter1ValueModified)
331 : {
332 0 : sal_Int16 aSelectedIndex = mpDistributionCombo-> GetSelectEntryPos();
333 0 : sal_Int64 aSelectedId = (sal_Int64) mpDistributionCombo->GetEntryData(aSelectedIndex);
334 0 : if (aSelectedId == DIST_UNIFORM ||
335 : aSelectedId == DIST_UNIFORM_INTEGER)
336 : {
337 0 : sal_Int64 min = mpParameter1Value->GetValue();
338 0 : sal_Int64 max = mpParameter2Value->GetValue();
339 0 : if(min > max)
340 : {
341 0 : mpParameter2Value->SetValue(min);
342 : }
343 : }
344 0 : return 0;
345 : }
346 :
347 0 : IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog, Parameter2ValueModified)
348 : {
349 0 : sal_Int16 aSelectedIndex = mpDistributionCombo-> GetSelectEntryPos();
350 0 : sal_Int64 aSelectedId = (sal_Int64) mpDistributionCombo->GetEntryData(aSelectedIndex);
351 0 : if (aSelectedId == DIST_UNIFORM ||
352 : aSelectedId == DIST_UNIFORM_INTEGER)
353 : {
354 0 : sal_Int64 min = mpParameter1Value->GetValue();
355 0 : sal_Int64 max = mpParameter2Value->GetValue();
356 0 : if(min > max)
357 : {
358 0 : mpParameter1Value->SetValue(max);
359 : }
360 : }
361 0 : return 0;
362 : }
363 :
364 0 : IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog, SeedCheckChanged)
365 : {
366 0 : mpSeed->Enable(mpEnableSeed->IsChecked());
367 0 : return 0;
368 : }
369 :
370 0 : IMPL_LINK_NOARG(ScRandomNumberGeneratorDialog, DistributionChanged)
371 : {
372 0 : sal_Int16 aSelectedIndex = mpDistributionCombo-> GetSelectEntryPos();
373 0 : sal_Int64 aSelectedId = (sal_Int64) mpDistributionCombo->GetEntryData(aSelectedIndex);
374 :
375 0 : mpParameter1Value->SetMin( SAL_MIN_INT64 );
376 0 : mpParameter1Value->SetMax( SAL_MAX_INT64 );
377 0 : mpParameter2Value->SetMin( SAL_MIN_INT64 );
378 0 : mpParameter2Value->SetMax( SAL_MAX_INT64 );
379 :
380 0 : mpParameter1Value->SetDecimalDigits(DIGITS);
381 0 : mpParameter1Value->SetSpinSize(PERCISION);
382 :
383 0 : mpParameter2Value->SetDecimalDigits(DIGITS);
384 0 : mpParameter2Value->SetSpinSize(PERCISION);
385 :
386 0 : switch(aSelectedId)
387 : {
388 : case DIST_UNIFORM:
389 : {
390 0 : mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_MINIMUM));
391 0 : mpParameter2Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_MAXIMUM));
392 0 : mpParameter2Text->Show();
393 0 : mpParameter2Value->Show();
394 0 : break;
395 : }
396 : case DIST_UNIFORM_INTEGER:
397 : {
398 0 : mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_MINIMUM));
399 0 : mpParameter1Value->SetDecimalDigits(0);
400 0 : mpParameter1Value->SetSpinSize(1);
401 :
402 0 : mpParameter2Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_MAXIMUM));
403 0 : mpParameter2Value->SetDecimalDigits(0);
404 0 : mpParameter2Value->SetSpinSize(1);
405 :
406 0 : mpParameter2Text->Show();
407 0 : mpParameter2Value->Show();
408 0 : break;
409 : }
410 : case DIST_NORMAL:
411 : {
412 0 : mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_MEAN));
413 0 : mpParameter2Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_DEVIATION));
414 0 : mpParameter2Text->Show();
415 0 : mpParameter2Value->Show();
416 0 : break;
417 : }
418 : case DIST_CAUCHY:
419 : {
420 0 : mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_MEDIAN));
421 0 : mpParameter2Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_SIGMA));
422 0 : mpParameter2Text->Show();
423 0 : mpParameter2Value->Show();
424 0 : break;
425 : }
426 : case DIST_BERNOULLI:
427 : case DIST_GEOMETRIC:
428 : {
429 0 : mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_PROBABILITY));
430 0 : mpParameter1Value->SetMin( 0 );
431 0 : mpParameter1Value->SetMax( PERCISION );
432 0 : mpParameter1Value->SetSpinSize(1000);
433 :
434 0 : mpParameter2Text->Hide();
435 0 : mpParameter2Value->Hide();
436 0 : break;
437 : }
438 : case DIST_BINOMIAL:
439 : case DIST_NEGATIVE_BINOMIAL:
440 : {
441 0 : mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_PROBABILITY));
442 0 : mpParameter1Value->SetMin( 0 );
443 0 : mpParameter1Value->SetMax( PERCISION );
444 0 : mpParameter1Value->SetSpinSize(1000);
445 :
446 0 : mpParameter2Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_NUMBER_OF_TRIALS));
447 0 : mpParameter2Value->SetDecimalDigits(0);
448 0 : mpParameter2Value->SetSpinSize(1);
449 0 : mpParameter2Value->SetMin(0);
450 :
451 0 : mpParameter2Text->Show();
452 0 : mpParameter2Value->Show();
453 0 : break;
454 : }
455 : case DIST_CHI_SQUARED:
456 : {
457 0 : mpParameter1Text->SetText( SC_STRLOAD( RID_STATISTICS_DLGS, STR_RNG_PARAMETER_STANDARD_NU_VALUE));
458 :
459 0 : mpParameter2Text->Hide();
460 0 : mpParameter2Value->Hide();
461 0 : break;
462 : }
463 : }
464 0 : return 0;
465 0 : }
466 :
467 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|