fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / StatisticsDialogs / SamplingDialog.cxx
blobbfd467fa078696de158c165736ac3ad5e20163ce
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>
14 #include <comphelper/random.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 "docfunc.hxx"
23 #include "StatisticsDialogs.hrc"
25 #include "SamplingDialog.hxx"
27 ScSamplingDialog::ScSamplingDialog(
28 SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
29 vcl::Window* pParent, ScViewData* pViewData ) :
30 ScAnyRefDlg ( pSfxBindings, pChildWindow, pParent,
31 "SamplingDialog", "modules/scalc/ui/samplingdialog.ui" ),
32 mpActiveEdit ( NULL ),
33 mViewData ( pViewData ),
34 mDocument ( pViewData->GetDocument() ),
35 mInputRange ( ScAddress::INITIALIZE_INVALID ),
36 mAddressDetails ( mDocument->GetAddressConvention(), 0, 0 ),
37 mOutputAddress ( ScAddress::INITIALIZE_INVALID ),
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");
61 Init();
62 GetRangeFromSelection();
65 ScSamplingDialog::~ScSamplingDialog()
67 disposeOnce();
70 void ScSamplingDialog::dispose()
72 mpInputRangeLabel.clear();
73 mpInputRangeEdit.clear();
74 mpInputRangeButton.clear();
75 mpOutputRangeLabel.clear();
76 mpOutputRangeEdit.clear();
77 mpOutputRangeButton.clear();
78 mpSampleSize.clear();
79 mpPeriod.clear();
80 mpRandomMethodRadio.clear();
81 mpPeriodicMethodRadio.clear();
82 mpButtonOk.clear();
83 mpActiveEdit.clear();
84 ScAnyRefDlg::dispose();
87 void ScSamplingDialog::Init()
89 mpButtonOk->SetClickHdl( LINK( this, ScSamplingDialog, OkClicked ) );
90 mpButtonOk->Enable(false);
92 Link<> aLink = LINK( this, ScSamplingDialog, GetFocusHandler );
93 mpInputRangeEdit->SetGetFocusHdl( aLink );
94 mpInputRangeButton->SetGetFocusHdl( aLink );
95 mpOutputRangeEdit->SetGetFocusHdl( aLink );
96 mpOutputRangeButton->SetGetFocusHdl( aLink );
98 aLink = LINK( this, ScSamplingDialog, LoseFocusHandler );
99 mpInputRangeEdit->SetLoseFocusHdl( aLink );
100 mpInputRangeButton->SetLoseFocusHdl( aLink );
101 mpOutputRangeEdit->SetLoseFocusHdl( aLink );
102 mpOutputRangeButton->SetLoseFocusHdl( aLink );
104 aLink = LINK( this, ScSamplingDialog, RefInputModifyHandler);
105 mpInputRangeEdit->SetModifyHdl( aLink);
106 mpOutputRangeEdit->SetModifyHdl( aLink);
108 mpSampleSize->SetModifyHdl( LINK( this, ScSamplingDialog, SamplingSizeValueModified ));
110 mpPeriodicMethodRadio->SetToggleHdl( LINK( this, ScSamplingDialog, ToggleSamplingMethod ) );
111 mpRandomMethodRadio->SetToggleHdl( LINK( this, ScSamplingDialog, ToggleSamplingMethod ) );
113 mpSampleSize->SetMin( 0 );
114 mpSampleSize->SetMax( SAL_MAX_INT64 );
116 mpOutputRangeEdit->GrabFocus();
117 mpPeriodicMethodRadio->Check(true);
119 ToggleSamplingMethod(NULL);
122 void ScSamplingDialog::GetRangeFromSelection()
124 mViewData->GetSimpleArea(mInputRange);
125 OUString aCurrentString(mInputRange.Format(SCR_ABS_3D, mDocument, mAddressDetails));
126 mpInputRangeEdit->SetText(aCurrentString);
129 void ScSamplingDialog::SetActive()
131 if ( mDialogLostFocus )
133 mDialogLostFocus = false;
134 if( mpActiveEdit )
135 mpActiveEdit->GrabFocus();
137 else
139 GrabFocus();
141 RefInputDone();
144 bool ScSamplingDialog::Close()
146 return DoClose( ScSamplingDialogWrapper::GetChildWindowId() );
149 void ScSamplingDialog::SetReference( const ScRange& rReferenceRange, ScDocument* pDocument )
151 if ( mpActiveEdit )
153 if ( rReferenceRange.aStart != rReferenceRange.aEnd )
154 RefInputStart( mpActiveEdit );
156 OUString aReferenceString;
158 if ( mpActiveEdit == mpInputRangeEdit )
160 mInputRange = rReferenceRange;
161 aReferenceString = mInputRange.Format(SCR_ABS_3D, pDocument, mAddressDetails);
162 mpInputRangeEdit->SetRefString( aReferenceString );
164 else if ( mpActiveEdit == mpOutputRangeEdit )
166 mOutputAddress = rReferenceRange.aStart;
168 sal_uInt16 nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ? SCA_ABS : SCA_ABS_3D;
169 aReferenceString = mOutputAddress.Format(nFormat, pDocument, pDocument->GetAddressConvention());
170 mpOutputRangeEdit->SetRefString( aReferenceString );
172 // Change sampling size according to output range selection
173 sal_Int64 aSelectedSampleSize = rReferenceRange.aEnd.Row() - rReferenceRange.aStart.Row() + 1;
174 if (aSelectedSampleSize > 1)
175 mpSampleSize->SetValue(aSelectedSampleSize);
176 SamplingSizeValueModified(NULL);
180 // Enable OK if both, input range and output address are set.
181 if (mInputRange.IsValid() && mOutputAddress.IsValid())
182 mpButtonOk->Enable();
185 ScRange ScSamplingDialog::PerformPeriodicSampling(ScDocShell* pDocShell)
187 ScAddress aStart = mInputRange.aStart;
188 ScAddress aEnd = mInputRange.aEnd;
190 SCTAB outTab = mOutputAddress.Tab();
191 SCCOL outCol = mOutputAddress.Col();
192 SCROW outRow = mOutputAddress.Row();
194 sal_Int64 aPeriod = mpPeriod->GetValue();
196 for (SCROW inTab = aStart.Tab(); inTab <= aEnd.Tab(); inTab++)
198 outCol = mOutputAddress.Col();
199 for (SCCOL inCol = aStart.Col(); inCol <= aEnd.Col(); inCol++)
201 sal_Int64 i = 0;
202 outRow = mOutputAddress.Row();
203 for (SCROW inRow = aStart.Row(); inRow <= aEnd.Row(); inRow++)
205 if (i % aPeriod == aPeriod - 1 ) // Sample the last of period
207 double aValue = mDocument->GetValue(ScAddress(inCol, inRow, inTab));
208 pDocShell->GetDocFunc().SetValueCell(ScAddress(outCol, outRow, outTab), aValue, true);
209 outRow++;
211 i++;
213 outCol++;
215 outTab++;
218 return ScRange(mOutputAddress, ScAddress(outTab, outRow, outTab) );
221 ScRange ScSamplingDialog::PerformRandomSampling(ScDocShell* pDocShell)
223 ScAddress aStart = mInputRange.aStart;
224 ScAddress aEnd = mInputRange.aEnd;
226 SCTAB outTab = mOutputAddress.Tab();
227 SCCOL outCol = mOutputAddress.Col();
228 SCROW outRow = mOutputAddress.Row();
230 SCROW inRow;
232 sal_Int64 aSampleSize = mpSampleSize->GetValue();
234 for (SCROW inTab = aStart.Tab(); inTab <= aEnd.Tab(); inTab++)
236 outCol = mOutputAddress.Col();
237 for (SCCOL inCol = aStart.Col(); inCol <= aEnd.Col(); inCol++)
239 SCROW aPopulationSize = (aEnd.Row() - aStart.Row()) + 1;
241 outRow = mOutputAddress.Row();
242 inRow = aStart.Row();
244 while ((outRow - mOutputAddress.Row()) < aSampleSize)
246 double aRandomValue = comphelper::rng::uniform_real_distribution();
248 if ( (aPopulationSize - (inRow - aStart.Row())) * aRandomValue >= aSampleSize - (outRow - mOutputAddress.Row()) )
250 inRow++;
252 else
254 double aValue = mDocument->GetValue( ScAddress(inCol, inRow, inTab) );
255 pDocShell->GetDocFunc().SetValueCell(ScAddress(outCol, outRow, outTab), aValue, true);
256 inRow++;
257 outRow++;
260 outCol++;
262 outTab++;
265 return ScRange(mOutputAddress, ScAddress(outTab, outRow, outTab) );
268 void ScSamplingDialog::PerformSampling()
270 OUString aUndo( SC_STRLOAD( RID_STATISTICS_DLGS, STR_SAMPLING_UNDO_NAME));
271 ScDocShell* pDocShell = mViewData->GetDocShell();
272 svl::IUndoManager* pUndoManager = pDocShell->GetUndoManager();
274 ScRange aModifiedRange;
276 pUndoManager->EnterListAction( aUndo, aUndo );
278 if (mpRandomMethodRadio->IsChecked())
280 aModifiedRange = PerformRandomSampling(pDocShell);
282 else if (mpPeriodicMethodRadio->IsChecked())
284 aModifiedRange = PerformPeriodicSampling(pDocShell);
287 pUndoManager->LeaveListAction();
288 pDocShell->PostPaint(aModifiedRange, PAINT_GRID);
291 IMPL_LINK( ScSamplingDialog, OkClicked, PushButton*, /*pButton*/ )
293 PerformSampling();
294 Close();
295 return 0;
298 IMPL_LINK( ScSamplingDialog, GetFocusHandler, Control*, pCtrl )
300 mpActiveEdit = NULL;
302 if( (pCtrl == (Control*) mpInputRangeEdit) || (pCtrl == (Control*) mpInputRangeButton) )
303 mpActiveEdit = mpInputRangeEdit;
304 else if( (pCtrl == (Control*) mpOutputRangeEdit) || (pCtrl == (Control*) mpOutputRangeButton) )
305 mpActiveEdit = mpOutputRangeEdit;
307 if( mpActiveEdit )
308 mpActiveEdit->SetSelection( Selection( 0, SELECTION_MAX ) );
310 return 0;
313 IMPL_LINK_NOARG(ScSamplingDialog, LoseFocusHandler)
315 mDialogLostFocus = !IsActive();
316 return 0;
319 IMPL_LINK_NOARG(ScSamplingDialog, SamplingSizeValueModified)
321 sal_Int64 aPopulationSize = mInputRange.aEnd.Row() - mInputRange.aStart.Row() + 1;
322 if (mpSampleSize->GetValue() > aPopulationSize)
323 mpSampleSize->SetValue(aPopulationSize);
324 return 0;
327 IMPL_LINK_NOARG(ScSamplingDialog, ToggleSamplingMethod)
329 if (mpRandomMethodRadio->IsChecked())
331 mpPeriod->Enable(false);
332 mpSampleSize->Enable(true);
334 else if (mpPeriodicMethodRadio->IsChecked())
336 mpPeriod->Enable(true);
337 mpSampleSize->Enable(false);
339 return 0;
342 IMPL_LINK_NOARG(ScSamplingDialog, RefInputModifyHandler)
344 if ( mpActiveEdit )
346 if ( mpActiveEdit == mpInputRangeEdit )
348 ScRangeList aRangeList;
349 bool bValid = ParseWithNames( aRangeList, mpInputRangeEdit->GetText(), mDocument);
350 const ScRange* pRange = (bValid && aRangeList.size() == 1) ? aRangeList[0] : nullptr;
351 if (pRange)
353 mInputRange = *pRange;
354 // Highlight the resulting range.
355 mpInputRangeEdit->StartUpdateData();
357 else
359 mInputRange = ScRange( ScAddress::INITIALIZE_INVALID);
362 else if ( mpActiveEdit == mpOutputRangeEdit )
364 ScRangeList aRangeList;
365 bool bValid = ParseWithNames( aRangeList, mpOutputRangeEdit->GetText(), mDocument);
366 const ScRange* pRange = (bValid && aRangeList.size() == 1) ? aRangeList[0] : nullptr;
367 if (pRange)
369 mOutputAddress = pRange->aStart;
371 // Crop output range to top left address for Edit field.
372 if (pRange->aStart != pRange->aEnd)
374 sal_uInt16 nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ? SCA_ABS : SCA_ABS_3D;
375 OUString aReferenceString = mOutputAddress.Format(nFormat, mDocument, mDocument->GetAddressConvention());
376 mpOutputRangeEdit->SetRefString( aReferenceString );
379 // Change sampling size according to output range selection
380 sal_Int64 aSelectedSampleSize = pRange->aEnd.Row() - pRange->aStart.Row() + 1;
381 if (aSelectedSampleSize > 1)
382 mpSampleSize->SetValue(aSelectedSampleSize);
383 SamplingSizeValueModified(NULL);
385 // Highlight the resulting range.
386 mpOutputRangeEdit->StartUpdateData();
388 else
390 mOutputAddress = ScAddress( ScAddress::INITIALIZE_INVALID);
395 // Enable OK if both, input range and output address are set.
396 if (mInputRange.IsValid() && mOutputAddress.IsValid())
397 mpButtonOk->Enable();
398 else
399 mpButtonOk->Disable();
401 return 0;
404 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */