/src/libreoffice/sc/source/ui/StatisticsDialogs/StatisticsTwoVariableDialog.cxx
Line | Count | Source |
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 <svl/undo.hxx> |
12 | | |
13 | | #include <rangelst.hxx> |
14 | | #include <docsh.hxx> |
15 | | #include <document.hxx> |
16 | | #include <scresid.hxx> |
17 | | #include <tabvwsh.hxx> |
18 | | |
19 | | #include <StatisticsTwoVariableDialog.hxx> |
20 | | |
21 | | ScStatisticsTwoVariableDialog::ScStatisticsTwoVariableDialog( |
22 | | SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow, |
23 | | weld::Window* pParent, ScViewData& rViewData, const OUString& rUIXMLDescription, const OUString& rID) |
24 | 0 | : ScAnyRefDlgController(pSfxBindings, pChildWindow, pParent, rUIXMLDescription, rID) |
25 | 0 | , mxVariable1RangeLabel(m_xBuilder->weld_label(u"variable1-range-label"_ustr)) |
26 | 0 | , mxVariable1RangeEdit(new formula::RefEdit(m_xBuilder->weld_entry(u"variable1-range-edit"_ustr))) |
27 | 0 | , mxVariable1RangeButton(new formula::RefButton(m_xBuilder->weld_button(u"variable1-range-button"_ustr))) |
28 | 0 | , mxVariable2RangeLabel(m_xBuilder->weld_label(u"variable2-range-label"_ustr)) |
29 | 0 | , mxVariable2RangeEdit(new formula::RefEdit(m_xBuilder->weld_entry(u"variable2-range-edit"_ustr))) |
30 | 0 | , mxVariable2RangeButton(new formula::RefButton(m_xBuilder->weld_button(u"variable2-range-button"_ustr))) |
31 | 0 | , mxOutputRangeLabel(m_xBuilder->weld_label(u"output-range-label"_ustr)) |
32 | 0 | , mxOutputRangeEdit(new formula::RefEdit(m_xBuilder->weld_entry(u"output-range-edit"_ustr))) |
33 | 0 | , mxOutputRangeButton(new formula::RefButton(m_xBuilder->weld_button(u"output-range-button"_ustr))) |
34 | 0 | , mViewData(rViewData) |
35 | 0 | , mDocument(rViewData.GetDocument()) |
36 | 0 | , mVariable1Range(ScAddress::INITIALIZE_INVALID) |
37 | 0 | , mVariable2Range(ScAddress::INITIALIZE_INVALID) |
38 | 0 | , mAddressDetails(mDocument.GetAddressConvention(), 0, 0 ) |
39 | 0 | , mOutputAddress(ScAddress::INITIALIZE_INVALID) |
40 | 0 | , mGroupedBy(GroupedBy::BY_COLUMN) |
41 | 0 | , mxButtonOk(m_xBuilder->weld_button(u"ok"_ustr)) |
42 | 0 | , mxButtonCancel(m_xBuilder->weld_button(u"cancel"_ustr)) |
43 | 0 | , mxGroupByColumnsRadio(m_xBuilder->weld_radio_button(u"groupedby-columns-radio"_ustr)) |
44 | 0 | , mxGroupByRowsRadio(m_xBuilder->weld_radio_button(u"groupedby-rows-radio"_ustr)) |
45 | 0 | , mpActiveEdit(nullptr) |
46 | 0 | , mCurrentAddress(rViewData.GetCurX(), rViewData.GetCurY(), rViewData.CurrentTabForData() ) |
47 | 0 | , mDialogLostFocus(false) |
48 | 0 | { |
49 | 0 | mxVariable1RangeEdit->SetReferences(this, mxVariable1RangeLabel.get()); |
50 | 0 | mxVariable1RangeButton->SetReferences(this, mxVariable1RangeEdit.get()); |
51 | |
|
52 | 0 | mxVariable2RangeEdit->SetReferences(this, mxVariable2RangeLabel.get()); |
53 | 0 | mxVariable2RangeButton->SetReferences(this, mxVariable2RangeEdit.get()); |
54 | |
|
55 | 0 | mxOutputRangeEdit->SetReferences(this, mxOutputRangeLabel.get()); |
56 | 0 | mxOutputRangeButton->SetReferences(this, mxOutputRangeEdit.get()); |
57 | |
|
58 | 0 | Init(); |
59 | 0 | GetRangeFromSelection(); |
60 | 0 | } |
61 | | |
62 | | ScStatisticsTwoVariableDialog::~ScStatisticsTwoVariableDialog() |
63 | 0 | { |
64 | 0 | } |
65 | | |
66 | | void ScStatisticsTwoVariableDialog::Init() |
67 | 0 | { |
68 | 0 | mxButtonCancel->connect_clicked( LINK( this, ScStatisticsTwoVariableDialog, ButtonClicked ) ); |
69 | 0 | mxButtonOk->connect_clicked( LINK( this, ScStatisticsTwoVariableDialog, ButtonClicked ) ); |
70 | 0 | mxButtonOk->set_sensitive(false); |
71 | |
|
72 | 0 | Link<formula::RefEdit&,void> aEditLink = LINK( this, ScStatisticsTwoVariableDialog, GetEditFocusHandler ); |
73 | 0 | mxVariable1RangeEdit->SetGetFocusHdl( aEditLink ); |
74 | 0 | mxVariable2RangeEdit->SetGetFocusHdl( aEditLink ); |
75 | 0 | mxOutputRangeEdit->SetGetFocusHdl( aEditLink ); |
76 | |
|
77 | 0 | Link<formula::RefButton&,void> aButtonLink = LINK( this, ScStatisticsTwoVariableDialog, GetButtonFocusHandler ); |
78 | 0 | mxVariable1RangeButton->SetGetFocusHdl( aButtonLink ); |
79 | 0 | mxVariable2RangeButton->SetGetFocusHdl( aButtonLink ); |
80 | 0 | mxOutputRangeButton->SetGetFocusHdl( aButtonLink ); |
81 | |
|
82 | 0 | aEditLink = LINK( this, ScStatisticsTwoVariableDialog, LoseEditFocusHandler ); |
83 | 0 | mxVariable1RangeEdit->SetLoseFocusHdl( aEditLink ); |
84 | 0 | mxVariable2RangeEdit->SetLoseFocusHdl( aEditLink ); |
85 | 0 | mxOutputRangeEdit->SetLoseFocusHdl( aEditLink ); |
86 | |
|
87 | 0 | aButtonLink = LINK( this, ScStatisticsTwoVariableDialog, LoseButtonFocusHandler ); |
88 | 0 | mxVariable1RangeButton->SetLoseFocusHdl( aButtonLink ); |
89 | 0 | mxVariable2RangeButton->SetLoseFocusHdl( aButtonLink ); |
90 | 0 | mxOutputRangeButton->SetLoseFocusHdl( aButtonLink ); |
91 | |
|
92 | 0 | Link<formula::RefEdit&,void> aLink2 = LINK( this, ScStatisticsTwoVariableDialog, RefInputModifyHandler); |
93 | 0 | mxVariable1RangeEdit->SetModifyHdl( aLink2); |
94 | 0 | mxVariable2RangeEdit->SetModifyHdl( aLink2); |
95 | 0 | mxOutputRangeEdit->SetModifyHdl( aLink2); |
96 | |
|
97 | 0 | mxOutputRangeEdit->GrabFocus(); |
98 | |
|
99 | 0 | mxGroupByColumnsRadio->connect_toggled( LINK( this, ScStatisticsTwoVariableDialog, GroupByChanged ) ); |
100 | 0 | mxGroupByRowsRadio->connect_toggled( LINK( this, ScStatisticsTwoVariableDialog, GroupByChanged ) ); |
101 | |
|
102 | 0 | mxGroupByColumnsRadio->set_active(true); |
103 | 0 | mxGroupByRowsRadio->set_active(false); |
104 | 0 | } |
105 | | |
106 | | void ScStatisticsTwoVariableDialog::GetRangeFromSelection() |
107 | 0 | { |
108 | 0 | OUString aCurrentString; |
109 | |
|
110 | 0 | ScRange aCurrentRange; |
111 | 0 | mViewData.GetSimpleArea(aCurrentRange); |
112 | |
|
113 | 0 | if (aCurrentRange.aEnd.Col() - aCurrentRange.aStart.Col() == 1) |
114 | 0 | { |
115 | 0 | mVariable1Range = aCurrentRange; |
116 | 0 | mVariable1Range.aEnd.SetCol(mVariable1Range.aStart.Col()); |
117 | 0 | aCurrentString = mVariable1Range.Format(mDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails); |
118 | 0 | mxVariable1RangeEdit->SetText(aCurrentString); |
119 | |
|
120 | 0 | mVariable2Range = aCurrentRange; |
121 | 0 | mVariable2Range.aStart.SetCol(mVariable2Range.aEnd.Col()); |
122 | 0 | aCurrentString = mVariable2Range.Format(mDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails); |
123 | 0 | mxVariable2RangeEdit->SetText(aCurrentString); |
124 | 0 | } |
125 | 0 | else |
126 | 0 | { |
127 | 0 | mVariable1Range = aCurrentRange; |
128 | 0 | aCurrentString = mVariable1Range.Format(mDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails); |
129 | 0 | mxVariable1RangeEdit->SetText(aCurrentString); |
130 | 0 | } |
131 | 0 | } |
132 | | |
133 | | void ScStatisticsTwoVariableDialog::SetActive() |
134 | 0 | { |
135 | 0 | if ( mDialogLostFocus ) |
136 | 0 | { |
137 | 0 | mDialogLostFocus = false; |
138 | 0 | if( mpActiveEdit ) |
139 | 0 | mpActiveEdit->GrabFocus(); |
140 | 0 | } |
141 | 0 | else |
142 | 0 | { |
143 | 0 | m_xDialog->grab_focus(); |
144 | 0 | } |
145 | 0 | RefInputDone(); |
146 | 0 | } |
147 | | |
148 | | void ScStatisticsTwoVariableDialog::SetReference( const ScRange& rReferenceRange, ScDocument& rDocument ) |
149 | 0 | { |
150 | 0 | if ( mpActiveEdit != nullptr ) |
151 | 0 | { |
152 | 0 | if ( rReferenceRange.aStart != rReferenceRange.aEnd ) |
153 | 0 | RefInputStart( mpActiveEdit ); |
154 | |
|
155 | 0 | OUString aReferenceString; |
156 | |
|
157 | 0 | if ( mpActiveEdit == mxVariable1RangeEdit.get() ) |
158 | 0 | { |
159 | 0 | mVariable1Range = rReferenceRange; |
160 | 0 | aReferenceString = mVariable1Range.Format(rDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails); |
161 | 0 | mxVariable1RangeEdit->SetRefString(aReferenceString); |
162 | 0 | } |
163 | 0 | else if ( mpActiveEdit == mxVariable2RangeEdit.get() ) |
164 | 0 | { |
165 | 0 | mVariable2Range = rReferenceRange; |
166 | 0 | aReferenceString = mVariable2Range.Format(rDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails); |
167 | 0 | mxVariable2RangeEdit->SetRefString(aReferenceString); |
168 | 0 | } |
169 | 0 | else if ( mpActiveEdit == mxOutputRangeEdit.get() ) |
170 | 0 | { |
171 | 0 | mOutputAddress = rReferenceRange.aStart; |
172 | |
|
173 | 0 | ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ? |
174 | 0 | ScRefFlags::ADDR_ABS : |
175 | 0 | ScRefFlags::ADDR_ABS_3D; |
176 | 0 | aReferenceString = mOutputAddress.Format(nFormat, &rDocument, rDocument.GetAddressConvention()); |
177 | 0 | mxOutputRangeEdit->SetRefString( aReferenceString ); |
178 | 0 | } |
179 | 0 | } |
180 | |
|
181 | 0 | ValidateDialogInput(); |
182 | 0 | } |
183 | | |
184 | | IMPL_LINK( ScStatisticsTwoVariableDialog, ButtonClicked, weld::Button&, rButton, void ) |
185 | 0 | { |
186 | 0 | if (&rButton == mxButtonOk.get()) |
187 | 0 | { |
188 | 0 | CalculateInputAndWriteToOutput(); |
189 | 0 | response(RET_OK); |
190 | 0 | } |
191 | 0 | else |
192 | 0 | response(RET_CANCEL); |
193 | 0 | } |
194 | | |
195 | | IMPL_LINK(ScStatisticsTwoVariableDialog, GetEditFocusHandler, formula::RefEdit&, rCtrl, void) |
196 | 0 | { |
197 | 0 | mpActiveEdit = nullptr; |
198 | 0 | if (&rCtrl == mxVariable1RangeEdit.get()) |
199 | 0 | { |
200 | 0 | mpActiveEdit = mxVariable1RangeEdit.get(); |
201 | 0 | } |
202 | 0 | else if (&rCtrl == mxVariable2RangeEdit.get()) |
203 | 0 | { |
204 | 0 | mpActiveEdit = mxVariable2RangeEdit.get(); |
205 | 0 | } |
206 | 0 | else if (&rCtrl == mxOutputRangeEdit.get()) |
207 | 0 | { |
208 | 0 | mpActiveEdit = mxOutputRangeEdit.get(); |
209 | 0 | } |
210 | |
|
211 | 0 | if( mpActiveEdit ) |
212 | 0 | mpActiveEdit->SelectAll(); |
213 | 0 | } |
214 | | |
215 | | IMPL_LINK( ScStatisticsTwoVariableDialog, GetButtonFocusHandler, formula::RefButton&, rCtrl, void ) |
216 | 0 | { |
217 | 0 | mpActiveEdit = nullptr; |
218 | 0 | if (&rCtrl == mxVariable1RangeButton.get()) |
219 | 0 | { |
220 | 0 | mpActiveEdit = mxVariable1RangeEdit.get(); |
221 | 0 | } |
222 | 0 | else if (&rCtrl == mxVariable2RangeButton.get()) |
223 | 0 | { |
224 | 0 | mpActiveEdit = mxVariable2RangeEdit.get(); |
225 | 0 | } |
226 | 0 | else if (&rCtrl == mxOutputRangeButton.get()) |
227 | 0 | { |
228 | 0 | mpActiveEdit = mxOutputRangeEdit.get(); |
229 | 0 | } |
230 | |
|
231 | 0 | if( mpActiveEdit ) |
232 | 0 | mpActiveEdit->SelectAll(); |
233 | 0 | } |
234 | | |
235 | | IMPL_LINK_NOARG( ScStatisticsTwoVariableDialog, LoseEditFocusHandler, formula::RefEdit&, void ) |
236 | 0 | { |
237 | 0 | mDialogLostFocus = !m_xDialog->has_toplevel_focus(); |
238 | 0 | } |
239 | | |
240 | | IMPL_LINK_NOARG( ScStatisticsTwoVariableDialog, LoseButtonFocusHandler, formula::RefButton&, void ) |
241 | 0 | { |
242 | 0 | mDialogLostFocus = !m_xDialog->has_toplevel_focus(); |
243 | 0 | } |
244 | | |
245 | | IMPL_LINK_NOARG(ScStatisticsTwoVariableDialog, GroupByChanged, weld::Toggleable&, void) |
246 | 0 | { |
247 | 0 | if (mxGroupByColumnsRadio->get_active()) |
248 | 0 | mGroupedBy = GroupedBy::BY_COLUMN; |
249 | 0 | else if (mxGroupByRowsRadio->get_active()) |
250 | 0 | mGroupedBy = GroupedBy::BY_ROW; |
251 | |
|
252 | 0 | ValidateDialogInput(); |
253 | 0 | } |
254 | | |
255 | | IMPL_LINK_NOARG( ScStatisticsTwoVariableDialog, RefInputModifyHandler, formula::RefEdit&, void ) |
256 | 0 | { |
257 | 0 | if ( mpActiveEdit ) |
258 | 0 | { |
259 | 0 | if (mpActiveEdit == mxVariable1RangeEdit.get()) |
260 | 0 | { |
261 | 0 | ScRangeList aRangeList; |
262 | 0 | bool bValid = ParseWithNames( aRangeList, mxVariable1RangeEdit->GetText(), mDocument); |
263 | 0 | const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr; |
264 | 0 | if (pRange) |
265 | 0 | { |
266 | 0 | mVariable1Range = *pRange; |
267 | | // Highlight the resulting range. |
268 | 0 | mxVariable1RangeEdit->StartUpdateData(); |
269 | 0 | } |
270 | 0 | else |
271 | 0 | { |
272 | 0 | mVariable1Range = ScRange( ScAddress::INITIALIZE_INVALID); |
273 | 0 | } |
274 | 0 | } |
275 | 0 | else if ( mpActiveEdit == mxVariable2RangeEdit.get() ) |
276 | 0 | { |
277 | 0 | ScRangeList aRangeList; |
278 | 0 | bool bValid = ParseWithNames( aRangeList, mxVariable2RangeEdit->GetText(), mDocument); |
279 | 0 | const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr; |
280 | 0 | if (pRange) |
281 | 0 | { |
282 | 0 | mVariable2Range = *pRange; |
283 | | // Highlight the resulting range. |
284 | 0 | mxVariable2RangeEdit->StartUpdateData(); |
285 | 0 | } |
286 | 0 | else |
287 | 0 | { |
288 | 0 | mVariable2Range = ScRange( ScAddress::INITIALIZE_INVALID); |
289 | 0 | } |
290 | 0 | } |
291 | 0 | else if ( mpActiveEdit == mxOutputRangeEdit.get() ) |
292 | 0 | { |
293 | 0 | ScRangeList aRangeList; |
294 | 0 | bool bValid = ParseWithNames( aRangeList, mxOutputRangeEdit->GetText(), mDocument); |
295 | 0 | const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr; |
296 | 0 | if (pRange) |
297 | 0 | { |
298 | 0 | mOutputAddress = pRange->aStart; |
299 | | |
300 | | // Crop output range to top left address for Edit field. |
301 | 0 | if (pRange->aStart != pRange->aEnd) |
302 | 0 | { |
303 | 0 | ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ? |
304 | 0 | ScRefFlags::ADDR_ABS : |
305 | 0 | ScRefFlags::ADDR_ABS_3D; |
306 | 0 | OUString aReferenceString = mOutputAddress.Format(nFormat, &mDocument, mDocument.GetAddressConvention()); |
307 | 0 | mxOutputRangeEdit->SetRefString( aReferenceString ); |
308 | 0 | } |
309 | | |
310 | | // Highlight the resulting range. |
311 | 0 | mxOutputRangeEdit->StartUpdateData(); |
312 | 0 | } |
313 | 0 | else |
314 | 0 | { |
315 | 0 | mOutputAddress = ScAddress( ScAddress::INITIALIZE_INVALID); |
316 | 0 | } |
317 | 0 | } |
318 | 0 | } |
319 | |
|
320 | 0 | ValidateDialogInput(); |
321 | 0 | } |
322 | | |
323 | | void ScStatisticsTwoVariableDialog::CalculateInputAndWriteToOutput() |
324 | 0 | { |
325 | 0 | OUString aUndo(ScResId(GetUndoNameId())); |
326 | 0 | ScDocShell& rDocShell = mViewData.GetDocShell(); |
327 | 0 | SfxUndoManager* pUndoManager = rDocShell.GetUndoManager(); |
328 | 0 | pUndoManager->EnterListAction( aUndo, aUndo, 0, mViewData.GetViewShell()->GetViewShellId() ); |
329 | |
|
330 | 0 | ScRange aOutputRange = ApplyOutput(rDocShell); |
331 | |
|
332 | 0 | pUndoManager->LeaveListAction(); |
333 | 0 | rDocShell.PostPaint( aOutputRange, PaintPartFlags::Grid ); |
334 | 0 | } |
335 | | |
336 | | bool ScStatisticsTwoVariableDialog::InputRangesValid() |
337 | 0 | { |
338 | 0 | return mVariable1Range.IsValid() && mVariable2Range.IsValid() && mOutputAddress.IsValid(); |
339 | 0 | } |
340 | | |
341 | | void ScStatisticsTwoVariableDialog::ValidateDialogInput() |
342 | 0 | { |
343 | | // Enable OK button if all inputs are ok. |
344 | 0 | mxButtonOk->set_sensitive(InputRangesValid()); |
345 | 0 | } |
346 | | |
347 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |