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  , mxGroupByColumnsRadio(m_xBuilder->weld_radio_button("groupedby-columns-radio"))
43  , mxGroupByRowsRadio(m_xBuilder->weld_radio_button("groupedby-rows-radio"))
44  , mpActiveEdit(nullptr)
45  , mCurrentAddress(rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo() )
46  , mDialogLostFocus(false)
47 {
48  mxVariable1RangeEdit->SetReferences(this, mxVariable1RangeLabel.get());
49  mxVariable1RangeButton->SetReferences(this, mxVariable1RangeEdit.get());
50 
51  mxVariable2RangeEdit->SetReferences(this, mxVariable2RangeLabel.get());
52  mxVariable2RangeButton->SetReferences(this, mxVariable2RangeEdit.get());
53 
54  mxOutputRangeEdit->SetReferences(this, mxOutputRangeLabel.get());
55  mxOutputRangeButton->SetReferences(this, mxOutputRangeEdit.get());
56 
57  Init();
59 }
60 
62 {
63 }
64 
66 {
67  mxButtonOk->connect_clicked( LINK( this, ScStatisticsTwoVariableDialog, OkClicked ) );
68  mxButtonOk->set_sensitive(false);
69 
70  Link<formula::RefEdit&,void> aEditLink = LINK( this, ScStatisticsTwoVariableDialog, GetEditFocusHandler );
71  mxVariable1RangeEdit->SetGetFocusHdl( aEditLink );
72  mxVariable2RangeEdit->SetGetFocusHdl( aEditLink );
73  mxOutputRangeEdit->SetGetFocusHdl( aEditLink );
74 
75  Link<formula::RefButton&,void> aButtonLink = LINK( this, ScStatisticsTwoVariableDialog, GetButtonFocusHandler );
76  mxVariable1RangeButton->SetGetFocusHdl( aButtonLink );
77  mxVariable2RangeButton->SetGetFocusHdl( aButtonLink );
78  mxOutputRangeButton->SetGetFocusHdl( aButtonLink );
79 
80  aEditLink = LINK( this, ScStatisticsTwoVariableDialog, LoseEditFocusHandler );
81  mxVariable1RangeEdit->SetLoseFocusHdl( aEditLink );
82  mxVariable2RangeEdit->SetLoseFocusHdl( aEditLink );
83  mxOutputRangeEdit->SetLoseFocusHdl( aEditLink );
84 
85  aButtonLink = LINK( this, ScStatisticsTwoVariableDialog, LoseButtonFocusHandler );
86  mxVariable1RangeButton->SetLoseFocusHdl( aButtonLink );
87  mxVariable2RangeButton->SetLoseFocusHdl( aButtonLink );
88  mxOutputRangeButton->SetLoseFocusHdl( aButtonLink );
89 
90  Link<formula::RefEdit&,void> aLink2 = LINK( this, ScStatisticsTwoVariableDialog, RefInputModifyHandler);
91  mxVariable1RangeEdit->SetModifyHdl( aLink2);
92  mxVariable2RangeEdit->SetModifyHdl( aLink2);
93  mxOutputRangeEdit->SetModifyHdl( aLink2);
94 
95  mxOutputRangeEdit->GrabFocus();
96 
97  mxGroupByColumnsRadio->connect_toggled( LINK( this, ScStatisticsTwoVariableDialog, GroupByChanged ) );
98  mxGroupByRowsRadio->connect_toggled( LINK( this, ScStatisticsTwoVariableDialog, GroupByChanged ) );
99 
100  mxGroupByColumnsRadio->set_active(true);
101  mxGroupByRowsRadio->set_active(false);
102 }
103 
105 {
106  OUString aCurrentString;
107 
108  ScRange aCurrentRange;
109  mViewData.GetSimpleArea(aCurrentRange);
110 
111  if (aCurrentRange.aEnd.Col() - aCurrentRange.aStart.Col() == 1)
112  {
113  mVariable1Range = aCurrentRange;
116  mxVariable1RangeEdit->SetText(aCurrentString);
117 
118  mVariable2Range = aCurrentRange;
121  mxVariable2RangeEdit->SetText(aCurrentString);
122  }
123  else
124  {
125  mVariable1Range = aCurrentRange;
127  mxVariable1RangeEdit->SetText(aCurrentString);
128  }
129 }
130 
132 {
133  if ( mDialogLostFocus )
134  {
135  mDialogLostFocus = false;
136  if( mpActiveEdit )
138  }
139  else
140  {
141  m_xDialog->grab_focus();
142  }
143  RefInputDone();
144 }
145 
146 void ScStatisticsTwoVariableDialog::SetReference( const ScRange& rReferenceRange, ScDocument& rDocument )
147 {
148  if ( mpActiveEdit != nullptr )
149  {
150  if ( rReferenceRange.aStart != rReferenceRange.aEnd )
152 
153  OUString aReferenceString;
154 
155  if ( mpActiveEdit == mxVariable1RangeEdit.get() )
156  {
157  mVariable1Range = rReferenceRange;
158  aReferenceString = mVariable1Range.Format(rDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails);
159  mxVariable1RangeEdit->SetRefString(aReferenceString);
160  }
161  else if ( mpActiveEdit == mxVariable2RangeEdit.get() )
162  {
163  mVariable2Range = rReferenceRange;
164  aReferenceString = mVariable2Range.Format(rDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails);
165  mxVariable2RangeEdit->SetRefString(aReferenceString);
166  }
167  else if ( mpActiveEdit == mxOutputRangeEdit.get() )
168  {
169  mOutputAddress = rReferenceRange.aStart;
170 
171  ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
174  aReferenceString = mOutputAddress.Format(nFormat, &rDocument, rDocument.GetAddressConvention());
175  mxOutputRangeEdit->SetRefString( aReferenceString );
176  }
177  }
178 
180 }
181 
183 {
184  CalculateInputAndWriteToOutput();
185  response(RET_OK);
186 }
187 
188 IMPL_LINK(ScStatisticsTwoVariableDialog, GetEditFocusHandler, formula::RefEdit&, rCtrl, void)
189 {
190  mpActiveEdit = nullptr;
191  if (&rCtrl == mxVariable1RangeEdit.get())
192  {
193  mpActiveEdit = mxVariable1RangeEdit.get();
194  }
195  else if (&rCtrl == mxVariable2RangeEdit.get())
196  {
197  mpActiveEdit = mxVariable2RangeEdit.get();
198  }
199  else if (&rCtrl == mxOutputRangeEdit.get())
200  {
201  mpActiveEdit = mxOutputRangeEdit.get();
202  }
203 
204  if( mpActiveEdit )
205  mpActiveEdit->SelectAll();
206 }
207 
208 IMPL_LINK( ScStatisticsTwoVariableDialog, GetButtonFocusHandler, formula::RefButton&, rCtrl, void )
209 {
210  mpActiveEdit = nullptr;
211  if (&rCtrl == mxVariable1RangeButton.get())
212  {
213  mpActiveEdit = mxVariable1RangeEdit.get();
214  }
215  else if (&rCtrl == mxVariable2RangeButton.get())
216  {
217  mpActiveEdit = mxVariable2RangeEdit.get();
218  }
219  else if (&rCtrl == mxOutputRangeButton.get())
220  {
221  mpActiveEdit = mxOutputRangeEdit.get();
222  }
223 
224  if( mpActiveEdit )
225  mpActiveEdit->SelectAll();
226 }
227 
229 {
230  mDialogLostFocus = !m_xDialog->has_toplevel_focus();
231 }
232 
234 {
235  mDialogLostFocus = !m_xDialog->has_toplevel_focus();
236 }
237 
239 {
240  if (mxGroupByColumnsRadio->get_active())
241  mGroupedBy = BY_COLUMN;
242  else if (mxGroupByRowsRadio->get_active())
243  mGroupedBy = BY_ROW;
244 
245  ValidateDialogInput();
246 }
247 
249 {
250  if ( mpActiveEdit )
251  {
252  if (mpActiveEdit == mxVariable1RangeEdit.get())
253  {
254  ScRangeList aRangeList;
255  bool bValid = ParseWithNames( aRangeList, mxVariable1RangeEdit->GetText(), mDocument);
256  const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
257  if (pRange)
258  {
259  mVariable1Range = *pRange;
260  // Highlight the resulting range.
261  mxVariable1RangeEdit->StartUpdateData();
262  }
263  else
264  {
265  mVariable1Range = ScRange( ScAddress::INITIALIZE_INVALID);
266  }
267  }
268  else if ( mpActiveEdit == mxVariable2RangeEdit.get() )
269  {
270  ScRangeList aRangeList;
271  bool bValid = ParseWithNames( aRangeList, mxVariable2RangeEdit->GetText(), mDocument);
272  const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
273  if (pRange)
274  {
275  mVariable2Range = *pRange;
276  // Highlight the resulting range.
277  mxVariable2RangeEdit->StartUpdateData();
278  }
279  else
280  {
281  mVariable2Range = ScRange( ScAddress::INITIALIZE_INVALID);
282  }
283  }
284  else if ( mpActiveEdit == mxOutputRangeEdit.get() )
285  {
286  ScRangeList aRangeList;
287  bool bValid = ParseWithNames( aRangeList, mxOutputRangeEdit->GetText(), mDocument);
288  const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
289  if (pRange)
290  {
291  mOutputAddress = pRange->aStart;
292 
293  // Crop output range to top left address for Edit field.
294  if (pRange->aStart != pRange->aEnd)
295  {
296  ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
299  OUString aReferenceString = mOutputAddress.Format(nFormat, &mDocument, mDocument.GetAddressConvention());
300  mxOutputRangeEdit->SetRefString( aReferenceString );
301  }
302 
303  // Highlight the resulting range.
304  mxOutputRangeEdit->StartUpdateData();
305  }
306  else
307  {
308  mOutputAddress = ScAddress( ScAddress::INITIALIZE_INVALID);
309  }
310  }
311  }
312 
313  ValidateDialogInput();
314 }
315 
317 {
318  OUString aUndo(ScResId(GetUndoNameId()));
319  ScDocShell* pDocShell = mViewData.GetDocShell();
320  SfxUndoManager* pUndoManager = pDocShell->GetUndoManager();
321  pUndoManager->EnterListAction( aUndo, aUndo, 0, mViewData.GetViewShell()->GetViewShellId() );
322 
323  ScRange aOutputRange = ApplyOutput(pDocShell);
324 
325  pUndoManager->LeaveListAction();
326  pDocShell->PostPaint( aOutputRange, PaintPartFlags::Grid );
327 }
328 
330 {
332 }
333 
335 {
336  // Enable OK button if all inputs are ok.
337  mxButtonOk->set_sensitive(InputRangesValid());
338 }
339 
340 /* 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:2107
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:354
ScAddress aStart
Definition: address.hxx:500
std::unique_ptr< formula::RefEdit > mxOutputRangeEdit
std::unique_ptr< weld::Label > mxVariable2RangeLabel
virtual const char * GetUndoNameId()=0
ScAddress aEnd
Definition: address.hxx:501
std::unique_ptr< formula::RefEdit > mxVariable2RangeEdit
IMPL_LINK_NOARG(ScStatisticsTwoVariableDialog, OkClicked, weld::Button &, void)
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:489
virtual SfxUndoManager * GetUndoManager() override
Definition: docsh.cxx:2805
virtual ScRange ApplyOutput(ScDocShell *pDocShell)=0
IMPL_LINK(ScStatisticsTwoVariableDialog, GetEditFocusHandler, formula::RefEdit &, rCtrl, void)
SCTAB Tab() const
Definition: address.hxx:271
std::unique_ptr< formula::RefButton > mxVariable2RangeButton
void SetCol(SCCOL nColP)
Definition: address.hxx:279
ScTabViewShell * GetViewShell() const
Definition: viewdata.hxx:357
bool IsValid() const
Definition: address.hxx:293
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:2203
size_t size() const
Definition: rangelst.hxx:90
std::unique_ptr< formula::RefButton > mxVariable1RangeButton
std::unique_ptr< weld::Button > mxButtonOk
OUString ScResId(const char *pId)
Definition: scdll.cxx:95
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
std::unique_ptr< weld::Label > mxVariable1RangeLabel
std::unique_ptr< weld::RadioButton > mxGroupByColumnsRadio
std::unique_ptr< formula::RefButton > mxOutputRangeButton
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:99
SCCOL Col() const
Definition: address.hxx:267
std::unique_ptr< formula::RefEdit > mxVariable1RangeEdit
size_t LeaveListAction()
std::unique_ptr< weld::Label > mxOutputRangeLabel
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:145
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