LibreOffice Module sc (master)  1
solvrdlg.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  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <scitems.hxx>
21 #include <sfx2/dispatch.hxx>
22 #include <svl/numformat.hxx>
23 #include <svl/zforlist.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/weld.hxx>
26 
27 #include <uiitems.hxx>
28 #include <reffact.hxx>
29 #include <document.hxx>
30 #include <globstr.hrc>
31 #include <scresid.hxx>
32 #include <sc.hrc>
33 #include <solvrdlg.hxx>
34 
36  ScDocument* pDocument,
37  const ScAddress& aCursorPos )
38 
39  : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/goalseekdlg.ui", "GoalSeekDialog")
40  , theFormulaCell(aCursorPos)
41  , theVariableCell(aCursorPos)
42  , pDoc(pDocument)
43  , nCurTab(aCursorPos.Tab())
44  , bDlgLostFocus(false)
45  , errMsgInvalidVar(ScResId(STR_INVALIDVAR))
46  , errMsgInvalidForm(ScResId(STR_INVALIDFORM))
47  , errMsgNoFormula(ScResId(STR_NOFORMULA))
48  , errMsgInvalidVal(ScResId(STR_INVALIDVAL))
49  , m_pEdActive(nullptr)
50  , m_xFtFormulaCell(m_xBuilder->weld_label("formulatext"))
51  , m_xEdFormulaCell(new formula::RefEdit(m_xBuilder->weld_entry("formulaedit")))
52  , m_xRBFormulaCell(new formula::RefButton(m_xBuilder->weld_button("formulabutton")))
53  , m_xEdTargetVal(m_xBuilder->weld_entry("target"))
54  , m_xFtVariableCell(m_xBuilder->weld_label("vartext"))
55  , m_xEdVariableCell(new formula::RefEdit(m_xBuilder->weld_entry("varedit")))
56  , m_xRBVariableCell(new formula::RefButton(m_xBuilder->weld_button("varbutton")))
57  , m_xBtnOk(m_xBuilder->weld_button("ok"))
58  , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
59 {
60  m_xEdFormulaCell->SetReferences(this, m_xFtFormulaCell.get());
61  m_xRBFormulaCell->SetReferences(this, m_xEdFormulaCell.get());
62  m_xEdVariableCell->SetReferences(this, m_xFtVariableCell.get());
63  m_xRBVariableCell->SetReferences(this, m_xEdVariableCell.get());
64  Init();
65 }
66 
68 {
69  if (m_xMessageBox)
70  m_xMessageBox->response(RET_CANCEL);
71  assert(!m_xMessageBox);
72 }
73 
75 {
76  m_xBtnOk->connect_clicked( LINK( this, ScSolverDlg, BtnHdl ) );
77  m_xBtnCancel->connect_clicked( LINK( this, ScSolverDlg, BtnHdl ) );
78 
79  Link<formula::RefEdit&,void> aEditLink = LINK( this, ScSolverDlg, GetEditFocusHdl );
80  m_xEdFormulaCell->SetGetFocusHdl( aEditLink );
81  m_xEdVariableCell->SetGetFocusHdl( aEditLink );
82 
83  Link<formula::RefButton&,void> aButtonLink = LINK( this, ScSolverDlg, GetButtonFocusHdl );
84  m_xRBFormulaCell->SetGetFocusHdl( aButtonLink );
85  m_xRBVariableCell->SetGetFocusHdl( aButtonLink );
86 
87  m_xEdTargetVal->connect_focus_in(LINK(this, ScSolverDlg, GetFocusHdl));
88 
89  aEditLink = LINK( this, ScSolverDlg, LoseEditFocusHdl );
90  m_xEdFormulaCell->SetLoseFocusHdl ( aEditLink );
91  m_xEdVariableCell->SetLoseFocusHdl ( aEditLink );
92 
93  aButtonLink = LINK( this, ScSolverDlg, LoseButtonFocusHdl );
94  m_xRBFormulaCell->SetLoseFocusHdl ( aButtonLink );
95  m_xRBVariableCell->SetLoseFocusHdl ( aButtonLink );
96 
98 
99  m_xEdFormulaCell->SetText( aStr );
100  m_xEdFormulaCell->GrabFocus();
102 }
103 
105 {
106  DoClose( ScSolverDlgWrapper::GetChildWindowId() );
107 }
108 
110 {
111  if ( bDlgLostFocus )
112  {
113  bDlgLostFocus = false;
114  if( m_pEdActive )
116  }
117  else
118  {
119  m_xDialog->grab_focus();
120  }
121  RefInputDone();
122 }
123 
124 void ScSolverDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
125 {
126  if( !m_pEdActive )
127  return;
128 
129  if ( rRef.aStart != rRef.aEnd )
131 
132  ScAddress aAdr = rRef.aStart;
133  ScRefFlags nFmt = ( aAdr.Tab() == nCurTab )
136 
137  OUString aStr(aAdr.Format(nFmt, &rDocP, rDocP.GetAddressConvention()));
138  m_pEdActive->SetRefString( aStr );
139 
140  if (m_pEdActive == m_xEdFormulaCell.get())
141  theFormulaCell = aAdr;
142  else if (m_pEdActive == m_xEdVariableCell.get())
143  theVariableCell = aAdr;
144 }
145 
147 {
148  OUString sMessage;
149 
150  switch (eError)
151  {
152  case SOLVERR_NOFORMULA:
153  sMessage = errMsgNoFormula;
154  break;
156  sMessage = errMsgInvalidForm;
157  break;
159  sMessage = errMsgInvalidVar;
160  break;
162  sMessage = errMsgInvalidVal;
163  break;
164  }
165 
167  VclMessageType::Warning, VclButtonsType::Ok,
168  sMessage));
169  m_xMessageBox->runAsync(m_xMessageBox, [this](sal_Int32 /*nResult*/) {
170  m_xEdTargetVal->grab_focus();
171  m_xMessageBox.reset();
172  });
173 }
174 
176 {
177  return m_pEdActive != nullptr;
178 }
179 
180 bool ScSolverDlg::CheckTargetValue( const OUString& rStrVal )
181 {
182  sal_uInt32 n1 = 0;
183  double n2;
184 
185  return pDoc->GetFormatTable()->IsNumberFormat( rStrVal, n1, n2 );
186 }
187 
188 // Handler:
189 
190 IMPL_LINK(ScSolverDlg, BtnHdl, weld::Button&, rBtn, void)
191 {
192  if (&rBtn == m_xBtnOk.get())
193  {
194  theTargetValStr = m_xEdTargetVal->get_text();
195 
196  // The following code checks:
197  // 1. do the strings contain correct references / defined names?
198  // 2. does the formula coordinate refer to a cell containing a formula?
199  // 3. has a valid target value been entered?
200 
201  const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
202  ScRefFlags nRes1 = theFormulaCell .Parse( m_xEdFormulaCell->GetText(), *pDoc, eConv );
203  ScRefFlags nRes2 = theVariableCell.Parse( m_xEdVariableCell->GetText(), *pDoc, eConv );
204 
205  if ( (nRes1 & ScRefFlags::VALID) == ScRefFlags::VALID )
206  {
207  if ( (nRes2 & ScRefFlags::VALID) == ScRefFlags::VALID )
208  {
209  if ( CheckTargetValue( theTargetValStr ) )
210  {
211  CellType eType = pDoc->GetCellType( theFormulaCell.Col(),
212  theFormulaCell.Row(),
213  theFormulaCell.Tab());
214 
215  if ( CELLTYPE_FORMULA == eType )
216  {
217  ScSolveParam aOutParam( theFormulaCell,
218  theVariableCell,
219  theTargetValStr );
220  ScSolveItem aOutItem( SCITEM_SOLVEDATA, &aOutParam );
221 
222  SetDispatcherLock( false );
223 
224  SwitchToDocument();
225  GetBindings().GetDispatcher()->ExecuteList(SID_SOLVE,
226  SfxCallMode::SLOT | SfxCallMode::RECORD,
227  { &aOutItem });
228  response(RET_OK);
229  }
230  else RaiseError( SOLVERR_NOFORMULA );
231  }
232  else RaiseError( SOLVERR_INVALID_TARGETVALUE );
233  }
234  else RaiseError( SOLVERR_INVALID_VARIABLE );
235  }
236  else RaiseError( SOLVERR_INVALID_FORMULA );
237  }
238  else if (&rBtn == m_xBtnCancel.get())
239  {
240  response(RET_CANCEL);
241  }
242 }
243 
244 IMPL_LINK(ScSolverDlg, GetEditFocusHdl, formula::RefEdit&, rCtrl, void)
245 {
246  if (&rCtrl == m_xEdFormulaCell.get())
247  m_pEdActive = m_xEdFormulaCell.get();
248  else if (&rCtrl == m_xEdVariableCell.get())
249  m_pEdActive = m_xEdVariableCell.get();
250 
251  if (m_pEdActive)
252  m_pEdActive->SelectAll();
253 }
254 
256 {
257  m_pEdActive = nullptr;
258  m_xEdTargetVal->select_region(0, -1);
259 }
260 
261 IMPL_LINK(ScSolverDlg, GetButtonFocusHdl, formula::RefButton&, rCtrl, void)
262 {
263  if (&rCtrl == m_xRBFormulaCell.get())
264  m_pEdActive = m_xEdFormulaCell.get();
265  else if (&rCtrl == m_xRBVariableCell.get())
266  m_pEdActive = m_xEdVariableCell.get();
267 
268  if (m_pEdActive)
269  m_pEdActive->SelectAll();
270 }
271 
272 IMPL_LINK_NOARG(ScSolverDlg, LoseEditFocusHdl, formula::RefEdit&, void)
273 {
274  bDlgLostFocus = !m_xDialog->has_toplevel_focus();
275 }
276 
277 IMPL_LINK_NOARG(ScSolverDlg, LoseButtonFocusHdl, formula::RefButton&, void)
278 {
279  bDlgLostFocus = !m_xDialog->has_toplevel_focus();
280 }
281 
282 
283 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
IMPL_LINK(ScSolverDlg, BtnHdl, weld::Button &, rBtn, void)
Definition: solvrdlg.cxx:190
std::unique_ptr< weld::Label > m_xFtFormulaCell
Definition: solvrdlg.hxx:61
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2108
const SfxPoolItem * ExecuteList(sal_uInt16 nSlot, SfxCallMode nCall, std::initializer_list< SfxPoolItem const * > args, std::initializer_list< SfxPoolItem const * > internalargs=std::initializer_list< SfxPoolItem const * >())
OUString sMessage
bool CheckTargetValue(const OUString &rStrVal)
Definition: solvrdlg.cxx:180
ScAddress aStart
Definition: address.hxx:499
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:89
const OUString errMsgInvalidVar
Definition: solvrdlg.hxx:54
int n1
virtual bool IsRefInputMode() const override
Definition: solvrdlg.cxx:175
ScAddress aEnd
Definition: address.hxx:500
virtual SfxBindings & GetBindings() override
bool bDlgLostFocus
Definition: solvrdlg.hxx:53
const OUString errMsgNoFormula
Definition: solvrdlg.hxx:56
RET_CANCEL
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:494
const OUString errMsgInvalidForm
Definition: solvrdlg.hxx:55
formula::RefEdit * m_pEdActive
Definition: solvrdlg.hxx:59
int n2
std::unique_ptr< weld::Button > m_xBtnOk
Definition: solvrdlg.hxx:71
const OUString errMsgInvalidVal
Definition: solvrdlg.hxx:57
std::shared_ptr< weld::MessageDialog > m_xMessageBox
Definition: solvrdlg.hxx:74
IMPL_LINK_NOARG(ScSolverDlg, GetFocusHdl, weld::Widget &, void)
Definition: solvrdlg.cxx:255
std::unique_ptr< formula::RefButton > m_xRBFormulaCell
Definition: solvrdlg.hxx:63
ScSolverErr
Definition: solvrdlg.hxx:25
SCTAB Tab() const
Definition: address.hxx:270
const SCTAB nCurTab
Definition: solvrdlg.hxx:52
DocumentType eType
void SetRefString(const OUString &rStr)
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:442
ScDocument * pDoc
Definition: solvrdlg.hxx:51
void Init()
Definition: solvrdlg.cxx:74
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
virtual void RefInputDone(bool bForced=false) override
Definition: anyrefdg.cxx:778
virtual void SetReference(const ScRange &rRef, ScDocument &rDoc) override
Definition: solvrdlg.cxx:124
std::unique_ptr< formula::RefEdit > m_xEdFormulaCell
Definition: solvrdlg.hxx:62
std::unique_ptr< formula::RefEdit > m_xEdVariableCell
Definition: solvrdlg.hxx:68
virtual ~ScSolverDlg() override
Definition: solvrdlg.cxx:67
CellType
Definition: global.hxx:268
ScAddress theVariableCell
Definition: solvrdlg.hxx:48
RET_OK
Reference< XExecutableDialog > m_xDialog
ScAddress theFormulaCell
Definition: solvrdlg.hxx:47
SfxDispatcher * GetDispatcher() const
virtual void Close() override
Definition: solvrdlg.cxx:104
ScSolverDlg(SfxBindings *pB, SfxChildWindow *pCW, weld::Window *pParent, ScDocument *pDocument, const ScAddress &aCursorPos)
Definition: solvrdlg.cxx:35
std::unique_ptr< formula::RefButton > m_xRBVariableCell
Definition: solvrdlg.hxx:69
ScRefFlags
Definition: address.hxx:144
std::unique_ptr< weld::Entry > m_xEdTargetVal
Definition: solvrdlg.hxx:65
#define SCITEM_SOLVEDATA
Definition: scitems.hxx:94
bool DoClose(sal_uInt16 nId)
Definition: anyrefdg.cxx:717
aStr
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
std::unique_ptr< weld::Button > m_xBtnCancel
Definition: solvrdlg.hxx:72
virtual void SetActive() override
Definition: solvrdlg.cxx:109
std::unique_ptr< weld::Label > m_xFtVariableCell
Definition: solvrdlg.hxx:67
virtual void RefInputStart(formula::RefEdit *pEdit, formula::RefButton *pButton=nullptr) override
Definition: anyrefdg.cxx:748
void RaiseError(ScSolverErr eError)
Definition: solvrdlg.cxx:146