Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / StatisticsDialogs / SamplingDialog.cxx
blobe67b1c610bc25c3c43e9e9bd0cf895cae87f8b11
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>
28 #include "SamplingDialog.hxx"
30 ScSamplingDialog::ScSamplingDialog(
31 SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
32 Window* pParent, ScViewData* pViewData ) :
33 ScAnyRefDlg ( pSfxBindings, pChildWindow, pParent,
34 "SamplingDialog", "modules/scalc/ui/samplingdialog.ui" ),
35 mViewData ( pViewData ),
36 mDocument ( pViewData->GetDocument() ),
37 mAddressDetails ( mDocument->GetAddressConvention(), 0, 0 ),
38 mCurrentAddress ( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() ),
39 mDialogLostFocus( false )
41 get(mpInputRangeLabel, "input-range-label");
42 get(mpInputRangeEdit, "input-range-edit");
43 get(mpInputRangeButton, "input-range-button");
44 mpInputRangeEdit->SetReferences(this, mpInputRangeLabel);
45 mpInputRangeButton->SetReferences(this, mpInputRangeEdit);
47 get(mpOutputRangeLabel, "output-range-label");
48 get(mpOutputRangeEdit, "output-range-edit");
49 get(mpOutputRangeButton, "output-range-button");
50 mpOutputRangeEdit->SetReferences(this, mpOutputRangeLabel);
51 mpOutputRangeButton->SetReferences(this, mpOutputRangeEdit);
53 get(mpSampleSize, "sample-size-spin");
54 get(mpPeriod, "period-spin");
56 get(mpRandomMethodRadio, "random-method-radio");
57 get(mpPeriodicMethodRadio, "periodic-method-radio");
59 get(mpButtonOk, "ok");
60 get(mpButtonApply, "apply");
61 get(mpButtonClose, "close");
63 Init();
64 GetRangeFromSelection();
67 void ScSamplingDialog::Init()
69 mpButtonOk->SetClickHdl( LINK( this, ScSamplingDialog, OkClicked ) );
70 mpButtonClose->SetClickHdl( LINK( this, ScSamplingDialog, CloseClicked ) );
71 mpButtonApply->SetClickHdl( LINK( this, ScSamplingDialog, ApplyClicked ) );
72 mpButtonOk->Enable(false);
73 mpButtonApply->Enable(false);
75 Link aLink = LINK( this, ScSamplingDialog, GetFocusHandler );
76 mpInputRangeEdit->SetGetFocusHdl( aLink );
77 mpInputRangeButton->SetGetFocusHdl( aLink );
78 mpOutputRangeEdit->SetGetFocusHdl( aLink );
79 mpOutputRangeButton->SetGetFocusHdl( aLink );
81 aLink = LINK( this, ScSamplingDialog, LoseFocusHandler );
82 mpInputRangeEdit->SetLoseFocusHdl( aLink );
83 mpInputRangeButton->SetLoseFocusHdl( aLink );
84 mpOutputRangeEdit->SetLoseFocusHdl( aLink );
85 mpOutputRangeButton->SetLoseFocusHdl( aLink );
87 mpSampleSize->SetModifyHdl( LINK( this, ScSamplingDialog, SamplingSizeValueModified ));
89 mpPeriodicMethodRadio->SetToggleHdl( LINK( this, ScSamplingDialog, ToggleSamplingMethod ) );
90 mpRandomMethodRadio->SetToggleHdl( LINK( this, ScSamplingDialog, ToggleSamplingMethod ) );
92 mpSampleSize->SetMin( 0 );
93 mpSampleSize->SetMax( SAL_MAX_INT64 );
95 mpOutputRangeEdit->GrabFocus();
96 mpPeriodicMethodRadio->Check(true);
98 ToggleSamplingMethod(NULL);
101 void ScSamplingDialog::GetRangeFromSelection()
103 mViewData->GetSimpleArea(mInputRange);
104 OUString aCurrentString(mInputRange.Format(SCR_ABS_3D, mDocument, mAddressDetails));
105 mpInputRangeEdit->SetText(aCurrentString);
108 ScSamplingDialog::~ScSamplingDialog()
111 void ScSamplingDialog::SetActive()
113 if ( mDialogLostFocus )
115 mDialogLostFocus = false;
116 if( mpActiveEdit )
117 mpActiveEdit->GrabFocus();
119 else
121 GrabFocus();
123 RefInputDone();
126 sal_Bool ScSamplingDialog::Close()
128 return DoClose( ScSamplingDialogWrapper::GetChildWindowId() );
131 void ScSamplingDialog::SetReference( const ScRange& rReferenceRange, ScDocument* pDocument )
133 if ( mpActiveEdit )
135 if ( rReferenceRange.aStart != rReferenceRange.aEnd )
136 RefInputStart( mpActiveEdit );
138 OUString aReferenceString;
140 if ( mpActiveEdit == mpInputRangeEdit )
142 mInputRange = rReferenceRange;
143 aReferenceString = mInputRange.Format(SCR_ABS_3D, pDocument, mAddressDetails);
144 mpInputRangeEdit->SetRefString( aReferenceString );
146 else if ( mpActiveEdit == mpOutputRangeEdit )
148 mOutputAddress = rReferenceRange.aStart;
150 sal_uInt16 nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ? SCA_ABS : SCA_ABS_3D;
151 aReferenceString = mOutputAddress.Format(nFormat, pDocument, pDocument->GetAddressConvention());
152 mpOutputRangeEdit->SetRefString( aReferenceString );
154 // Change sampling size according to output range selection
155 sal_Int64 aSelectedSampleSize = rReferenceRange.aEnd.Row() - rReferenceRange.aStart.Row() + 1;
156 if (aSelectedSampleSize > 1)
157 mpSampleSize->SetValue(aSelectedSampleSize);
158 SamplingSizeValueModified(NULL);
160 // Enable OK, Cancel if output range is set
161 mpButtonOk->Enable(!mpOutputRangeEdit->GetText().isEmpty());
162 mpButtonApply->Enable(!mpOutputRangeEdit->GetText().isEmpty());
167 ScRange ScSamplingDialog::PerformPeriodicSampling(ScDocShell* pDocShell)
169 ScAddress aStart = mInputRange.aStart;
170 ScAddress aEnd = mInputRange.aEnd;
172 SCTAB outTab = mOutputAddress.Tab();
173 SCCOL outCol = mOutputAddress.Col();
174 SCROW outRow = mOutputAddress.Row();
176 sal_Int64 aPeriod = mpPeriod->GetValue();
178 for (SCROW inTab = aStart.Tab(); inTab <= aEnd.Tab(); inTab++)
180 outCol = mOutputAddress.Col();
181 for (SCCOL inCol = aStart.Col(); inCol <= aEnd.Col(); inCol++)
183 sal_Int64 i = 0;
184 outRow = mOutputAddress.Row();
185 for (SCROW inRow = aStart.Row(); inRow <= aEnd.Row(); inRow++)
187 if (i % aPeriod == aPeriod - 1 ) // Sample the last of period
189 double aValue = mDocument->GetValue(ScAddress(inCol, inRow, inTab));
190 pDocShell->GetDocFunc().SetValueCell(ScAddress(outCol, outRow, outTab), aValue, true);
191 outRow++;
193 i++;
195 outCol++;
197 outTab++;
200 return ScRange(mOutputAddress, ScAddress(outTab, outRow, outTab) );
203 ScRange ScSamplingDialog::PerformRandomSampling(ScDocShell* pDocShell)
205 ScAddress aStart = mInputRange.aStart;
206 ScAddress aEnd = mInputRange.aEnd;
208 SCTAB outTab = mOutputAddress.Tab();
209 SCCOL outCol = mOutputAddress.Col();
210 SCROW outRow = mOutputAddress.Row();
212 TimeValue now;
213 osl_getSystemTime(&now);
214 boost::mt19937 seed(now.Nanosec);
215 boost::uniform_01<boost::mt19937> rng(seed);
217 SCROW inRow;
219 sal_Int64 aSampleSize = mpSampleSize->GetValue();
221 for (SCROW inTab = aStart.Tab(); inTab <= aEnd.Tab(); inTab++)
223 outCol = mOutputAddress.Col();
224 for (SCCOL inCol = aStart.Col(); inCol <= aEnd.Col(); inCol++)
226 SCROW aPopulationSize = (aEnd.Row() - aStart.Row()) + 1;
228 outRow = mOutputAddress.Row();
229 inRow = aStart.Row();
231 double aRandomValue;
233 while ((outRow - mOutputAddress.Row()) < aSampleSize)
235 aRandomValue = rng();
237 if ( (aPopulationSize - (inRow - aStart.Row())) * aRandomValue >= aSampleSize - (outRow - mOutputAddress.Row()) )
239 inRow++;
241 else
243 double aValue = mDocument->GetValue( ScAddress(inCol, inRow, inTab) );
244 pDocShell->GetDocFunc().SetValueCell(ScAddress(outCol, outRow, outTab), aValue, true);
245 inRow++;
246 outRow++;
249 outCol++;
251 outTab++;
254 return ScRange(mOutputAddress, ScAddress(outTab, outRow, outTab) );
257 void ScSamplingDialog::PerformSampling()
259 OUString aUndo( SC_STRLOAD( RID_STATISTICS_DLGS, STR_SAMPLING_UNDO_NAME));
260 ScDocShell* pDocShell = mViewData->GetDocShell();
261 svl::IUndoManager* pUndoManager = pDocShell->GetUndoManager();
263 ScRange aModifiedRange;
265 pUndoManager->EnterListAction( aUndo, aUndo );
267 if (mpRandomMethodRadio->IsChecked())
269 aModifiedRange = PerformRandomSampling(pDocShell);
271 else if (mpPeriodicMethodRadio->IsChecked())
273 aModifiedRange = PerformPeriodicSampling(pDocShell);
276 pUndoManager->LeaveListAction();
277 pDocShell->PostPaint(aModifiedRange, PAINT_GRID);
280 IMPL_LINK( ScSamplingDialog, OkClicked, PushButton*, /*pButton*/ )
282 ApplyClicked(NULL);
283 CloseClicked(NULL);
284 return 0;
288 IMPL_LINK( ScSamplingDialog, ApplyClicked, PushButton*, /*pButton*/ )
290 PerformSampling();
291 return 0;
294 IMPL_LINK( ScSamplingDialog, CloseClicked, PushButton*, /*pButton*/ )
296 Close();
297 return 0;
300 IMPL_LINK( ScSamplingDialog, GetFocusHandler, Control*, pCtrl )
302 mpActiveEdit = NULL;
304 if( (pCtrl == (Control*) mpInputRangeEdit) || (pCtrl == (Control*) mpInputRangeButton) )
305 mpActiveEdit = mpInputRangeEdit;
306 else if( (pCtrl == (Control*) mpOutputRangeEdit) || (pCtrl == (Control*) mpOutputRangeButton) )
307 mpActiveEdit = mpOutputRangeEdit;
309 if( mpActiveEdit )
310 mpActiveEdit->SetSelection( Selection( 0, SELECTION_MAX ) );
312 return 0;
315 IMPL_LINK_NOARG(ScSamplingDialog, LoseFocusHandler)
317 mDialogLostFocus = !IsActive();
318 return 0;
321 IMPL_LINK_NOARG(ScSamplingDialog, SamplingSizeValueModified)
323 sal_Int64 aPopulationSize = mInputRange.aEnd.Row() - mInputRange.aStart.Row() + 1;
324 if (mpSampleSize->GetValue() > aPopulationSize)
325 mpSampleSize->SetValue(aPopulationSize);
326 return 0;
329 IMPL_LINK_NOARG(ScSamplingDialog, ToggleSamplingMethod)
331 if (mpRandomMethodRadio->IsChecked())
333 mpPeriod->Enable(false);
334 mpSampleSize->Enable(true);
336 else if (mpPeriodicMethodRadio->IsChecked())
338 mpPeriod->Enable(true);
339 mpSampleSize->Enable(false);
341 return 0;
345 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */