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  , mpActiveEdit(nullptr)
69  , mCurrentAddress(rViewData.GetCurX(), rViewData.GetCurY(), rViewData.GetTabNo())
70  , mDialogLostFocus(false)
71 {
72  mxInputRangeEdit->SetReferences(this, mxInputRangeLabel.get());
73  mxInputRangeButton->SetReferences(this, mxInputRangeEdit.get());
74 
75  mxOutputRangeEdit->SetReferences(this, mxOutputRangeLabel.get());
76  mxOutputRangeButton->SetReferences(this, mxOutputRangeEdit.get());
77 
78  Init();
80 }
81 
83 {
84 }
85 
87 {
88  mxButtonOk->connect_clicked( LINK( this, ScStatisticsInputOutputDialog, OkClicked ) );
89  mxButtonOk->set_sensitive(false);
90 
91  Link<formula::RefEdit&,void> aEditLink = LINK( this, ScStatisticsInputOutputDialog, GetEditFocusHandler );
92  mxInputRangeEdit->SetGetFocusHdl( aEditLink );
93  mxOutputRangeEdit->SetGetFocusHdl( aEditLink );
94  Link<formula::RefButton&,void> aButtonLink = LINK( this, ScStatisticsInputOutputDialog, GetButtonFocusHandler );
95  mxInputRangeButton->SetGetFocusHdl( aButtonLink );
96  mxOutputRangeButton->SetGetFocusHdl( aButtonLink );
97 
98  aEditLink = LINK( this, ScStatisticsInputOutputDialog, LoseEditFocusHandler );
99  mxInputRangeEdit->SetLoseFocusHdl( aEditLink );
100  mxOutputRangeEdit->SetLoseFocusHdl( aEditLink );
101  aButtonLink = LINK( this, ScStatisticsInputOutputDialog, LoseButtonFocusHandler );
102  mxInputRangeButton->SetLoseFocusHdl( aButtonLink );
103  mxOutputRangeButton->SetLoseFocusHdl( aButtonLink );
104 
105  Link<formula::RefEdit&,void> aLink2 = LINK( this, ScStatisticsInputOutputDialog, RefInputModifyHandler);
106  mxInputRangeEdit->SetModifyHdl( aLink2);
107  mxOutputRangeEdit->SetModifyHdl( aLink2);
108 
109  mxOutputRangeEdit->GrabFocus();
110 
111  mxGroupByColumnsRadio->connect_toggled( LINK( this, ScStatisticsInputOutputDialog, GroupByChanged ) );
112  mxGroupByRowsRadio->connect_toggled( LINK( this, ScStatisticsInputOutputDialog, GroupByChanged ) );
113 
114  mxGroupByColumnsRadio->set_active(true);
115  mxGroupByRowsRadio->set_active(false);
116 }
117 
119 {
122  mxInputRangeEdit->SetText(aCurrentString);
123 }
124 
126 {
127  if ( mDialogLostFocus )
128  {
129  mDialogLostFocus = false;
130  if( mpActiveEdit )
132  }
133  else
134  {
135  m_xDialog->grab_focus();
136  }
137  RefInputDone();
138 }
139 
140 void ScStatisticsInputOutputDialog::SetReference( const ScRange& rReferenceRange, ScDocument& rDocument )
141 {
142  if ( mpActiveEdit )
143  {
144  if ( rReferenceRange.aStart != rReferenceRange.aEnd )
146 
147  OUString aReferenceString;
148 
149  if (mpActiveEdit == mxInputRangeEdit.get())
150  {
151  mInputRange = rReferenceRange;
152  aReferenceString = mInputRange.Format(rDocument, ScRefFlags::RANGE_ABS_3D, mAddressDetails);
153  mxInputRangeEdit->SetRefString( aReferenceString );
154  }
155  else if (mpActiveEdit == mxOutputRangeEdit.get())
156  {
157  mOutputAddress = rReferenceRange.aStart;
158 
159  ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
162  aReferenceString = mOutputAddress.Format(nFormat, &rDocument, rDocument.GetAddressConvention());
163  mxOutputRangeEdit->SetRefString( aReferenceString );
164  }
165  }
166 
168 }
169 
171 {
172  CalculateInputAndWriteToOutput();
173  response(RET_OK);
174 }
175 
176 IMPL_LINK(ScStatisticsInputOutputDialog, GetEditFocusHandler, formula::RefEdit&, rCtrl, void)
177 {
178  mpActiveEdit = nullptr;
179 
180  if (&rCtrl == mxInputRangeEdit.get())
181  mpActiveEdit = mxInputRangeEdit.get();
182  if (&rCtrl == mxOutputRangeEdit.get())
183  mpActiveEdit = mxOutputRangeEdit.get();
184 
185  if (mpActiveEdit)
186  mpActiveEdit->SelectAll();
187 }
188 
189 IMPL_LINK(ScStatisticsInputOutputDialog, GetButtonFocusHandler, formula::RefButton&, rCtrl, void)
190 {
191  mpActiveEdit = nullptr;
192 
193  if (&rCtrl == mxInputRangeButton.get())
194  mpActiveEdit = mxInputRangeEdit.get();
195  else if (&rCtrl == mxOutputRangeButton.get())
196  mpActiveEdit = mxOutputRangeEdit.get();
197 
198  if (mpActiveEdit)
199  mpActiveEdit->SelectAll();
200 }
201 
203 {
204  mDialogLostFocus = !m_xDialog->has_toplevel_focus();
205 }
206 
208 {
209  mDialogLostFocus = !m_xDialog->has_toplevel_focus();
210 }
211 
213 {
214  if (mxGroupByColumnsRadio->get_active())
215  mGroupedBy = BY_COLUMN;
216  else if (mxGroupByRowsRadio->get_active())
217  mGroupedBy = BY_ROW;
218 
219  ValidateDialogInput();
220 }
221 
223 {
224  if ( mpActiveEdit )
225  {
226  if (mpActiveEdit == mxInputRangeEdit.get())
227  {
228  ScRangeList aRangeList;
229  bool bValid = ParseWithNames( aRangeList, mxInputRangeEdit->GetText(), mDocument);
230  const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
231  if (pRange)
232  {
233  mInputRange = *pRange;
234  // Highlight the resulting range.
235  mxInputRangeEdit->StartUpdateData();
236  }
237  else
238  {
239  mInputRange = ScRange( ScAddress::INITIALIZE_INVALID);
240  }
241  }
242  else if (mpActiveEdit == mxOutputRangeEdit.get())
243  {
244  ScRangeList aRangeList;
245  bool bValid = ParseWithNames( aRangeList, mxOutputRangeEdit->GetText(), mDocument);
246  const ScRange* pRange = (bValid && aRangeList.size() == 1) ? &aRangeList[0] : nullptr;
247  if (pRange)
248  {
249  mOutputAddress = pRange->aStart;
250 
251  // Crop output range to top left address for Edit field.
252  if (pRange->aStart != pRange->aEnd)
253  {
254  ScRefFlags nFormat = ( mOutputAddress.Tab() == mCurrentAddress.Tab() ) ?
257  OUString aReferenceString = mOutputAddress.Format(nFormat, &mDocument, mDocument.GetAddressConvention());
258  mxOutputRangeEdit->SetRefString( aReferenceString );
259  }
260 
261  // Highlight the resulting range.
262  mxOutputRangeEdit->StartUpdateData();
263  }
264  else
265  {
266  mOutputAddress = ScAddress( ScAddress::INITIALIZE_INVALID);
267  }
268  }
269  }
270 
271  ValidateDialogInput();
272 }
273 
275 {
276  OUString aUndo(ScResId(GetUndoNameId()));
277  ScDocShell* pDocShell = mViewData.GetDocShell();
278  SfxUndoManager* pUndoManager = pDocShell->GetUndoManager();
279  pUndoManager->EnterListAction( aUndo, aUndo, 0, mViewData.GetViewShell()->GetViewShellId() );
280 
281  ScRange aOutputRange = ApplyOutput(pDocShell);
282 
283  pUndoManager->LeaveListAction();
284  pDocShell->PostPaint( aOutputRange, PaintPartFlags::Grid );
285 }
286 
288 {
290 }
291 
293 {
294  // Enable OK button if all inputs are ok.
295  mxButtonOk->set_sensitive(InputRangesValid());
296 }
297 
298 /* 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
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
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
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:489
virtual SfxUndoManager * GetUndoManager() override
Definition: docsh.cxx:2805
void push_back(const ScRange &rRange)
Definition: rangelst.cxx:1144
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:2203
size_t size() const
Definition: rangelst.hxx:90
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
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
size_t LeaveListAction()
sal_Int32 SCROW
Definition: types.hxx:18
IMPL_LINK_NOARG(ScStatisticsInputOutputDialog, OkClicked, weld::Button &, void)
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
IMPL_LINK(ScStatisticsInputOutputDialog, GetEditFocusHandler, formula::RefEdit &, rCtrl, void)
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