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 <StatisticsInputOutputDialog.hxx>
21 ScRangeList
ScStatisticsInputOutputDialog::MakeColumnRangeList(SCTAB aTab
, ScAddress
const & aStart
, ScAddress
const & aEnd
)
23 ScRangeList aRangeList
;
24 for (SCCOL inCol
= aStart
.Col(); inCol
<= aEnd
.Col(); inCol
++)
26 ScRange
aColumnRange (
27 ScAddress(inCol
, aStart
.Row(), aTab
),
28 ScAddress(inCol
, aEnd
.Row(), aTab
) );
30 aRangeList
.push_back(aColumnRange
);
35 ScRangeList
ScStatisticsInputOutputDialog::MakeRowRangeList(SCTAB aTab
, ScAddress
const & aStart
, ScAddress
const & aEnd
)
37 ScRangeList aRangeList
;
38 for (SCROW inRow
= aStart
.Row(); inRow
<= aEnd
.Row(); inRow
++)
41 ScAddress(aStart
.Col(), inRow
, aTab
),
42 ScAddress(aEnd
.Col(), inRow
, aTab
) );
44 aRangeList
.push_back(aRowRange
);
49 ScStatisticsInputOutputDialog::ScStatisticsInputOutputDialog(
50 SfxBindings
* pSfxBindings
, SfxChildWindow
* pChildWindow
,
51 weld::Window
* pParent
, ScViewData
& rViewData
, const OUString
& rUIXMLDescription
, const OUString
& rID
)
52 : ScAnyRefDlgController(pSfxBindings
, pChildWindow
, pParent
, rUIXMLDescription
, rID
)
53 , mxInputRangeLabel(m_xBuilder
->weld_label(u
"input-range-label"_ustr
))
54 , mxInputRangeEdit(new formula::RefEdit(m_xBuilder
->weld_entry(u
"input-range-edit"_ustr
)))
55 , mxInputRangeButton(new formula::RefButton(m_xBuilder
->weld_button(u
"input-range-button"_ustr
)))
56 , mxOutputRangeLabel(m_xBuilder
->weld_label(u
"output-range-label"_ustr
))
57 , mxOutputRangeEdit(new formula::RefEdit(m_xBuilder
->weld_entry(u
"output-range-edit"_ustr
)))
58 , mxOutputRangeButton(new formula::RefButton(m_xBuilder
->weld_button(u
"output-range-button"_ustr
)))
59 , mxGroupByColumnsRadio(m_xBuilder
->weld_radio_button(u
"groupedby-columns-radio"_ustr
))
60 , mxGroupByRowsRadio(m_xBuilder
->weld_radio_button(u
"groupedby-rows-radio"_ustr
))
61 , mViewData(rViewData
)
62 , mDocument(rViewData
.GetDocument())
63 , mInputRange(ScAddress::INITIALIZE_INVALID
)
64 , mAddressDetails(mDocument
.GetAddressConvention(), 0, 0)
65 , mOutputAddress(ScAddress::INITIALIZE_INVALID
)
66 , mGroupedBy(BY_COLUMN
)
67 , mxButtonOk(m_xBuilder
->weld_button(u
"ok"_ustr
))
68 , mxButtonCancel(m_xBuilder
->weld_button(u
"cancel"_ustr
))
69 , mpActiveEdit(nullptr)
70 , mCurrentAddress(rViewData
.GetCurX(), rViewData
.GetCurY(), rViewData
.GetTabNo())
71 , mDialogLostFocus(false)
73 mxInputRangeEdit
->SetReferences(this, mxInputRangeLabel
.get());
74 mxInputRangeButton
->SetReferences(this, mxInputRangeEdit
.get());
76 mxOutputRangeEdit
->SetReferences(this, mxOutputRangeLabel
.get());
77 mxOutputRangeButton
->SetReferences(this, mxOutputRangeEdit
.get());
80 GetRangeFromSelection();
83 ScStatisticsInputOutputDialog::~ScStatisticsInputOutputDialog()
87 void ScStatisticsInputOutputDialog::Init()
89 mxButtonCancel
->connect_clicked( LINK( this, ScStatisticsInputOutputDialog
, ButtonClicked
) );
90 mxButtonOk
->connect_clicked( LINK( this, ScStatisticsInputOutputDialog
, ButtonClicked
) );
91 mxButtonOk
->set_sensitive(false);
93 Link
<formula::RefEdit
&,void> aEditLink
= LINK( this, ScStatisticsInputOutputDialog
, GetEditFocusHandler
);
94 mxInputRangeEdit
->SetGetFocusHdl( aEditLink
);
95 mxOutputRangeEdit
->SetGetFocusHdl( aEditLink
);
96 Link
<formula::RefButton
&,void> aButtonLink
= LINK( this, ScStatisticsInputOutputDialog
, GetButtonFocusHandler
);
97 mxInputRangeButton
->SetGetFocusHdl( aButtonLink
);
98 mxOutputRangeButton
->SetGetFocusHdl( aButtonLink
);
100 aEditLink
= LINK( this, ScStatisticsInputOutputDialog
, LoseEditFocusHandler
);
101 mxInputRangeEdit
->SetLoseFocusHdl( aEditLink
);
102 mxOutputRangeEdit
->SetLoseFocusHdl( aEditLink
);
103 aButtonLink
= LINK( this, ScStatisticsInputOutputDialog
, LoseButtonFocusHandler
);
104 mxInputRangeButton
->SetLoseFocusHdl( aButtonLink
);
105 mxOutputRangeButton
->SetLoseFocusHdl( aButtonLink
);
107 Link
<formula::RefEdit
&,void> aLink2
= LINK( this, ScStatisticsInputOutputDialog
, RefInputModifyHandler
);
108 mxInputRangeEdit
->SetModifyHdl( aLink2
);
109 mxOutputRangeEdit
->SetModifyHdl( aLink2
);
111 mxOutputRangeEdit
->GrabFocus();
113 mxGroupByColumnsRadio
->connect_toggled( LINK( this, ScStatisticsInputOutputDialog
, GroupByChanged
) );
114 mxGroupByRowsRadio
->connect_toggled( LINK( this, ScStatisticsInputOutputDialog
, GroupByChanged
) );
116 mxGroupByColumnsRadio
->set_active(true);
117 mxGroupByRowsRadio
->set_active(false);
120 void ScStatisticsInputOutputDialog::GetRangeFromSelection()
122 mViewData
.GetSimpleArea(mInputRange
);
123 OUString
aCurrentString(mInputRange
.Format(mDocument
, ScRefFlags::RANGE_ABS_3D
, mAddressDetails
));
124 mxInputRangeEdit
->SetText(aCurrentString
);
127 void ScStatisticsInputOutputDialog::SetActive()
129 if ( mDialogLostFocus
)
131 mDialogLostFocus
= false;
133 mpActiveEdit
->GrabFocus();
137 m_xDialog
->grab_focus();
142 void ScStatisticsInputOutputDialog::SetReference( const ScRange
& rReferenceRange
, ScDocument
& rDocument
)
146 if ( rReferenceRange
.aStart
!= rReferenceRange
.aEnd
)
147 RefInputStart( mpActiveEdit
);
149 OUString aReferenceString
;
151 if (mpActiveEdit
== mxInputRangeEdit
.get())
153 mInputRange
= rReferenceRange
;
154 aReferenceString
= mInputRange
.Format(rDocument
, ScRefFlags::RANGE_ABS_3D
, mAddressDetails
);
155 mxInputRangeEdit
->SetRefString( aReferenceString
);
157 else if (mpActiveEdit
== mxOutputRangeEdit
.get())
159 mOutputAddress
= rReferenceRange
.aStart
;
161 ScRefFlags nFormat
= ( mOutputAddress
.Tab() == mCurrentAddress
.Tab() ) ?
162 ScRefFlags::ADDR_ABS
:
163 ScRefFlags::ADDR_ABS_3D
;
164 aReferenceString
= mOutputAddress
.Format(nFormat
, &rDocument
, rDocument
.GetAddressConvention());
165 mxOutputRangeEdit
->SetRefString( aReferenceString
);
169 ValidateDialogInput();
172 IMPL_LINK( ScStatisticsInputOutputDialog
, ButtonClicked
, weld::Button
&, rButton
, void )
174 if (&rButton
== mxButtonOk
.get())
176 CalculateInputAndWriteToOutput();
180 response(RET_CANCEL
);
183 IMPL_LINK(ScStatisticsInputOutputDialog
, GetEditFocusHandler
, formula::RefEdit
&, rCtrl
, void)
185 mpActiveEdit
= nullptr;
187 if (&rCtrl
== mxInputRangeEdit
.get())
188 mpActiveEdit
= mxInputRangeEdit
.get();
189 if (&rCtrl
== mxOutputRangeEdit
.get())
190 mpActiveEdit
= mxOutputRangeEdit
.get();
193 mpActiveEdit
->SelectAll();
196 IMPL_LINK(ScStatisticsInputOutputDialog
, GetButtonFocusHandler
, formula::RefButton
&, rCtrl
, void)
198 mpActiveEdit
= nullptr;
200 if (&rCtrl
== mxInputRangeButton
.get())
201 mpActiveEdit
= mxInputRangeEdit
.get();
202 else if (&rCtrl
== mxOutputRangeButton
.get())
203 mpActiveEdit
= mxOutputRangeEdit
.get();
206 mpActiveEdit
->SelectAll();
209 IMPL_LINK_NOARG(ScStatisticsInputOutputDialog
, LoseEditFocusHandler
, formula::RefEdit
&, void)
211 mDialogLostFocus
= !m_xDialog
->has_toplevel_focus();
214 IMPL_LINK_NOARG(ScStatisticsInputOutputDialog
, LoseButtonFocusHandler
, formula::RefButton
&, void)
216 mDialogLostFocus
= !m_xDialog
->has_toplevel_focus();
219 IMPL_LINK_NOARG( ScStatisticsInputOutputDialog
, GroupByChanged
, weld::Toggleable
&, void )
221 if (mxGroupByColumnsRadio
->get_active())
222 mGroupedBy
= BY_COLUMN
;
223 else if (mxGroupByRowsRadio
->get_active())
226 ValidateDialogInput();
229 IMPL_LINK_NOARG( ScStatisticsInputOutputDialog
, RefInputModifyHandler
, formula::RefEdit
&, void )
233 if (mpActiveEdit
== mxInputRangeEdit
.get())
235 ScRangeList aRangeList
;
236 bool bValid
= ParseWithNames( aRangeList
, mxInputRangeEdit
->GetText(), mDocument
);
237 const ScRange
* pRange
= (bValid
&& aRangeList
.size() == 1) ? &aRangeList
[0] : nullptr;
240 mInputRange
= *pRange
;
241 // Highlight the resulting range.
242 mxInputRangeEdit
->StartUpdateData();
246 mInputRange
= ScRange( ScAddress::INITIALIZE_INVALID
);
249 else if (mpActiveEdit
== mxOutputRangeEdit
.get())
251 ScRangeList aRangeList
;
252 bool bValid
= ParseWithNames( aRangeList
, mxOutputRangeEdit
->GetText(), mDocument
);
253 const ScRange
* pRange
= (bValid
&& aRangeList
.size() == 1) ? &aRangeList
[0] : nullptr;
256 mOutputAddress
= pRange
->aStart
;
258 // Crop output range to top left address for Edit field.
259 if (pRange
->aStart
!= pRange
->aEnd
)
261 ScRefFlags nFormat
= ( mOutputAddress
.Tab() == mCurrentAddress
.Tab() ) ?
262 ScRefFlags::ADDR_ABS
:
263 ScRefFlags::ADDR_ABS_3D
;
264 OUString aReferenceString
= mOutputAddress
.Format(nFormat
, &mDocument
, mDocument
.GetAddressConvention());
265 mxOutputRangeEdit
->SetRefString( aReferenceString
);
268 // Highlight the resulting range.
269 mxOutputRangeEdit
->StartUpdateData();
273 mOutputAddress
= ScAddress( ScAddress::INITIALIZE_INVALID
);
278 ValidateDialogInput();
281 void ScStatisticsInputOutputDialog::CalculateInputAndWriteToOutput()
283 OUString
aUndo(ScResId(GetUndoNameId()));
284 ScDocShell
* pDocShell
= mViewData
.GetDocShell();
285 SfxUndoManager
* pUndoManager
= pDocShell
->GetUndoManager();
286 pUndoManager
->EnterListAction( aUndo
, aUndo
, 0, mViewData
.GetViewShell()->GetViewShellId() );
288 ScRange aOutputRange
= ApplyOutput(pDocShell
);
290 pUndoManager
->LeaveListAction();
291 pDocShell
->PostPaint( aOutputRange
, PaintPartFlags::Grid
);
294 bool ScStatisticsInputOutputDialog::InputRangesValid()
296 return mInputRange
.IsValid() && mOutputAddress
.IsValid();
299 void ScStatisticsInputOutputDialog::ValidateDialogInput()
301 // Enable OK button if all inputs are ok.
302 mxButtonOk
->set_sensitive(InputRangesValid());
305 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */