1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
11 #include <svl/undo.hxx>
13 #include <rangelst.hxx>
15 #include <document.hxx>
16 #include <scresid.hxx>
17 #include <tabvwsh.hxx>
19 #include <StatisticsTwoVariableDialog.hxx>
21 ScStatisticsTwoVariableDialog::ScStatisticsTwoVariableDialog(
22 SfxBindings
* pSfxBindings
, SfxChildWindow
* pChildWindow
,
23 weld::Window
* pParent
, ScViewData
& rViewData
, const OUString
& rUIXMLDescription
, const OUString
& rID
)
24 : ScAnyRefDlgController(pSfxBindings
, pChildWindow
, pParent
, rUIXMLDescription
, rID
)
25 , mxVariable1RangeLabel(m_xBuilder
->weld_label(u
"variable1-range-label"_ustr
))
26 , mxVariable1RangeEdit(new formula::RefEdit(m_xBuilder
->weld_entry(u
"variable1-range-edit"_ustr
)))
27 , mxVariable1RangeButton(new formula::RefButton(m_xBuilder
->weld_button(u
"variable1-range-button"_ustr
)))
28 , mxVariable2RangeLabel(m_xBuilder
->weld_label(u
"variable2-range-label"_ustr
))
29 , mxVariable2RangeEdit(new formula::RefEdit(m_xBuilder
->weld_entry(u
"variable2-range-edit"_ustr
)))
30 , mxVariable2RangeButton(new formula::RefButton(m_xBuilder
->weld_button(u
"variable2-range-button"_ustr
)))
31 , mxOutputRangeLabel(m_xBuilder
->weld_label(u
"output-range-label"_ustr
))
32 , mxOutputRangeEdit(new formula::RefEdit(m_xBuilder
->weld_entry(u
"output-range-edit"_ustr
)))
33 , mxOutputRangeButton(new formula::RefButton(m_xBuilder
->weld_button(u
"output-range-button"_ustr
)))
34 , mViewData(rViewData
)
35 , mDocument(rViewData
.GetDocument())
36 , mVariable1Range(ScAddress::INITIALIZE_INVALID
)
37 , mVariable2Range(ScAddress::INITIALIZE_INVALID
)
38 , mAddressDetails(mDocument
.GetAddressConvention(), 0, 0 )
39 , mOutputAddress(ScAddress::INITIALIZE_INVALID
)
40 , mGroupedBy(BY_COLUMN
)
41 , mxButtonOk(m_xBuilder
->weld_button(u
"ok"_ustr
))
42 , mxButtonCancel(m_xBuilder
->weld_button(u
"cancel"_ustr
))
43 , mxGroupByColumnsRadio(m_xBuilder
->weld_radio_button(u
"groupedby-columns-radio"_ustr
))
44 , mxGroupByRowsRadio(m_xBuilder
->weld_radio_button(u
"groupedby-rows-radio"_ustr
))
45 , mpActiveEdit(nullptr)
46 , mCurrentAddress(rViewData
.GetCurX(), rViewData
.GetCurY(), rViewData
.GetTabNo() )
47 , mDialogLostFocus(false)
49 mxVariable1RangeEdit
->SetReferences(this, mxVariable1RangeLabel
.get());
50 mxVariable1RangeButton
->SetReferences(this, mxVariable1RangeEdit
.get());
52 mxVariable2RangeEdit
->SetReferences(this, mxVariable2RangeLabel
.get());
53 mxVariable2RangeButton
->SetReferences(this, mxVariable2RangeEdit
.get());
55 mxOutputRangeEdit
->SetReferences(this, mxOutputRangeLabel
.get());
56 mxOutputRangeButton
->SetReferences(this, mxOutputRangeEdit
.get());
59 GetRangeFromSelection();
62 ScStatisticsTwoVariableDialog::~ScStatisticsTwoVariableDialog()
66 void ScStatisticsTwoVariableDialog::Init()
68 mxButtonCancel
->connect_clicked( LINK( this, ScStatisticsTwoVariableDialog
, ButtonClicked
) );
69 mxButtonOk
->connect_clicked( LINK( this, ScStatisticsTwoVariableDialog
, ButtonClicked
) );
70 mxButtonOk
->set_sensitive(false);
72 Link
<formula::RefEdit
&,void> aEditLink
= LINK( this, ScStatisticsTwoVariableDialog
, GetEditFocusHandler
);
73 mxVariable1RangeEdit
->SetGetFocusHdl( aEditLink
);
74 mxVariable2RangeEdit
->SetGetFocusHdl( aEditLink
);
75 mxOutputRangeEdit
->SetGetFocusHdl( aEditLink
);
77 Link
<formula::RefButton
&,void> aButtonLink
= LINK( this, ScStatisticsTwoVariableDialog
, GetButtonFocusHandler
);
78 mxVariable1RangeButton
->SetGetFocusHdl( aButtonLink
);
79 mxVariable2RangeButton
->SetGetFocusHdl( aButtonLink
);
80 mxOutputRangeButton
->SetGetFocusHdl( aButtonLink
);
82 aEditLink
= LINK( this, ScStatisticsTwoVariableDialog
, LoseEditFocusHandler
);
83 mxVariable1RangeEdit
->SetLoseFocusHdl( aEditLink
);
84 mxVariable2RangeEdit
->SetLoseFocusHdl( aEditLink
);
85 mxOutputRangeEdit
->SetLoseFocusHdl( aEditLink
);
87 aButtonLink
= LINK( this, ScStatisticsTwoVariableDialog
, LoseButtonFocusHandler
);
88 mxVariable1RangeButton
->SetLoseFocusHdl( aButtonLink
);
89 mxVariable2RangeButton
->SetLoseFocusHdl( aButtonLink
);
90 mxOutputRangeButton
->SetLoseFocusHdl( aButtonLink
);
92 Link
<formula::RefEdit
&,void> aLink2
= LINK( this, ScStatisticsTwoVariableDialog
, RefInputModifyHandler
);
93 mxVariable1RangeEdit
->SetModifyHdl( aLink2
);
94 mxVariable2RangeEdit
->SetModifyHdl( aLink2
);
95 mxOutputRangeEdit
->SetModifyHdl( aLink2
);
97 mxOutputRangeEdit
->GrabFocus();
99 mxGroupByColumnsRadio
->connect_toggled( LINK( this, ScStatisticsTwoVariableDialog
, GroupByChanged
) );
100 mxGroupByRowsRadio
->connect_toggled( LINK( this, ScStatisticsTwoVariableDialog
, GroupByChanged
) );
102 mxGroupByColumnsRadio
->set_active(true);
103 mxGroupByRowsRadio
->set_active(false);
106 void ScStatisticsTwoVariableDialog::GetRangeFromSelection()
108 OUString aCurrentString
;
110 ScRange aCurrentRange
;
111 mViewData
.GetSimpleArea(aCurrentRange
);
113 if (aCurrentRange
.aEnd
.Col() - aCurrentRange
.aStart
.Col() == 1)
115 mVariable1Range
= aCurrentRange
;
116 mVariable1Range
.aEnd
.SetCol(mVariable1Range
.aStart
.Col());
117 aCurrentString
= mVariable1Range
.Format(mDocument
, ScRefFlags::RANGE_ABS_3D
, mAddressDetails
);
118 mxVariable1RangeEdit
->SetText(aCurrentString
);
120 mVariable2Range
= aCurrentRange
;
121 mVariable2Range
.aStart
.SetCol(mVariable2Range
.aEnd
.Col());
122 aCurrentString
= mVariable2Range
.Format(mDocument
, ScRefFlags::RANGE_ABS_3D
, mAddressDetails
);
123 mxVariable2RangeEdit
->SetText(aCurrentString
);
127 mVariable1Range
= aCurrentRange
;
128 aCurrentString
= mVariable1Range
.Format(mDocument
, ScRefFlags::RANGE_ABS_3D
, mAddressDetails
);
129 mxVariable1RangeEdit
->SetText(aCurrentString
);
133 void ScStatisticsTwoVariableDialog::SetActive()
135 if ( mDialogLostFocus
)
137 mDialogLostFocus
= false;
139 mpActiveEdit
->GrabFocus();
143 m_xDialog
->grab_focus();
148 void ScStatisticsTwoVariableDialog::SetReference( const ScRange
& rReferenceRange
, ScDocument
& rDocument
)
150 if ( mpActiveEdit
!= nullptr )
152 if ( rReferenceRange
.aStart
!= rReferenceRange
.aEnd
)
153 RefInputStart( mpActiveEdit
);
155 OUString aReferenceString
;
157 if ( mpActiveEdit
== mxVariable1RangeEdit
.get() )
159 mVariable1Range
= rReferenceRange
;
160 aReferenceString
= mVariable1Range
.Format(rDocument
, ScRefFlags::RANGE_ABS_3D
, mAddressDetails
);
161 mxVariable1RangeEdit
->SetRefString(aReferenceString
);
163 else if ( mpActiveEdit
== mxVariable2RangeEdit
.get() )
165 mVariable2Range
= rReferenceRange
;
166 aReferenceString
= mVariable2Range
.Format(rDocument
, ScRefFlags::RANGE_ABS_3D
, mAddressDetails
);
167 mxVariable2RangeEdit
->SetRefString(aReferenceString
);
169 else if ( mpActiveEdit
== mxOutputRangeEdit
.get() )
171 mOutputAddress
= rReferenceRange
.aStart
;
173 ScRefFlags nFormat
= ( mOutputAddress
.Tab() == mCurrentAddress
.Tab() ) ?
174 ScRefFlags::ADDR_ABS
:
175 ScRefFlags::ADDR_ABS_3D
;
176 aReferenceString
= mOutputAddress
.Format(nFormat
, &rDocument
, rDocument
.GetAddressConvention());
177 mxOutputRangeEdit
->SetRefString( aReferenceString
);
181 ValidateDialogInput();
184 IMPL_LINK( ScStatisticsTwoVariableDialog
, ButtonClicked
, weld::Button
&, rButton
, void )
186 if (&rButton
== mxButtonOk
.get())
188 CalculateInputAndWriteToOutput();
192 response(RET_CANCEL
);
195 IMPL_LINK(ScStatisticsTwoVariableDialog
, GetEditFocusHandler
, formula::RefEdit
&, rCtrl
, void)
197 mpActiveEdit
= nullptr;
198 if (&rCtrl
== mxVariable1RangeEdit
.get())
200 mpActiveEdit
= mxVariable1RangeEdit
.get();
202 else if (&rCtrl
== mxVariable2RangeEdit
.get())
204 mpActiveEdit
= mxVariable2RangeEdit
.get();
206 else if (&rCtrl
== mxOutputRangeEdit
.get())
208 mpActiveEdit
= mxOutputRangeEdit
.get();
212 mpActiveEdit
->SelectAll();
215 IMPL_LINK( ScStatisticsTwoVariableDialog
, GetButtonFocusHandler
, formula::RefButton
&, rCtrl
, void )
217 mpActiveEdit
= nullptr;
218 if (&rCtrl
== mxVariable1RangeButton
.get())
220 mpActiveEdit
= mxVariable1RangeEdit
.get();
222 else if (&rCtrl
== mxVariable2RangeButton
.get())
224 mpActiveEdit
= mxVariable2RangeEdit
.get();
226 else if (&rCtrl
== mxOutputRangeButton
.get())
228 mpActiveEdit
= mxOutputRangeEdit
.get();
232 mpActiveEdit
->SelectAll();
235 IMPL_LINK_NOARG( ScStatisticsTwoVariableDialog
, LoseEditFocusHandler
, formula::RefEdit
&, void )
237 mDialogLostFocus
= !m_xDialog
->has_toplevel_focus();
240 IMPL_LINK_NOARG( ScStatisticsTwoVariableDialog
, LoseButtonFocusHandler
, formula::RefButton
&, void )
242 mDialogLostFocus
= !m_xDialog
->has_toplevel_focus();
245 IMPL_LINK_NOARG(ScStatisticsTwoVariableDialog
, GroupByChanged
, weld::Toggleable
&, void)
247 if (mxGroupByColumnsRadio
->get_active())
248 mGroupedBy
= BY_COLUMN
;
249 else if (mxGroupByRowsRadio
->get_active())
252 ValidateDialogInput();
255 IMPL_LINK_NOARG( ScStatisticsTwoVariableDialog
, RefInputModifyHandler
, formula::RefEdit
&, void )
259 if (mpActiveEdit
== mxVariable1RangeEdit
.get())
261 ScRangeList aRangeList
;
262 bool bValid
= ParseWithNames( aRangeList
, mxVariable1RangeEdit
->GetText(), mDocument
);
263 const ScRange
* pRange
= (bValid
&& aRangeList
.size() == 1) ? &aRangeList
[0] : nullptr;
266 mVariable1Range
= *pRange
;
267 // Highlight the resulting range.
268 mxVariable1RangeEdit
->StartUpdateData();
272 mVariable1Range
= ScRange( ScAddress::INITIALIZE_INVALID
);
275 else if ( mpActiveEdit
== mxVariable2RangeEdit
.get() )
277 ScRangeList aRangeList
;
278 bool bValid
= ParseWithNames( aRangeList
, mxVariable2RangeEdit
->GetText(), mDocument
);
279 const ScRange
* pRange
= (bValid
&& aRangeList
.size() == 1) ? &aRangeList
[0] : nullptr;
282 mVariable2Range
= *pRange
;
283 // Highlight the resulting range.
284 mxVariable2RangeEdit
->StartUpdateData();
288 mVariable2Range
= ScRange( ScAddress::INITIALIZE_INVALID
);
291 else if ( mpActiveEdit
== mxOutputRangeEdit
.get() )
293 ScRangeList aRangeList
;
294 bool bValid
= ParseWithNames( aRangeList
, mxOutputRangeEdit
->GetText(), mDocument
);
295 const ScRange
* pRange
= (bValid
&& aRangeList
.size() == 1) ? &aRangeList
[0] : nullptr;
298 mOutputAddress
= pRange
->aStart
;
300 // Crop output range to top left address for Edit field.
301 if (pRange
->aStart
!= pRange
->aEnd
)
303 ScRefFlags nFormat
= ( mOutputAddress
.Tab() == mCurrentAddress
.Tab() ) ?
304 ScRefFlags::ADDR_ABS
:
305 ScRefFlags::ADDR_ABS_3D
;
306 OUString aReferenceString
= mOutputAddress
.Format(nFormat
, &mDocument
, mDocument
.GetAddressConvention());
307 mxOutputRangeEdit
->SetRefString( aReferenceString
);
310 // Highlight the resulting range.
311 mxOutputRangeEdit
->StartUpdateData();
315 mOutputAddress
= ScAddress( ScAddress::INITIALIZE_INVALID
);
320 ValidateDialogInput();
323 void ScStatisticsTwoVariableDialog::CalculateInputAndWriteToOutput()
325 OUString
aUndo(ScResId(GetUndoNameId()));
326 ScDocShell
* pDocShell
= mViewData
.GetDocShell();
327 SfxUndoManager
* pUndoManager
= pDocShell
->GetUndoManager();
328 pUndoManager
->EnterListAction( aUndo
, aUndo
, 0, mViewData
.GetViewShell()->GetViewShellId() );
330 ScRange aOutputRange
= ApplyOutput(pDocShell
);
332 pUndoManager
->LeaveListAction();
333 pDocShell
->PostPaint( aOutputRange
, PaintPartFlags::Grid
);
336 bool ScStatisticsTwoVariableDialog::InputRangesValid()
338 return mVariable1Range
.IsValid() && mVariable2Range
.IsValid() && mOutputAddress
.IsValid();
341 void ScStatisticsTwoVariableDialog::ValidateDialogInput()
343 // Enable OK button if all inputs are ok.
344 mxButtonOk
->set_sensitive(InputRangesValid());
347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */