LibreOffice Module sc (master)  1
StatisticsTwoVariableDialog.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  SfxBindings* pSfxBindings, SfxChildWindow* pChildWindow,
23  weld::Window* pParent, ScViewData& rViewData, const OUString& rUIXMLDescription, const OString& rID)
24  : ScAnyRefDlgController(pSfxBindings, pChildWindow, pParent, rUIXMLDescription, rID)
25  , mxVariable1RangeLabel(m_xBuilder->weld_label("variable1-range-label"))
26  , mxVariable1RangeEdit(new formula::RefEdit(m_xBuilder->weld_entry("variable1-range-edit")))
27  , mxVariable1RangeButton(new formula::RefButton(m_xBuilder->weld_button("variable1-range-button")))
28  , mxVariable2RangeLabel(m_xBuilder->weld_label("variable2-range-label"))
29  , mxVariable2RangeEdit(new formula::RefEdit(m_xBuilder->weld_entry("variable2-range-edit")))
30  , mxVariable2RangeButton(new formula::RefButton(m_xBuilder->weld_button("variable2-range-button")))
31  , mxOutputRangeLabel(m_xBuilder->weld_label("output-range-label"))
32  , mxOutputRangeEdit(new formula::RefEdit(m_xBuilder->weld_entry("output-range-edit")))
33  , mxOutputRangeButton(new formula::RefButton(m_xBuilder->weld_button("output-range-button")))
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("ok"))
42  , mxButtonCancel(m_xBuilder->weld_button("cancel"))
43  , mxGroupByColumnsRadio(m_xBuilder->weld_radio_button("groupedby-columns-radio"))
44  , mxGroupByRowsRadio(m_xBuilder->weld_radio_button("groupedby-rows-radio"))
45  , mpActiveEdit(nullptr)
46  , mCurrentAddress(rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() )
47  , mDialogLostFocus(false)
48 {
49  mxVariable1RangeEdit->SetReferences(this, mxVariable1RangeLabel.get());
50  mxVariable1RangeButton->SetReferences(this, mxVariable1RangeEdit.get());
51 
52  mxVariable2RangeEdit->SetReferences(this, mxVariable2RangeLabel.get());
53  mxVariable2RangeButton->SetReferences(this, mxVariable2RangeEdit.get());
54 
55  mxOutputRangeEdit->SetReferences(this, mxOutputRangeLabel.get());
56  mxOutputRangeButton->SetReferences(this, mxOutputRangeEdit.get());
57 
58  Init();
60 }
61 
63 {
64 }
65 
67 {
68  mxButtonCancel->connect_clicked( LINK( this, ScStatisticsTwoVariableDialog, ButtonClicked ) );
69  mxButtonOk->connect_clicked( LINK( this, ScStatisticsTwoVariableDialog, ButtonClicked ) );
70  mxButtonOk->set_sensitive(false);
71 
72  Link<formula::RefEdit&,void> aEditLink = LINK( this, ScStatisticsTwoVariableDialog, GetEditFocusHandler );
73  mxVariable1RangeEdit->SetGetFocusHdl( aEditLink );
74  mxVariable2RangeEdit->SetGetFocusHdl( aEditLink );
75  mxOutputRangeEdit->SetGetFocusHdl( aEditLink );
76 
77  Link<formula::RefButton&,void> aButtonLink = LINK( this, ScStatisticsTwoVariableDialog, GetButtonFocusHandler );
78  mxVariable1RangeButton->SetGetFocusHdl( aButtonLink );
79  mxVariable2RangeButton->SetGetFocusHdl( aButtonLink );
80  mxOutputRangeButton->SetGetFocusHdl( aButtonLink );
81 
82  aEditLink = LINK( this, ScStatisticsTwoVariableDialog, LoseEditFocusHandler );
83  mxVariable1RangeEdit->SetLoseFocusHdl( aEditLink );
84  mxVariable2RangeEdit->SetLoseFocusHdl( aEditLink );
85  mxOutputRangeEdit->SetLoseFocusHdl( aEditLink );
86 
87  aButtonLink = LINK( this, ScStatisticsTwoVariableDialog, LoseButtonFocusHandler );
88  mxVariable1RangeButton->SetLoseFocusHdl( aButtonLink );
89  mxVariable2RangeButton->SetLoseFocusHdl( aButtonLink );
90  mxOutputRangeButton->SetLoseFocusHdl( aButtonLink );
91 
92  Link<formula::RefEdit&,void> aLink2 = LINK( this, ScStatisticsTwoVariableDialog, RefInputModifyHandler);
93  mxVariable1RangeEdit->SetModifyHdl( aLink2);
94  mxVariable2RangeEdit->SetModifyHdl( aLink2);
95  mxOutputRangeEdit->SetModifyHdl( aLink2);
96 
97  mxOutputRangeEdit->GrabFocus();
98 
99  mxGroupByColumnsRadio->connect_toggled( LINK( this, ScStatisticsTwoVariableDialog, GroupByChanged ) );
100  mxGroupByRowsRadio->connect_toggled( LINK( this, ScStatisticsTwoVariableDialog, GroupByChanged ) );
101 
102  mxGroupByColumnsRadio->set_active(true);
103  mxGroupByRowsRadio->set_active(false);
104 }
105 
107 {
108  OUString aCurrentString;
109 
110  ScRange aCurrentRange;
111  mViewData.GetSimpleArea(aCurrentRange);
112 
113  if (aCurrentRange.aEnd.Col() - aCurrentRange.aStart.Col() == 1)
114  {
115  mVariable1Range = aCurrentRange;
118  mxVariable1RangeEdit->SetText(aCurrentString);
119 
120  mVariable2Range = aCurrentRange;
123  mxVariable2RangeEdit->SetText(aCurrentString);
124  }
125  else
126  {
127  mVariable1Range = aCurrentRange;
129  mxVariable1RangeEdit->SetText(aCurrentString);
130  }
131 }
132 
134 {
135  if ( mDialogLostFocus )
136  {
137  mDialogLostFocus = false;
138  if( mpActiveEdit )
140  }
141  else
142  {
143  m_xDialog->grab_focus();
144  }
145  RefInputDone();
146 }
147 
148 void ScStatisticsTwoVariableDialog::SetReference( const ScRange& rReferenceRange, ScDocument& rDocument )
149 {
150  if ( mpActiveEdit != nullptr )
151  {
152  if ( rReferenceRange.aStart != rReferenceRange.aEnd )
154 
155  OUString aReferenceString;
156 
157  if ( mpActiveEdit == mxVariable1RangeEdit.get() )
158  {
159  mVariable1Range = rReferenceRange;
160  aReferenceString = mVariable1Range.Format(rDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails);
161  mxVariable1RangeEdit->SetRefString(aReferenceString);
162  }
163  else if ( mpActiveEdit == mxVariable2RangeEdit.get() )
164  {
165  mVariable2Range = rReferenceRange;
166  aReferenceString = mVariable2Range.Format(rDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails);
167  mxVariable2RangeEdit->SetRefString(aReferenceString);
168  }
169  else if ( mpActiveEdit == mxOutputRangeEdit.get() )
170  {
171  mOutputAddress = rReferenceRange.aStart;
172 
173  ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
176  aReferenceString = mOutputAddress.Format(nFormat, &rDocument, rDocument.GetAddressConvention());
177  mxOutputRangeEdit->SetRefString( aReferenceString );
178  }
179  }
180 
182 }
183 
184 IMPL_LINK( ScStatisticsTwoVariableDialog, ButtonClicked, weld::Button&, rButton, void )
185 {
186  if (&rButton == mxButtonOk.get())
187  {
188  CalculateInputAndWriteToOutput();
189  response(RET_OK);
190  }
191  else
192  response(RET_CANCEL);
193 }
194 
195 IMPL_LINK(ScStatisticsTwoVariableDialog, GetEditFocusHandler, formula::RefEdit&, rCtrl, void)
196 {
197  mpActiveEdit = nullptr;
198  if (&rCtrl == mxVariable1RangeEdit.get())
199  {
200  mpActiveEdit = mxVariable1RangeEdit.get();
201  }
202  else if (&rCtrl == mxVariable2RangeEdit.get())
203  {
204  mpActiveEdit = mxVariable2RangeEdit.get();
205  }
206  else if (&rCtrl == mxOutputRangeEdit.get())
207  {
208  mpActiveEdit = mxOutputRangeEdit.get();
209  }
210 
211  if( mpActiveEdit )
212  mpActiveEdit->SelectAll();
213 }
214 
215 IMPL_LINK( ScStatisticsTwoVariableDialog, GetButtonFocusHandler, formula::RefButton&, rCtrl, void )
216 {
217  mpActiveEdit = nullptr;
218  if (&rCtrl == mxVariable1RangeButton.get())
219  {
220  mpActiveEdit = mxVariable1RangeEdit.get();
221  }
222  else if (&rCtrl == mxVariable2RangeButton.get())
223  {
224  mpActiveEdit = mxVariable2RangeEdit.get();
225  }
226  else if (&rCtrl == mxOutputRangeButton.get())
227  {
228  mpActiveEdit = mxOutputRangeEdit.get();
229  }
230 
231  if( mpActiveEdit )
232  mpActiveEdit->SelectAll();
233 }
234 
236 {
237  mDialogLostFocus = !m_xDialog->has_toplevel_focus();
238 }
239 
241 {
242  mDialogLostFocus = !m_xDialog->has_toplevel_focus();
243 }
244 
246 {
247  if (mxGroupByColumnsRadio->get_active())
248  mGroupedBy = BY_COLUMN;
249  else if (mxGroupByRowsRadio->get_active())
250  mGroupedBy = BY_ROW;
251 
252  ValidateDialogInput();
253 }
254 
256 {
257  if ( mpActiveEdit )
258  {
259  if (mpActiveEdit == mxVariable1RangeEdit.get())
260  {
261  ScRangeList aRangeList;
262  bool bValid = ParseWithNames( aRangeList, mxVariable1RangeEdit->GetText(), mDocument);
263  const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
264  if (pRange)
265  {
266  mVariable1Range = *pRange;
267  // Highlight the resulting range.
268  mxVariable1RangeEdit->StartUpdateData();
269  }
270  else
271  {
272  mVariable1Range = ScRange( ScAddress::INITIALIZE_INVALID);
273  }
274  }
275  else if ( mpActiveEdit == mxVariable2RangeEdit.get() )
276  {
277  ScRangeList aRangeList;
278  bool bValid = ParseWithNames( aRangeList, mxVariable2RangeEdit->GetText(), mDocument);
279  const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
280  if (pRange)
281  {
282  mVariable2Range = *pRange;
283  // Highlight the resulting range.
284  mxVariable2RangeEdit->StartUpdateData();
285  }
286  else
287  {
288  mVariable2Range = ScRange( ScAddress::INITIALIZE_INVALID);
289  }
290  }
291  else if ( mpActiveEdit == mxOutputRangeEdit.get() )
292  {
293  ScRangeList aRangeList;
294  bool bValid = ParseWithNames( aRangeList, mxOutputRangeEdit->GetText(), mDocument);
295  const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
296  if (pRange)
297  {
298  mOutputAddress = pRange->aStart;
299 
300  // Crop output range to top left address for Edit field.
301  if (pRange->aStart != pRange->aEnd)
302  {
303  ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
306  OUString aReferenceString = mOutputAddress.Format(nFormat, &mDocument, mDocument.GetAddressConvention());
307  mxOutputRangeEdit->SetRefString( aReferenceString );
308  }
309 
310  // Highlight the resulting range.
311  mxOutputRangeEdit->StartUpdateData();
312  }
313  else
314  {
315  mOutputAddress = ScAddress( ScAddress::INITIALIZE_INVALID);
316  }
317  }
318  }
319 
320  ValidateDialogInput();
321 }
322 
324 {
325  OUString aUndo(ScResId(GetUndoNameId()));
326  ScDocShell* pDocShell = mViewData.GetDocShell();
327  SfxUndoManager* pUndoManager = pDocShell->GetUndoManager();
328  pUndoManager->EnterListAction( aUndo, aUndo, 0, mViewData.GetViewShell()->GetViewShellId() );
329 
330  ScRange aOutputRange = ApplyOutput(pDocShell);
331 
332  pUndoManager->LeaveListAction();
333  pDocShell->PostPaint( aOutputRange, PaintPartFlags::Grid );
334 }
335 
337 {
339 }
340 
342 {
343  // Enable OK button if all inputs are ok.
344  mxButtonOk->set_sensitive(InputRangesValid());
345 }
346 
347 /* 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
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:353
ScAddress aStart
Definition: address.hxx:499
std::unique_ptr< formula::RefEdit > mxOutputRangeEdit
std::unique_ptr< weld::Label > mxVariable2RangeLabel
virtual const char * GetUndoNameId()=0
ScAddress aEnd
Definition: address.hxx:500
std::unique_ptr< formula::RefEdit > mxVariable2RangeEdit
RET_CANCEL
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:493
virtual SfxUndoManager * GetUndoManager() override
Definition: docsh.cxx:2806
virtual ScRange ApplyOutput(ScDocShell *pDocShell)=0
SCTAB Tab() const
Definition: address.hxx:270
std::unique_ptr< formula::RefButton > mxVariable2RangeButton
void SetCol(SCCOL nColP)
Definition: address.hxx:278
ScTabViewShell * GetViewShell() const
Definition: viewdata.hxx:356
bool IsValid() const
Definition: address.hxx:292
IMPL_LINK(ScStatisticsTwoVariableDialog, ButtonClicked, weld::Button &, rButton, void)
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:89
std::unique_ptr< formula::RefButton > mxVariable1RangeButton
std::unique_ptr< weld::Button > mxButtonOk
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:1171
virtual void RefInputDone(bool bForced=false) override
Definition: anyrefdg.cxx:755
std::unique_ptr< weld::Label > mxVariable1RangeLabel
std::unique_ptr< weld::RadioButton > mxGroupByColumnsRadio
std::unique_ptr< formula::RefButton > mxOutputRangeButton
bool IsValid() const
Definition: address.hxx:546
void PostPaint(SCCOL nStartCol, SCROW nStartRow, SCTAB nStartTab, SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab, PaintPartFlags nPart, sal_uInt16 nExtFlags=0)
Definition: docsh3.cxx:99
SCCOL Col() const
Definition: address.hxx:266
std::unique_ptr< formula::RefEdit > mxVariable1RangeEdit
size_t LeaveListAction()
std::unique_ptr< weld::Label > mxOutputRangeLabel
IMPL_LINK_NOARG(ScStatisticsTwoVariableDialog, LoseEditFocusHandler, formula::RefEdit &, void)
std::unique_ptr< weld::Button > mxButtonCancel
RET_OK
std::unique_ptr< weld::RadioButton > mxGroupByRowsRadio
Reference< XExecutableDialog > m_xDialog
virtual void EnterListAction(const OUString &rComment, const OUString &rRepeatComment, sal_uInt16 nId, ViewShellId nViewShellId)
ScStatisticsTwoVariableDialog(SfxBindings *pB, SfxChildWindow *pCW, weld::Window *pParent, ScViewData &rViewData, const OUString &rUIXMLDescription, const OString &rID)
ScRefFlags
Definition: address.hxx:144
virtual void SetReference(const ScRange &rRef, ScDocument &rDoc) override
virtual void RefInputStart(formula::RefEdit *pEdit, formula::RefButton *pButton=nullptr) override
Definition: anyrefdg.cxx:725
ViewShellId GetViewShellId() const override