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