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 : #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"
24 :
25 : #include "SamplingDialog.hxx"
26 :
27 0 : 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 0 : mDocument ( pViewData->GetDocument() ),
35 : mAddressDetails ( mDocument->GetAddressConvention(), 0, 0 ),
36 0 : mCurrentAddress ( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() ),
37 0 : mDialogLostFocus( false )
38 : {
39 0 : get(mpInputRangeLabel, "input-range-label");
40 0 : get(mpInputRangeEdit, "input-range-edit");
41 0 : get(mpInputRangeButton, "input-range-button");
42 0 : mpInputRangeEdit->SetReferences(this, mpInputRangeLabel);
43 0 : mpInputRangeButton->SetReferences(this, mpInputRangeEdit);
44 :
45 0 : get(mpOutputRangeLabel, "output-range-label");
46 0 : get(mpOutputRangeEdit, "output-range-edit");
47 0 : get(mpOutputRangeButton, "output-range-button");
48 0 : mpOutputRangeEdit->SetReferences(this, mpOutputRangeLabel);
49 0 : mpOutputRangeButton->SetReferences(this, mpOutputRangeEdit);
50 :
51 0 : get(mpSampleSize, "sample-size-spin");
52 0 : get(mpPeriod, "period-spin");
53 :
54 0 : get(mpRandomMethodRadio, "random-method-radio");
55 0 : get(mpPeriodicMethodRadio, "periodic-method-radio");
56 :
57 0 : get(mpButtonOk, "ok");
58 :
59 0 : Init();
60 0 : GetRangeFromSelection();
61 0 : }
62 :
63 0 : void ScSamplingDialog::Init()
64 : {
65 0 : mpButtonOk->SetClickHdl( LINK( this, ScSamplingDialog, OkClicked ) );
66 0 : mpButtonOk->Enable(false);
67 :
68 0 : Link aLink = LINK( this, ScSamplingDialog, GetFocusHandler );
69 0 : mpInputRangeEdit->SetGetFocusHdl( aLink );
70 0 : mpInputRangeButton->SetGetFocusHdl( aLink );
71 0 : mpOutputRangeEdit->SetGetFocusHdl( aLink );
72 0 : mpOutputRangeButton->SetGetFocusHdl( aLink );
73 :
74 0 : aLink = LINK( this, ScSamplingDialog, LoseFocusHandler );
75 0 : mpInputRangeEdit->SetLoseFocusHdl( aLink );
76 0 : mpInputRangeButton->SetLoseFocusHdl( aLink );
77 0 : mpOutputRangeEdit->SetLoseFocusHdl( aLink );
78 0 : mpOutputRangeButton->SetLoseFocusHdl( aLink );
79 :
80 0 : mpSampleSize->SetModifyHdl( LINK( this, ScSamplingDialog, SamplingSizeValueModified ));
81 :
82 0 : mpPeriodicMethodRadio->SetToggleHdl( LINK( this, ScSamplingDialog, ToggleSamplingMethod ) );
83 0 : mpRandomMethodRadio->SetToggleHdl( LINK( this, ScSamplingDialog, ToggleSamplingMethod ) );
84 :
85 0 : mpSampleSize->SetMin( 0 );
86 0 : mpSampleSize->SetMax( SAL_MAX_INT64 );
87 :
88 0 : mpOutputRangeEdit->GrabFocus();
89 0 : mpPeriodicMethodRadio->Check(true);
90 :
91 0 : ToggleSamplingMethod(NULL);
92 0 : }
93 :
94 0 : void ScSamplingDialog::GetRangeFromSelection()
95 : {
96 0 : mViewData->GetSimpleArea(mInputRange);
97 0 : OUString aCurrentString(mInputRange.Format(SCR_ABS_3D, mDocument, mAddressDetails));
98 0 : mpInputRangeEdit->SetText(aCurrentString);
99 0 : }
100 :
101 0 : ScSamplingDialog::~ScSamplingDialog()
102 0 : {}
103 :
104 0 : void ScSamplingDialog::SetActive()
105 : {
106 0 : if ( mDialogLostFocus )
107 : {
108 0 : mDialogLostFocus = false;
109 0 : if( mpActiveEdit )
110 0 : mpActiveEdit->GrabFocus();
111 : }
112 : else
113 : {
114 0 : GrabFocus();
115 : }
116 0 : RefInputDone();
117 0 : }
118 :
119 0 : bool ScSamplingDialog::Close()
120 : {
121 0 : return DoClose( ScSamplingDialogWrapper::GetChildWindowId() );
122 : }
123 :
124 0 : void ScSamplingDialog::SetReference( const ScRange& rReferenceRange, ScDocument* pDocument )
125 : {
126 0 : if ( mpActiveEdit )
127 : {
128 0 : if ( rReferenceRange.aStart != rReferenceRange.aEnd )
129 0 : RefInputStart( mpActiveEdit );
130 :
131 0 : OUString aReferenceString;
132 :
133 0 : if ( mpActiveEdit == mpInputRangeEdit )
134 : {
135 0 : mInputRange = rReferenceRange;
136 0 : aReferenceString = mInputRange.Format(SCR_ABS_3D, pDocument, mAddressDetails);
137 0 : mpInputRangeEdit->SetRefString( aReferenceString );
138 : }
139 0 : else if ( mpActiveEdit == mpOutputRangeEdit )
140 : {
141 0 : mOutputAddress = rReferenceRange.aStart;
142 :
143 0 : sal_uInt16 nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ? SCA_ABS : SCA_ABS_3D;
144 0 : aReferenceString = mOutputAddress.Format(nFormat, pDocument, pDocument->GetAddressConvention());
145 0 : mpOutputRangeEdit->SetRefString( aReferenceString );
146 :
147 : // Change sampling size according to output range selection
148 0 : sal_Int64 aSelectedSampleSize = rReferenceRange.aEnd.Row() - rReferenceRange.aStart.Row() + 1;
149 0 : if (aSelectedSampleSize > 1)
150 0 : mpSampleSize->SetValue(aSelectedSampleSize);
151 0 : SamplingSizeValueModified(NULL);
152 :
153 : // Enable OK, Cancel if output range is set
154 0 : mpButtonOk->Enable(!mpOutputRangeEdit->GetText().isEmpty());
155 0 : }
156 : }
157 0 : }
158 :
159 0 : ScRange ScSamplingDialog::PerformPeriodicSampling(ScDocShell* pDocShell)
160 : {
161 0 : ScAddress aStart = mInputRange.aStart;
162 0 : ScAddress aEnd = mInputRange.aEnd;
163 :
164 0 : SCTAB outTab = mOutputAddress.Tab();
165 0 : SCCOL outCol = mOutputAddress.Col();
166 0 : SCROW outRow = mOutputAddress.Row();
167 :
168 0 : sal_Int64 aPeriod = mpPeriod->GetValue();
169 :
170 0 : for (SCROW inTab = aStart.Tab(); inTab <= aEnd.Tab(); inTab++)
171 : {
172 0 : outCol = mOutputAddress.Col();
173 0 : for (SCCOL inCol = aStart.Col(); inCol <= aEnd.Col(); inCol++)
174 : {
175 0 : sal_Int64 i = 0;
176 0 : outRow = mOutputAddress.Row();
177 0 : for (SCROW inRow = aStart.Row(); inRow <= aEnd.Row(); inRow++)
178 : {
179 0 : if (i % aPeriod == aPeriod - 1 ) // Sample the last of period
180 : {
181 0 : double aValue = mDocument->GetValue(ScAddress(inCol, inRow, inTab));
182 0 : pDocShell->GetDocFunc().SetValueCell(ScAddress(outCol, outRow, outTab), aValue, true);
183 0 : outRow++;
184 : }
185 0 : i++;
186 : }
187 0 : outCol++;
188 : }
189 0 : outTab++;
190 : }
191 :
192 0 : return ScRange(mOutputAddress, ScAddress(outTab, outRow, outTab) );
193 : }
194 :
195 0 : ScRange ScSamplingDialog::PerformRandomSampling(ScDocShell* pDocShell)
196 : {
197 0 : ScAddress aStart = mInputRange.aStart;
198 0 : ScAddress aEnd = mInputRange.aEnd;
199 :
200 0 : SCTAB outTab = mOutputAddress.Tab();
201 0 : SCCOL outCol = mOutputAddress.Col();
202 0 : SCROW outRow = mOutputAddress.Row();
203 :
204 : SCROW inRow;
205 :
206 0 : sal_Int64 aSampleSize = mpSampleSize->GetValue();
207 :
208 0 : for (SCROW inTab = aStart.Tab(); inTab <= aEnd.Tab(); inTab++)
209 : {
210 0 : outCol = mOutputAddress.Col();
211 0 : for (SCCOL inCol = aStart.Col(); inCol <= aEnd.Col(); inCol++)
212 : {
213 0 : SCROW aPopulationSize = (aEnd.Row() - aStart.Row()) + 1;
214 :
215 0 : outRow = mOutputAddress.Row();
216 0 : inRow = aStart.Row();
217 :
218 0 : while ((outRow - mOutputAddress.Row()) < aSampleSize)
219 : {
220 0 : double aRandomValue = comphelper::rng::uniform_real_distribution();
221 :
222 0 : if ( (aPopulationSize - (inRow - aStart.Row())) * aRandomValue >= aSampleSize - (outRow - mOutputAddress.Row()) )
223 : {
224 0 : inRow++;
225 : }
226 : else
227 : {
228 0 : double aValue = mDocument->GetValue( ScAddress(inCol, inRow, inTab) );
229 0 : pDocShell->GetDocFunc().SetValueCell(ScAddress(outCol, outRow, outTab), aValue, true);
230 0 : inRow++;
231 0 : outRow++;
232 : }
233 : }
234 0 : outCol++;
235 : }
236 0 : outTab++;
237 : }
238 :
239 0 : return ScRange(mOutputAddress, ScAddress(outTab, outRow, outTab) );
240 : }
241 :
242 0 : void ScSamplingDialog::PerformSampling()
243 : {
244 0 : OUString aUndo( SC_STRLOAD( RID_STATISTICS_DLGS, STR_SAMPLING_UNDO_NAME));
245 0 : ScDocShell* pDocShell = mViewData->GetDocShell();
246 0 : svl::IUndoManager* pUndoManager = pDocShell->GetUndoManager();
247 :
248 0 : ScRange aModifiedRange;
249 :
250 0 : pUndoManager->EnterListAction( aUndo, aUndo );
251 :
252 0 : if (mpRandomMethodRadio->IsChecked())
253 : {
254 0 : aModifiedRange = PerformRandomSampling(pDocShell);
255 : }
256 0 : else if (mpPeriodicMethodRadio->IsChecked())
257 : {
258 0 : aModifiedRange = PerformPeriodicSampling(pDocShell);
259 : }
260 :
261 0 : pUndoManager->LeaveListAction();
262 0 : pDocShell->PostPaint(aModifiedRange, PAINT_GRID);
263 0 : }
264 :
265 0 : IMPL_LINK( ScSamplingDialog, OkClicked, PushButton*, /*pButton*/ )
266 : {
267 0 : PerformSampling();
268 0 : Close();
269 0 : return 0;
270 : }
271 :
272 0 : IMPL_LINK( ScSamplingDialog, GetFocusHandler, Control*, pCtrl )
273 : {
274 0 : mpActiveEdit = NULL;
275 :
276 0 : if( (pCtrl == (Control*) mpInputRangeEdit) || (pCtrl == (Control*) mpInputRangeButton) )
277 0 : mpActiveEdit = mpInputRangeEdit;
278 0 : else if( (pCtrl == (Control*) mpOutputRangeEdit) || (pCtrl == (Control*) mpOutputRangeButton) )
279 0 : mpActiveEdit = mpOutputRangeEdit;
280 :
281 0 : if( mpActiveEdit )
282 0 : mpActiveEdit->SetSelection( Selection( 0, SELECTION_MAX ) );
283 :
284 0 : return 0;
285 : }
286 :
287 0 : IMPL_LINK_NOARG(ScSamplingDialog, LoseFocusHandler)
288 : {
289 0 : mDialogLostFocus = !IsActive();
290 0 : return 0;
291 : }
292 :
293 0 : IMPL_LINK_NOARG(ScSamplingDialog, SamplingSizeValueModified)
294 : {
295 0 : sal_Int64 aPopulationSize = mInputRange.aEnd.Row() - mInputRange.aStart.Row() + 1;
296 0 : if (mpSampleSize->GetValue() > aPopulationSize)
297 0 : mpSampleSize->SetValue(aPopulationSize);
298 0 : return 0;
299 : }
300 :
301 0 : IMPL_LINK_NOARG(ScSamplingDialog, ToggleSamplingMethod)
302 : {
303 0 : if (mpRandomMethodRadio->IsChecked())
304 : {
305 0 : mpPeriod->Enable(false);
306 0 : mpSampleSize->Enable(true);
307 : }
308 0 : else if (mpPeriodicMethodRadio->IsChecked())
309 : {
310 0 : mpPeriod->Enable(true);
311 0 : mpSampleSize->Enable(false);
312 : }
313 0 : return 0;
314 228 : }
315 :
316 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|