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