LibreOffice Module sc (master)  1
StatisticsInputOutputDialog.cxx
Go to the documentation of this file.
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 
20 
22 {
23  ScRangeList aRangeList;
24  for (SCCOL inCol = aStart.Col(); inCol <= aEnd.Col(); inCol++)
25  {
26  ScRange aColumnRange (
27  ScAddress(inCol, aStart.Row(), aTab),
28  ScAddress(inCol, aEnd.Row(), aTab) );
29 
30  aRangeList.push_back(aColumnRange);
31  }
32  return aRangeList;
33 }
34 
36 {
37  ScRangeList aRangeList;
38  for (SCROW inRow = aStart.Row(); inRow <= aEnd.Row(); inRow++)
39  {
40  ScRange aRowRange (
41  ScAddress(aStart.Col(), inRow, aTab),
42  ScAddress(aEnd.Col(), inRow, aTab) );
43 
44  aRangeList.push_back(aRowRange);
45  }
46  return aRangeList;
47 }
48 
50  SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
51  weld::Window* pParent, ScViewData& rViewData, const OUString& rUIXMLDescription, const OString& rID)
52  : ScAnyRefDlgController(pSfxBindings, pChildWindow, pParent, rUIXMLDescription, rID)
53  , mxInputRangeLabel(m_xBuilder->weld_label("input-range-label"))
54  , mxInputRangeEdit(new formula::RefEdit(m_xBuilder->weld_entry("input-range-edit")))
55  , mxInputRangeButton(new formula::RefButton(m_xBuilder->weld_button("input-range-button")))
56  , mxOutputRangeLabel(m_xBuilder->weld_label("output-range-label"))
57  , mxOutputRangeEdit(new formula::RefEdit(m_xBuilder->weld_entry("output-range-edit")))
58  , mxOutputRangeButton(new formula::RefButton(m_xBuilder->weld_button("output-range-button")))
59  , mxGroupByColumnsRadio(m_xBuilder->weld_radio_button("groupedby-columns-radio"))
60  , mxGroupByRowsRadio(m_xBuilder->weld_radio_button("groupedby-rows-radio"))
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("ok"))
68  , mxButtonCancel(m_xBuilder->weld_button("cancel"))
69  , mpActiveEdit(nullptr)
70  , mCurrentAddress(rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo())
71  , mDialogLostFocus(false)
72 {
73  mxInputRangeEdit->SetReferences(this, mxInputRangeLabel.get());
74  mxInputRangeButton->SetReferences(this, mxInputRangeEdit.get());
75 
76  mxOutputRangeEdit->SetReferences(this, mxOutputRangeLabel.get());
77  mxOutputRangeButton->SetReferences(this, mxOutputRangeEdit.get());
78 
79  Init();
81 }
82 
84 {
85 }
86 
88 {
89  mxButtonCancel->connect_clicked( LINK( this, ScStatisticsInputOutputDialog, ButtonClicked ) );
90  mxButtonOk->connect_clicked( LINK( this, ScStatisticsInputOutputDialog, ButtonClicked ) );
91  mxButtonOk->set_sensitive(false);
92 
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 );
99 
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 );
106 
107  Link<formula::RefEdit&,void> aLink2 = LINK( this, ScStatisticsInputOutputDialog, RefInputModifyHandler);
108  mxInputRangeEdit->SetModifyHdl( aLink2);
109  mxOutputRangeEdit->SetModifyHdl( aLink2);
110 
111  mxOutputRangeEdit->GrabFocus();
112 
113  mxGroupByColumnsRadio->connect_toggled( LINK( this, ScStatisticsInputOutputDialog, GroupByChanged ) );
114  mxGroupByRowsRadio->connect_toggled( LINK( this, ScStatisticsInputOutputDialog, GroupByChanged ) );
115 
116  mxGroupByColumnsRadio->set_active(true);
117  mxGroupByRowsRadio->set_active(false);
118 }
119 
121 {
124  mxInputRangeEdit->SetText(aCurrentString);
125 }
126 
128 {
129  if ( mDialogLostFocus )
130  {
131  mDialogLostFocus = false;
132  if( mpActiveEdit )
134  }
135  else
136  {
137  m_xDialog->grab_focus();
138  }
139  RefInputDone();
140 }
141 
142 void ScStatisticsInputOutputDialog::SetReference( const ScRange& rReferenceRange, ScDocument& rDocument )
143 {
144  if ( mpActiveEdit )
145  {
146  if ( rReferenceRange.aStart != rReferenceRange.aEnd )
148 
149  OUString aReferenceString;
150 
151  if (mpActiveEdit == mxInputRangeEdit.get())
152  {
153  mInputRange = rReferenceRange;
154  aReferenceString = mInputRange.Format(rDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails);
155  mxInputRangeEdit->SetRefString( aReferenceString );
156  }
157  else if (mpActiveEdit == mxOutputRangeEdit.get())
158  {
159  mOutputAddress = rReferenceRange.aStart;
160 
161  ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
164  aReferenceString = mOutputAddress.Format(nFormat, &rDocument, rDocument.GetAddressConvention());
165  mxOutputRangeEdit->SetRefString( aReferenceString );
166  }
167  }
168 
170 }
171 
172 IMPL_LINK( ScStatisticsInputOutputDialog, ButtonClicked, weld::Button&, rButton, void )
173 {
174  if (&rButton == mxButtonOk.get())
175  {
176  CalculateInputAndWriteToOutput();
177  response(RET_OK);
178  }
179  else
180  response(RET_CANCEL);
181 }
182 
183 IMPL_LINK(ScStatisticsInputOutputDialog, GetEditFocusHandler, formula::RefEdit&, rCtrl, void)
184 {
185  mpActiveEdit = nullptr;
186 
187  if (&rCtrl == mxInputRangeEdit.get())
188  mpActiveEdit = mxInputRangeEdit.get();
189  if (&rCtrl == mxOutputRangeEdit.get())
190  mpActiveEdit = mxOutputRangeEdit.get();
191 
192  if (mpActiveEdit)
193  mpActiveEdit->SelectAll();
194 }
195 
196 IMPL_LINK(ScStatisticsInputOutputDialog, GetButtonFocusHandler, formula::RefButton&, rCtrl, void)
197 {
198  mpActiveEdit = nullptr;
199 
200  if (&rCtrl == mxInputRangeButton.get())
201  mpActiveEdit = mxInputRangeEdit.get();
202  else if (&rCtrl == mxOutputRangeButton.get())
203  mpActiveEdit = mxOutputRangeEdit.get();
204 
205  if (mpActiveEdit)
206  mpActiveEdit->SelectAll();
207 }
208 
210 {
211  mDialogLostFocus = !m_xDialog->has_toplevel_focus();
212 }
213 
215 {
216  mDialogLostFocus = !m_xDialog->has_toplevel_focus();
217 }
218 
220 {
221  if (mxGroupByColumnsRadio->get_active())
222  mGroupedBy = BY_COLUMN;
223  else if (mxGroupByRowsRadio->get_active())
224  mGroupedBy = BY_ROW;
225 
226  ValidateDialogInput();
227 }
228 
230 {
231  if ( mpActiveEdit )
232  {
233  if (mpActiveEdit == mxInputRangeEdit.get())
234  {
235  ScRangeList aRangeList;
236  bool bValid = ParseWithNames( aRangeList, mxInputRangeEdit->GetText(), mDocument);
237  const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
238  if (pRange)
239  {
240  mInputRange = *pRange;
241  // Highlight the resulting range.
242  mxInputRangeEdit->StartUpdateData();
243  }
244  else
245  {
246  mInputRange = ScRange( ScAddress::INITIALIZE_INVALID);
247  }
248  }
249  else if (mpActiveEdit == mxOutputRangeEdit.get())
250  {
251  ScRangeList aRangeList;
252  bool bValid = ParseWithNames( aRangeList, mxOutputRangeEdit->GetText(), mDocument);
253  const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
254  if (pRange)
255  {
256  mOutputAddress = pRange->aStart;
257 
258  // Crop output range to top left address for Edit field.
259  if (pRange->aStart != pRange->aEnd)
260  {
261  ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
264  OUString aReferenceString = mOutputAddress.Format(nFormat, &mDocument, mDocument.GetAddressConvention());
265  mxOutputRangeEdit->SetRefString( aReferenceString );
266  }
267 
268  // Highlight the resulting range.
269  mxOutputRangeEdit->StartUpdateData();
270  }
271  else
272  {
273  mOutputAddress = ScAddress( ScAddress::INITIALIZE_INVALID);
274  }
275  }
276  }
277 
278  ValidateDialogInput();
279 }
280 
282 {
283  OUString aUndo(ScResId(GetUndoNameId()));
284  ScDocShell* pDocShell = mViewData.GetDocShell();
285  SfxUndoManager* pUndoManager = pDocShell->GetUndoManager();
286  pUndoManager->EnterListAction( aUndo, aUndo, 0, mViewData.GetViewShell()->GetViewShellId() );
287 
288  ScRange aOutputRange = ApplyOutput(pDocShell);
289 
290  pUndoManager->LeaveListAction();
291  pDocShell->PostPaint( aOutputRange, PaintPartFlags::Grid );
292 }
293 
295 {
297 }
298 
300 {
301  // Enable OK button if all inputs are ok.
302  mxButtonOk->set_sensitive(InputRangesValid());
303 }
304 
305 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2116
std::unique_ptr< weld::Label > mxInputRangeLabel
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:354
ScAddress aStart
Definition: address.hxx:500
static ScRangeList MakeRowRangeList(SCTAB aTab, ScAddress const &aStart, ScAddress const &aEnd)
SCROW Row() const
Definition: address.hxx:262
IMPL_LINK(ScStatisticsInputOutputDialog, ButtonClicked, weld::Button &, rButton, void)
ScStatisticsInputOutputDialog(SfxBindings *pB, SfxChildWindow *pCW, weld::Window *pParent, ScViewData &rViewData, const OUString &rUIXMLDescription, const OString &rID)
std::unique_ptr< weld::Label > mxOutputRangeLabel
std::unique_ptr< formula::RefButton > mxOutputRangeButton
ScAddress aEnd
Definition: address.hxx:501
RET_CANCEL
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:488
std::unique_ptr< weld::Button > mxButtonCancel
virtual SfxUndoManager * GetUndoManager() override
Definition: docsh.cxx:2806
IMPL_LINK_NOARG(ScStatisticsInputOutputDialog, LoseEditFocusHandler, formula::RefEdit &, void)
void push_back(const ScRange &rRange)
Definition: rangelst.cxx:1142
SCTAB Tab() const
Definition: address.hxx:271
ScTabViewShell * GetViewShell() const
Definition: viewdata.hxx:357
bool IsValid() const
Definition: address.hxx:293
std::unique_ptr< weld::RadioButton > mxGroupByRowsRadio
std::unique_ptr< formula::RefButton > mxInputRangeButton
sal_Int16 SCCOL
Definition: types.hxx:22
SC_DLLPUBLIC OUString Format(const ScDocument &rDocument, ScRefFlags nFlags=ScRefFlags::ZERO, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, bool bFullAddressNotation=false) const
Returns string with formatted cell range from aStart to aEnd, according to provided address conventio...
Definition: address.cxx:2212
size_t size() const
Definition: rangelst.hxx:90
OUString ScResId(const char *pId)
Definition: scdll.cxx:89
ScMarkType GetSimpleArea(SCCOL &rStartCol, SCROW &rStartRow, SCTAB &rStartTab, SCCOL &rEndCol, SCROW &rEndRow, SCTAB &rEndTab) const
Definition: viewdata.cxx:1170
virtual void RefInputDone(bool bForced=false) override
Definition: anyrefdg.cxx:755
bool IsValid() const
Definition: address.hxx:547
void PostPaint(SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, PaintPartFlags nPart, sal_uInt16 nExtFlags=0)
Definition: docsh3.cxx:98
SCCOL Col() const
Definition: address.hxx:267
size_t LeaveListAction()
sal_Int32 SCROW
Definition: types.hxx:18
std::unique_ptr< weld::Button > mxButtonOk
RET_OK
Reference< XExecutableDialog > m_xDialog
virtual void EnterListAction(const OUString &rComment, const OUString &rRepeatComment, sal_uInt16 nId, ViewShellId nViewShellId)
std::unique_ptr< formula::RefEdit > mxOutputRangeEdit
virtual void SetReference(const ScRange &rRef, ScDocument &rDoc) override
std::unique_ptr< formula::RefEdit > mxInputRangeEdit
ScRefFlags
Definition: address.hxx:145
static ScRangeList MakeColumnRangeList(SCTAB aTab, ScAddress const &aStart, ScAddress const &aEnd)
std::unique_ptr< weld::RadioButton > mxGroupByColumnsRadio
virtual ScRange ApplyOutput(ScDocShell *pDocShell)=0
sal_Int16 SCTAB
Definition: types.hxx:23
virtual const char * GetUndoNameId()=0
virtual void RefInputStart(formula::RefEdit *pEdit, formula::RefButton *pButton=nullptr) override
Definition: anyrefdg.cxx:725
ViewShellId GetViewShellId() const override