Line data Source code
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 "rangelst.hxx"
21 : #include "scitems.hxx"
22 : #include <sfx2/bindings.hxx>
23 : #include <sfx2/imagemgr.hxx>
24 : #include <svl/zforlist.hxx>
25 : #include <vcl/builderfactory.hxx>
26 : #include <vcl/msgbox.hxx>
27 : #include <vcl/svapp.hxx>
28 :
29 : #include "uiitems.hxx"
30 : #include "reffact.hxx"
31 : #include "docsh.hxx"
32 : #include "docfunc.hxx"
33 : #include "formulacell.hxx"
34 : #include "rangeutl.hxx"
35 : #include "scresid.hxx"
36 : #include "convuno.hxx"
37 : #include "unonames.hxx"
38 : #include "solveroptions.hxx"
39 : #include "solverutil.hxx"
40 : #include "globstr.hrc"
41 :
42 : #include "optsolver.hxx"
43 :
44 : #include <com/sun/star/sheet/Solver.hpp>
45 : #include <com/sun/star/sheet/XSolverDescription.hpp>
46 :
47 : using namespace com::sun::star;
48 :
49 0 : ScSolverProgressDialog::ScSolverProgressDialog(vcl::Window* pParent)
50 : : ModelessDialog(pParent, "SolverProgressDialog",
51 0 : "modules/scalc/ui/solverprogressdialog.ui")
52 : {
53 0 : get(m_pFtTime, "progress");
54 0 : }
55 :
56 0 : ScSolverProgressDialog::~ScSolverProgressDialog()
57 : {
58 0 : disposeOnce();
59 0 : }
60 :
61 0 : void ScSolverProgressDialog::dispose()
62 : {
63 0 : m_pFtTime.clear();
64 0 : ModelessDialog::dispose();
65 0 : }
66 :
67 :
68 0 : void ScSolverProgressDialog::HideTimeLimit()
69 : {
70 0 : m_pFtTime->Hide();
71 0 : }
72 :
73 0 : void ScSolverProgressDialog::SetTimeLimit( sal_Int32 nSeconds )
74 : {
75 0 : OUString aOld = m_pFtTime->GetText();
76 0 : OUString aNew = aOld.replaceFirst("#", OUString::number(nSeconds));
77 0 : m_pFtTime->SetText( aNew );
78 0 : }
79 :
80 0 : ScSolverNoSolutionDialog::ScSolverNoSolutionDialog( vcl::Window* pParent, const OUString& rErrorText )
81 0 : : ModalDialog(pParent, "NoSolutionDialog", "modules/scalc/ui/nosolutiondialog.ui")
82 : {
83 0 : get(m_pFtErrorText, "error");
84 0 : m_pFtErrorText->SetText(rErrorText);
85 0 : }
86 :
87 0 : ScSolverNoSolutionDialog::~ScSolverNoSolutionDialog()
88 : {
89 0 : disposeOnce();
90 0 : }
91 :
92 0 : void ScSolverNoSolutionDialog::dispose()
93 : {
94 0 : m_pFtErrorText.clear();
95 0 : ModalDialog::dispose();
96 0 : }
97 :
98 0 : ScSolverSuccessDialog::ScSolverSuccessDialog( vcl::Window* pParent, const OUString& rSolution )
99 0 : : ModalDialog(pParent, "SolverSuccessDialog", "modules/scalc/ui/solversuccessdialog.ui")
100 : {
101 0 : get(m_pFtResult, "result");
102 0 : get(m_pBtnOk, "ok");
103 0 : m_pBtnOk->SetClickHdl(LINK(this, ScSolverSuccessDialog, ClickHdl));
104 0 : get(m_pBtnCancel, "cancel");
105 0 : m_pBtnCancel->SetClickHdl(LINK(this, ScSolverSuccessDialog, ClickHdl));
106 0 : OUString aMessage = m_pFtResult->GetText() + " " + rSolution;
107 0 : m_pFtResult->SetText(aMessage);
108 0 : }
109 :
110 0 : ScSolverSuccessDialog::~ScSolverSuccessDialog()
111 : {
112 0 : disposeOnce();
113 0 : }
114 :
115 0 : void ScSolverSuccessDialog::dispose()
116 : {
117 0 : m_pFtResult.clear();
118 0 : m_pBtnOk.clear();
119 0 : m_pBtnCancel.clear();
120 0 : ModalDialog::dispose();
121 0 : }
122 :
123 0 : IMPL_LINK( ScSolverSuccessDialog, ClickHdl, PushButton*, pBtn )
124 : {
125 0 : if (pBtn == m_pBtnOk)
126 0 : EndDialog(RET_OK);
127 : else
128 0 : EndDialog(RET_CANCEL);
129 0 : return 0;
130 : }
131 :
132 0 : ScCursorRefEdit::ScCursorRefEdit( vcl::Window* pParent, vcl::Window *pLabel )
133 0 : : formula::RefEdit( pParent, pLabel )
134 : {
135 0 : }
136 :
137 0 : VCL_BUILDER_FACTORY_ARGS(ScCursorRefEdit, nullptr)
138 :
139 0 : void ScCursorRefEdit::SetCursorLinks( const Link<>& rUp, const Link<>& rDown )
140 : {
141 0 : maCursorUpLink = rUp;
142 0 : maCursorDownLink = rDown;
143 0 : }
144 :
145 0 : void ScCursorRefEdit::KeyInput( const KeyEvent& rKEvt )
146 : {
147 0 : vcl::KeyCode aCode = rKEvt.GetKeyCode();
148 0 : bool bUp = (aCode.GetCode() == KEY_UP);
149 0 : bool bDown = (aCode.GetCode() == KEY_DOWN);
150 0 : if ( !aCode.IsShift() && !aCode.IsMod1() && !aCode.IsMod2() && ( bUp || bDown ) )
151 : {
152 0 : if ( bUp )
153 0 : maCursorUpLink.Call( this );
154 : else
155 0 : maCursorDownLink.Call( this );
156 : }
157 : else
158 0 : formula::RefEdit::KeyInput( rKEvt );
159 0 : }
160 :
161 0 : ScOptSolverSave::ScOptSolverSave( const OUString& rObjective, bool bMax, bool bMin, bool bValue,
162 : const OUString& rTarget, const OUString& rVariable,
163 : const std::vector<ScOptConditionRow>& rConditions,
164 : const OUString& rEngine,
165 : const uno::Sequence<beans::PropertyValue>& rProperties ) :
166 : maObjective( rObjective ),
167 : mbMax( bMax ),
168 : mbMin( bMin ),
169 : mbValue( bValue ),
170 : maTarget( rTarget ),
171 : maVariable( rVariable ),
172 : maConditions( rConditions ),
173 : maEngine( rEngine ),
174 0 : maProperties( rProperties )
175 : {
176 0 : }
177 :
178 : // class ScOptSolverDlg
179 :
180 0 : ScOptSolverDlg::ScOptSolverDlg( SfxBindings* pB, SfxChildWindow* pCW, vcl::Window* pParent,
181 : ScDocShell* pDocSh, ScAddress aCursorPos )
182 :
183 : : ScAnyRefDlg(pB, pCW, pParent, "SolverDialog", "modules/scalc/ui/solverdlg.ui")
184 0 : , maInputError(ScGlobal::GetRscString(STR_INVALIDINPUT))
185 0 : , maConditionError(ScGlobal::GetRscString(STR_INVALIDCONDITION))
186 :
187 : , mpDocShell(pDocSh)
188 0 : , mrDoc(pDocSh->GetDocument())
189 0 : , mnCurTab(aCursorPos.Tab())
190 : , mpEdActive(NULL)
191 : , mbDlgLostFocus(false)
192 0 : , nScrollPos(0)
193 : {
194 0 : get(m_pFtObjectiveCell, "targetlabel");
195 0 : get(m_pEdObjectiveCell, "targetedit");
196 0 : m_pEdObjectiveCell->SetReferences(this, m_pFtObjectiveCell);
197 0 : get(m_pRBObjectiveCell, "targetbutton");
198 0 : m_pRBObjectiveCell->SetReferences(this, m_pEdObjectiveCell);
199 0 : get(m_pRbMax, "max");
200 0 : get(m_pRbMin, "min");
201 0 : get(m_pRbValue, "value");
202 0 : get(m_pEdTargetValue, "valueedit");
203 0 : m_pEdTargetValue->SetReferences(this, get<FixedText>("result"));
204 0 : get(m_pRBTargetValue, "valuebutton");
205 0 : m_pRBTargetValue->SetReferences(this, m_pEdTargetValue);
206 0 : get(m_pFtVariableCells, "changelabel");
207 0 : get(m_pEdVariableCells, "changeedit");
208 0 : m_pEdVariableCells->SetReferences(this, m_pFtVariableCells);
209 0 : get(m_pRBVariableCells, "changebutton");
210 0 : m_pRBVariableCells->SetReferences(this, m_pEdVariableCells);
211 0 : get(m_pFtCellRef, "cellreflabel");
212 0 : get(m_pEdLeft1, "ref1edit");
213 0 : m_pEdLeft1->SetReferences(this, m_pFtCellRef);
214 0 : get(m_pRBLeft1, "ref1button");
215 0 : m_pRBLeft1->SetReferences(this, m_pEdLeft1);
216 0 : get(m_pFtOperator, "oplabel");
217 0 : get(m_pLbOp1, "op1list");
218 0 : get(m_pFtConstraint, "constraintlabel");
219 0 : get(m_pEdRight1, "val1edit");
220 0 : m_pEdRight1->SetReferences(this, m_pFtConstraint);
221 0 : get(m_pRBRight1, "val1button");
222 0 : m_pRBRight1->SetReferences(this, m_pEdRight1);
223 0 : get(m_pBtnDel1, "del1");
224 0 : get(m_pEdLeft2, "ref2edit");
225 0 : m_pEdLeft2->SetReferences(this, m_pFtCellRef);
226 0 : get(m_pRBLeft2, "ref2button");
227 0 : m_pRBLeft2->SetReferences(this, m_pEdLeft2);
228 0 : get(m_pLbOp2, "op2list");
229 0 : get(m_pEdRight2, "val2edit");
230 0 : m_pEdRight2->SetReferences(this, m_pFtConstraint);
231 0 : get(m_pRBRight2, "val2button");
232 0 : m_pRBRight2->SetReferences(this, m_pEdRight2);
233 0 : get(m_pBtnDel2, "del2");
234 0 : get(m_pEdLeft3, "ref3edit");
235 0 : m_pEdLeft3->SetReferences(this, m_pFtCellRef);
236 0 : get(m_pRBLeft3, "ref3button");
237 0 : m_pRBLeft3->SetReferences(this, m_pEdLeft3);
238 0 : get(m_pLbOp3, "op3list");
239 0 : get(m_pEdRight3, "val3edit");
240 0 : m_pEdRight3->SetReferences(this, m_pFtConstraint);
241 0 : get(m_pRBRight3, "val3button");
242 0 : m_pRBRight3->SetReferences(this, m_pEdRight3);
243 0 : get(m_pBtnDel3, "del3");
244 0 : get(m_pEdLeft4, "ref4edit");
245 0 : m_pEdLeft4->SetReferences(this, m_pFtCellRef);
246 0 : get(m_pRBLeft4, "ref4button");
247 0 : m_pRBLeft4->SetReferences(this, m_pEdLeft4);
248 0 : get(m_pLbOp4, "op4list");
249 0 : get(m_pEdRight4, "val4edit");
250 0 : m_pEdRight4->SetReferences(this, m_pFtConstraint);
251 0 : get(m_pRBRight4, "val4button");
252 0 : m_pRBRight4->SetReferences(this, m_pEdRight4);
253 0 : get(m_pBtnDel4, "del4");
254 0 : get(m_pScrollBar, "scrollbar");
255 0 : get(m_pBtnOpt, "options");
256 0 : get(m_pBtnCancel, "close");
257 0 : get(m_pBtnSolve, "solve");
258 :
259 0 : mpLeftEdit[0] = m_pEdLeft1;
260 0 : mpLeftButton[0] = m_pRBLeft1;
261 0 : mpRightEdit[0] = m_pEdRight1;
262 0 : mpRightButton[0] = m_pRBRight1;
263 0 : mpOperator[0] = m_pLbOp1;
264 0 : mpDelButton[0] = m_pBtnDel1;
265 :
266 0 : mpLeftEdit[1] = m_pEdLeft2;
267 0 : mpLeftButton[1] = m_pRBLeft2;
268 0 : mpRightEdit[1] = m_pEdRight2;
269 0 : mpRightButton[1] = m_pRBRight2;
270 0 : mpOperator[1] = m_pLbOp2;
271 0 : mpDelButton[1] = m_pBtnDel2;
272 :
273 0 : mpLeftEdit[2] = m_pEdLeft3;
274 0 : mpLeftButton[2] = m_pRBLeft3;
275 0 : mpRightEdit[2] = m_pEdRight3;
276 0 : mpRightButton[2] = m_pRBRight3;
277 0 : mpOperator[2] = m_pLbOp3;
278 0 : mpDelButton[2] = m_pBtnDel3;
279 :
280 0 : mpLeftEdit[3] = m_pEdLeft4;
281 0 : mpLeftButton[3] = m_pRBLeft4;
282 0 : mpRightEdit[3] = m_pEdRight4;
283 0 : mpRightButton[3] = m_pRBRight4;
284 0 : mpOperator[3] = m_pLbOp4;
285 0 : mpDelButton[3] = m_pBtnDel4;
286 :
287 0 : m_pEdLeft2->SetAccessibleName(m_pFtCellRef->GetText());
288 0 : m_pLbOp2->SetAccessibleName(m_pFtOperator->GetText());
289 0 : m_pEdRight2->SetAccessibleName(m_pFtConstraint->GetText());
290 0 : m_pEdLeft3->SetAccessibleName(m_pFtCellRef->GetText());
291 0 : m_pLbOp3->SetAccessibleName(m_pFtOperator->GetText());
292 0 : m_pEdRight3->SetAccessibleName(m_pFtConstraint->GetText());
293 0 : m_pEdLeft4->SetAccessibleName(m_pFtCellRef->GetText());
294 0 : m_pLbOp4->SetAccessibleName(m_pFtOperator->GetText());
295 0 : m_pEdRight4->SetAccessibleName(m_pFtConstraint->GetText());
296 :
297 0 : Init( aCursorPos );
298 0 : }
299 :
300 0 : ScOptSolverDlg::~ScOptSolverDlg()
301 : {
302 0 : disposeOnce();
303 0 : }
304 :
305 0 : void ScOptSolverDlg::dispose()
306 : {
307 0 : m_pFtObjectiveCell.clear();
308 0 : m_pEdObjectiveCell.clear();
309 0 : m_pRBObjectiveCell.clear();
310 0 : m_pRbMax.clear();
311 0 : m_pRbMin.clear();
312 0 : m_pRbValue.clear();
313 0 : m_pEdTargetValue.clear();
314 0 : m_pRBTargetValue.clear();
315 0 : m_pFtVariableCells.clear();
316 0 : m_pEdVariableCells.clear();
317 0 : m_pRBVariableCells.clear();
318 0 : m_pFtCellRef.clear();
319 0 : m_pEdLeft1.clear();
320 0 : m_pRBLeft1.clear();
321 0 : m_pFtOperator.clear();
322 0 : m_pLbOp1.clear();
323 0 : m_pFtConstraint.clear();
324 0 : m_pEdRight1.clear();
325 0 : m_pRBRight1.clear();
326 0 : m_pBtnDel1.clear();
327 0 : m_pEdLeft2.clear();
328 0 : m_pRBLeft2.clear();
329 0 : m_pLbOp2.clear();
330 0 : m_pEdRight2.clear();
331 0 : m_pRBRight2.clear();
332 0 : m_pBtnDel2.clear();
333 0 : m_pEdLeft3.clear();
334 0 : m_pRBLeft3.clear();
335 0 : m_pLbOp3.clear();
336 0 : m_pEdRight3.clear();
337 0 : m_pRBRight3.clear();
338 0 : m_pBtnDel3.clear();
339 0 : m_pEdLeft4.clear();
340 0 : m_pRBLeft4.clear();
341 0 : m_pLbOp4.clear();
342 0 : m_pEdRight4.clear();
343 0 : m_pRBRight4.clear();
344 0 : m_pBtnDel4.clear();
345 0 : m_pScrollBar.clear();
346 0 : m_pBtnOpt.clear();
347 0 : m_pBtnCancel.clear();
348 0 : m_pBtnSolve.clear();
349 0 : mpEdActive.clear();
350 0 : for (auto p : mpLeftButton)
351 0 : p.clear();
352 0 : for (auto p : mpRightButton)
353 0 : p.clear();
354 0 : for (auto p : mpOperator)
355 0 : p.clear();
356 0 : for (auto p : mpDelButton)
357 0 : p.clear();
358 0 : ScAnyRefDlg::dispose();
359 0 : }
360 :
361 0 : void ScOptSolverDlg::Init(const ScAddress& rCursorPos)
362 : {
363 : // Get the "Delete Rows" commandimagelist images from sfx instead of
364 : // adding a second copy to sc (see ScTbxInsertCtrl::StateChanged)
365 :
366 0 : OUString aSlotURL( "slot:" );
367 0 : aSlotURL += OUString::number( SID_DEL_ROWS );
368 0 : uno::Reference<frame::XFrame> xFrame = GetBindings().GetActiveFrame();
369 0 : Image aDelNm = ::GetImage( xFrame, aSlotURL, false );
370 :
371 0 : for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
372 : {
373 0 : mpDelButton[nRow]->SetModeImage( aDelNm );
374 : }
375 :
376 0 : m_pBtnOpt->SetClickHdl( LINK( this, ScOptSolverDlg, BtnHdl ) );
377 0 : m_pBtnCancel->SetClickHdl( LINK( this, ScOptSolverDlg, BtnHdl ) );
378 0 : m_pBtnSolve->SetClickHdl( LINK( this, ScOptSolverDlg, BtnHdl ) );
379 :
380 0 : Link<> aLink = LINK( this, ScOptSolverDlg, GetFocusHdl );
381 0 : m_pEdObjectiveCell->SetGetFocusHdl( aLink );
382 0 : m_pRBObjectiveCell->SetGetFocusHdl( aLink );
383 0 : m_pEdTargetValue->SetGetFocusHdl( aLink );
384 0 : m_pRBTargetValue->SetGetFocusHdl( aLink );
385 0 : m_pEdVariableCells->SetGetFocusHdl( aLink );
386 0 : m_pRBVariableCells->SetGetFocusHdl( aLink );
387 0 : m_pRbValue->SetGetFocusHdl( aLink );
388 0 : for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
389 : {
390 0 : mpLeftEdit[nRow]->SetGetFocusHdl( aLink );
391 0 : mpLeftButton[nRow]->SetGetFocusHdl( aLink );
392 0 : mpRightEdit[nRow]->SetGetFocusHdl( aLink );
393 0 : mpRightButton[nRow]->SetGetFocusHdl( aLink );
394 0 : mpOperator[nRow]->SetGetFocusHdl( aLink );
395 : }
396 :
397 0 : aLink = LINK( this, ScOptSolverDlg, LoseFocusHdl );
398 0 : m_pEdObjectiveCell->SetLoseFocusHdl( aLink );
399 0 : m_pRBObjectiveCell->SetLoseFocusHdl( aLink );
400 0 : m_pEdTargetValue->SetLoseFocusHdl( aLink );
401 0 : m_pRBTargetValue-> SetLoseFocusHdl( aLink );
402 0 : m_pEdVariableCells->SetLoseFocusHdl( aLink );
403 0 : m_pRBVariableCells->SetLoseFocusHdl( aLink );
404 0 : for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
405 : {
406 0 : mpLeftEdit[nRow]->SetLoseFocusHdl( aLink );
407 0 : mpLeftButton[nRow]->SetLoseFocusHdl( aLink );
408 0 : mpRightEdit[nRow]->SetLoseFocusHdl( aLink );
409 0 : mpRightButton[nRow]->SetLoseFocusHdl( aLink );
410 : }
411 :
412 0 : Link<> aCursorUp = LINK( this, ScOptSolverDlg, CursorUpHdl );
413 0 : Link<> aCursorDown = LINK( this, ScOptSolverDlg, CursorDownHdl );
414 0 : Link<> aCondModify = LINK( this, ScOptSolverDlg, CondModifyHdl );
415 0 : for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
416 : {
417 0 : mpLeftEdit[nRow]->SetCursorLinks( aCursorUp, aCursorDown );
418 0 : mpRightEdit[nRow]->SetCursorLinks( aCursorUp, aCursorDown );
419 0 : mpLeftEdit[nRow]->SetModifyHdl( aCondModify );
420 0 : mpRightEdit[nRow]->SetModifyHdl( aCondModify );
421 0 : mpDelButton[nRow]->SetClickHdl( LINK( this, ScOptSolverDlg, DelBtnHdl ) );
422 0 : mpOperator[nRow]->SetSelectHdl( LINK( this, ScOptSolverDlg, SelectHdl ) );
423 : }
424 0 : m_pEdTargetValue->SetModifyHdl( LINK( this, ScOptSolverDlg, TargetModifyHdl ) );
425 :
426 0 : m_pScrollBar->SetEndScrollHdl( LINK( this, ScOptSolverDlg, ScrollHdl ) );
427 0 : m_pScrollBar->SetScrollHdl( LINK( this, ScOptSolverDlg, ScrollHdl ) );
428 :
429 0 : m_pScrollBar->SetPageSize( EDIT_ROW_COUNT );
430 0 : m_pScrollBar->SetVisibleSize( EDIT_ROW_COUNT );
431 0 : m_pScrollBar->SetLineSize( 1 );
432 : // Range is set in ShowConditions
433 :
434 : // get available solver implementations
435 : //! sort by descriptions?
436 0 : ScSolverUtil::GetImplementations( maImplNames, maDescriptions );
437 0 : sal_Int32 nImplCount = maImplNames.getLength();
438 :
439 0 : const ScOptSolverSave* pOldData = mpDocShell->GetSolverSaveData();
440 0 : if ( pOldData )
441 : {
442 0 : m_pEdObjectiveCell->SetRefString( pOldData->GetObjective() );
443 0 : m_pRbMax->Check( pOldData->GetMax() );
444 0 : m_pRbMin->Check( pOldData->GetMin() );
445 0 : m_pRbValue->Check( pOldData->GetValue() );
446 0 : m_pEdTargetValue->SetRefString( pOldData->GetTarget() );
447 0 : m_pEdVariableCells->SetRefString( pOldData->GetVariable() );
448 0 : maConditions = pOldData->GetConditions();
449 0 : maEngine = pOldData->GetEngine();
450 0 : maProperties = pOldData->GetProperties();
451 : }
452 : else
453 : {
454 0 : m_pRbMax->Check();
455 0 : OUString aCursorStr;
456 0 : if ( !mrDoc.GetRangeAtBlock( ScRange(rCursorPos), &aCursorStr ) )
457 0 : aCursorStr = rCursorPos.Format(SCA_ABS, NULL, mrDoc.GetAddressConvention());
458 0 : m_pEdObjectiveCell->SetRefString( aCursorStr );
459 0 : if ( nImplCount > 0 )
460 0 : maEngine = maImplNames[0]; // use first implementation
461 : }
462 0 : ShowConditions();
463 :
464 0 : m_pEdObjectiveCell->GrabFocus();
465 0 : mpEdActive = m_pEdObjectiveCell;
466 0 : }
467 :
468 0 : void ScOptSolverDlg::ReadConditions()
469 : {
470 0 : for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
471 : {
472 0 : ScOptConditionRow aRowEntry;
473 0 : aRowEntry.aLeftStr = mpLeftEdit[nRow]->GetText();
474 0 : aRowEntry.aRightStr = mpRightEdit[nRow]->GetText();
475 0 : aRowEntry.nOperator = mpOperator[nRow]->GetSelectEntryPos();
476 :
477 0 : long nVecPos = nScrollPos + nRow;
478 0 : if ( nVecPos >= (long)maConditions.size() && !aRowEntry.IsDefault() )
479 0 : maConditions.resize( nVecPos + 1 );
480 :
481 0 : if ( nVecPos < (long)maConditions.size() )
482 0 : maConditions[nVecPos] = aRowEntry;
483 :
484 : // remove default entries at the end
485 0 : size_t nSize = maConditions.size();
486 0 : while ( nSize > 0 && maConditions[ nSize-1 ].IsDefault() )
487 0 : --nSize;
488 0 : maConditions.resize( nSize );
489 0 : }
490 0 : }
491 :
492 0 : void ScOptSolverDlg::ShowConditions()
493 : {
494 0 : for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
495 : {
496 0 : ScOptConditionRow aRowEntry;
497 :
498 0 : long nVecPos = nScrollPos + nRow;
499 0 : if ( nVecPos < (long)maConditions.size() )
500 0 : aRowEntry = maConditions[nVecPos];
501 :
502 0 : mpLeftEdit[nRow]->SetRefString( aRowEntry.aLeftStr );
503 0 : mpRightEdit[nRow]->SetRefString( aRowEntry.aRightStr );
504 0 : mpOperator[nRow]->SelectEntryPos( aRowEntry.nOperator );
505 0 : }
506 :
507 : // allow to scroll one page behind the visible or stored rows
508 0 : long nVisible = nScrollPos + EDIT_ROW_COUNT;
509 0 : long nMax = std::max( nVisible, (long) maConditions.size() );
510 0 : m_pScrollBar->SetRange( Range( 0, nMax + EDIT_ROW_COUNT ) );
511 0 : m_pScrollBar->SetThumbPos( nScrollPos );
512 :
513 0 : EnableButtons();
514 0 : }
515 :
516 0 : void ScOptSolverDlg::EnableButtons()
517 : {
518 0 : for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
519 : {
520 0 : long nVecPos = nScrollPos + nRow;
521 0 : mpDelButton[nRow]->Enable( nVecPos < (long)maConditions.size() );
522 : }
523 0 : }
524 :
525 0 : bool ScOptSolverDlg::Close()
526 : {
527 0 : return DoClose( ScOptSolverDlgWrapper::GetChildWindowId() );
528 : }
529 :
530 0 : void ScOptSolverDlg::SetActive()
531 : {
532 0 : if ( mbDlgLostFocus )
533 : {
534 0 : mbDlgLostFocus = false;
535 0 : if( mpEdActive )
536 0 : mpEdActive->GrabFocus();
537 : }
538 : else
539 : {
540 0 : GrabFocus();
541 : }
542 0 : RefInputDone();
543 0 : }
544 :
545 0 : void ScOptSolverDlg::SetReference( const ScRange& rRef, ScDocument* pDocP )
546 : {
547 0 : if( mpEdActive )
548 : {
549 0 : if ( rRef.aStart != rRef.aEnd )
550 0 : RefInputStart(mpEdActive);
551 :
552 : // "target"/"value": single cell
553 0 : bool bSingle = ( mpEdActive == m_pEdObjectiveCell || mpEdActive == m_pEdTargetValue );
554 :
555 0 : OUString aStr;
556 0 : ScAddress aAdr = rRef.aStart;
557 0 : ScRange aNewRef( rRef );
558 0 : if ( bSingle )
559 0 : aNewRef.aEnd = aAdr;
560 :
561 0 : OUString aName;
562 0 : if ( pDocP->GetRangeAtBlock( aNewRef, &aName ) ) // named range: show name
563 0 : aStr = aName;
564 : else // format cell/range reference
565 : {
566 0 : sal_uInt16 nFmt = ( aAdr.Tab() == mnCurTab ) ? SCA_ABS : SCA_ABS_3D;
567 0 : if ( bSingle )
568 0 : aStr = aAdr.Format(nFmt, pDocP, pDocP->GetAddressConvention());
569 : else
570 0 : aStr = rRef.Format(nFmt | SCR_ABS, pDocP, pDocP->GetAddressConvention());
571 : }
572 :
573 : // variable cells can be several ranges, so only the selection is replaced
574 0 : if ( mpEdActive == m_pEdVariableCells )
575 : {
576 0 : OUString aVal = mpEdActive->GetText();
577 0 : Selection aSel = mpEdActive->GetSelection();
578 0 : aSel.Justify();
579 0 : aVal = aVal.replaceAt( aSel.Min(), aSel.Len(), aStr );
580 0 : Selection aNewSel( aSel.Min(), aSel.Min()+aStr.getLength() );
581 0 : mpEdActive->SetRefString( aVal );
582 0 : mpEdActive->SetSelection( aNewSel );
583 : }
584 : else
585 0 : mpEdActive->SetRefString( aStr );
586 :
587 0 : ReadConditions();
588 0 : EnableButtons();
589 :
590 : // select "Value of" if a ref is input into "target" edit
591 0 : if ( mpEdActive == m_pEdTargetValue )
592 0 : m_pRbValue->Check();
593 : }
594 0 : }
595 :
596 0 : bool ScOptSolverDlg::IsRefInputMode() const
597 : {
598 0 : return mpEdActive != nullptr;
599 : }
600 :
601 : // Handler:
602 :
603 0 : IMPL_LINK( ScOptSolverDlg, BtnHdl, PushButton*, pBtn )
604 : {
605 0 : if ( pBtn == m_pBtnSolve || pBtn == m_pBtnCancel )
606 : {
607 0 : bool bSolve = ( pBtn == m_pBtnSolve );
608 :
609 0 : SetDispatcherLock( false );
610 0 : SwitchToDocument();
611 :
612 0 : bool bClose = true;
613 0 : if ( bSolve )
614 0 : bClose = CallSolver();
615 :
616 0 : if ( bClose )
617 : {
618 : // Close: write dialog settings to DocShell for subsequent calls
619 0 : ReadConditions();
620 : ScOptSolverSave aSave(
621 0 : m_pEdObjectiveCell->GetText(), m_pRbMax->IsChecked(), m_pRbMin->IsChecked(), m_pRbValue->IsChecked(),
622 0 : m_pEdTargetValue->GetText(), m_pEdVariableCells->GetText(), maConditions, maEngine, maProperties );
623 0 : mpDocShell->SetSolverSaveData( aSave );
624 0 : Close();
625 : }
626 : else
627 : {
628 : // no solution -> dialog is kept open
629 0 : SetDispatcherLock( true );
630 : }
631 : }
632 0 : else if ( pBtn == m_pBtnOpt )
633 : {
634 : //! move options dialog to UI lib?
635 : ScopedVclPtr<ScSolverOptionsDialog> pOptDlg(
636 0 : VclPtr<ScSolverOptionsDialog>::Create( this, maImplNames, maDescriptions, maEngine, maProperties ));
637 0 : if ( pOptDlg->Execute() == RET_OK )
638 : {
639 0 : maEngine = pOptDlg->GetEngine();
640 0 : maProperties = pOptDlg->GetProperties();
641 0 : }
642 : }
643 :
644 0 : return 0;
645 : }
646 :
647 0 : IMPL_LINK( ScOptSolverDlg, GetFocusHdl, Control*, pCtrl )
648 : {
649 0 : Edit* pEdit = NULL;
650 0 : mpEdActive = NULL;
651 :
652 0 : if( pCtrl == m_pEdObjectiveCell || pCtrl == m_pRBObjectiveCell )
653 0 : pEdit = mpEdActive = m_pEdObjectiveCell;
654 0 : else if( pCtrl == m_pEdTargetValue || pCtrl == m_pRBTargetValue )
655 0 : pEdit = mpEdActive = m_pEdTargetValue;
656 0 : else if( pCtrl == m_pEdVariableCells || pCtrl == m_pRBVariableCells )
657 0 : pEdit = mpEdActive = m_pEdVariableCells;
658 0 : for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
659 : {
660 0 : if( pCtrl == mpLeftEdit[nRow] || pCtrl == mpLeftButton[nRow] )
661 0 : pEdit = mpEdActive = mpLeftEdit[nRow].get();
662 0 : else if( pCtrl == mpRightEdit[nRow] || pCtrl == mpRightButton[nRow] )
663 0 : pEdit = mpEdActive = mpRightEdit[nRow].get();
664 0 : else if( pCtrl == mpOperator[nRow] ) // focus on "operator" list box
665 0 : mpEdActive = mpRightEdit[nRow].get(); // use right edit for ref input, but don't change selection
666 : }
667 0 : if( pCtrl == m_pRbValue ) // focus on "Value of" radio button
668 0 : mpEdActive = m_pEdTargetValue; // use value edit for ref input, but don't change selection
669 :
670 0 : if( pEdit )
671 0 : pEdit->SetSelection( Selection( 0, SELECTION_MAX ) );
672 :
673 0 : return 0;
674 : }
675 :
676 0 : IMPL_LINK_NOARG(ScOptSolverDlg, LoseFocusHdl)
677 : {
678 0 : mbDlgLostFocus = !IsActive();
679 0 : return 0;
680 : }
681 :
682 0 : IMPL_LINK( ScOptSolverDlg, DelBtnHdl, PushButton*, pBtn )
683 : {
684 0 : for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
685 0 : if( pBtn == mpDelButton[nRow] )
686 : {
687 0 : bool bHadFocus = pBtn->HasFocus();
688 :
689 0 : ReadConditions();
690 0 : long nVecPos = nScrollPos + nRow;
691 0 : if ( nVecPos < (long)maConditions.size() )
692 : {
693 0 : maConditions.erase( maConditions.begin() + nVecPos );
694 0 : ShowConditions();
695 :
696 0 : if ( bHadFocus && !pBtn->IsEnabled() )
697 : {
698 : // If the button is disabled, focus would normally move to the next control,
699 : // (left edit of the next row). Move it to left edit of this row instead.
700 :
701 0 : mpEdActive = mpLeftEdit[nRow].get();
702 0 : mpEdActive->GrabFocus();
703 : }
704 : }
705 : }
706 :
707 0 : return 0;
708 : }
709 :
710 0 : IMPL_LINK_NOARG(ScOptSolverDlg, TargetModifyHdl)
711 : {
712 : // modify handler for the target edit:
713 : // select "Value of" if something is input into the edit
714 0 : if ( !m_pEdTargetValue->GetText().isEmpty() )
715 0 : m_pRbValue->Check();
716 0 : return 0;
717 : }
718 :
719 0 : IMPL_LINK_NOARG(ScOptSolverDlg, CondModifyHdl)
720 : {
721 : // modify handler for the condition edits, just to enable/disable "delete" buttons
722 0 : ReadConditions();
723 0 : EnableButtons();
724 0 : return 0;
725 : }
726 :
727 0 : IMPL_LINK_NOARG(ScOptSolverDlg, SelectHdl)
728 : {
729 : // select handler for operator list boxes, just to enable/disable "delete" buttons
730 0 : ReadConditions();
731 0 : EnableButtons();
732 0 : return 0;
733 : }
734 :
735 0 : IMPL_LINK_NOARG(ScOptSolverDlg, ScrollHdl)
736 : {
737 0 : ReadConditions();
738 0 : nScrollPos = m_pScrollBar->GetThumbPos();
739 0 : ShowConditions();
740 0 : if( mpEdActive )
741 0 : mpEdActive->SetSelection( Selection( 0, SELECTION_MAX ) );
742 0 : return 0;
743 : }
744 :
745 0 : IMPL_LINK( ScOptSolverDlg, CursorUpHdl, ScCursorRefEdit*, pEdit )
746 : {
747 0 : if ( pEdit == mpLeftEdit[0] || pEdit == mpRightEdit[0] )
748 : {
749 0 : if ( nScrollPos > 0 )
750 : {
751 0 : ReadConditions();
752 0 : --nScrollPos;
753 0 : ShowConditions();
754 0 : if( mpEdActive )
755 0 : mpEdActive->SetSelection( Selection( 0, SELECTION_MAX ) );
756 : }
757 : }
758 : else
759 : {
760 0 : formula::RefEdit* pFocus = NULL;
761 0 : for ( sal_uInt16 nRow = 1; nRow < EDIT_ROW_COUNT; ++nRow ) // second row or below: move focus
762 : {
763 0 : if ( pEdit == mpLeftEdit[nRow] )
764 0 : pFocus = mpLeftEdit[nRow-1];
765 0 : else if ( pEdit == mpRightEdit[nRow] )
766 0 : pFocus = mpRightEdit[nRow-1];
767 : }
768 0 : if (pFocus)
769 : {
770 0 : mpEdActive = pFocus;
771 0 : pFocus->GrabFocus();
772 : }
773 : }
774 :
775 0 : return 0;
776 : }
777 :
778 0 : IMPL_LINK( ScOptSolverDlg, CursorDownHdl, ScCursorRefEdit*, pEdit )
779 : {
780 0 : if ( pEdit == mpLeftEdit[EDIT_ROW_COUNT-1] || pEdit == mpRightEdit[EDIT_ROW_COUNT-1] )
781 : {
782 : //! limit scroll position?
783 0 : ReadConditions();
784 0 : ++nScrollPos;
785 0 : ShowConditions();
786 0 : if( mpEdActive )
787 0 : mpEdActive->SetSelection( Selection( 0, SELECTION_MAX ) );
788 : }
789 : else
790 : {
791 0 : formula::RefEdit* pFocus = NULL;
792 0 : for ( sal_uInt16 nRow = 0; nRow+1 < EDIT_ROW_COUNT; ++nRow ) // before last row: move focus
793 : {
794 0 : if ( pEdit == mpLeftEdit[nRow] )
795 0 : pFocus = mpLeftEdit[nRow+1];
796 0 : else if ( pEdit == mpRightEdit[nRow] )
797 0 : pFocus = mpRightEdit[nRow+1];
798 : }
799 0 : if (pFocus)
800 : {
801 0 : mpEdActive = pFocus;
802 0 : pFocus->GrabFocus();
803 : }
804 : }
805 :
806 0 : return 0;
807 : }
808 :
809 0 : void ScOptSolverDlg::ShowError( bool bCondition, formula::RefEdit* pFocus )
810 : {
811 0 : OUString aMessage = bCondition ? maConditionError : maInputError;
812 0 : ScopedVclPtrInstance<MessageDialog>::Create(this, aMessage)->Execute();
813 0 : if (pFocus)
814 : {
815 0 : mpEdActive = pFocus;
816 0 : pFocus->GrabFocus();
817 0 : }
818 0 : }
819 :
820 0 : bool ScOptSolverDlg::ParseRef( ScRange& rRange, const OUString& rInput, bool bAllowRange )
821 : {
822 0 : ScRangeUtil aRangeUtil;
823 0 : ScAddress::Details aDetails(mrDoc.GetAddressConvention(), 0, 0);
824 0 : sal_uInt16 nFlags = rRange.ParseAny( rInput, &mrDoc, aDetails );
825 0 : if ( nFlags & SCA_VALID )
826 : {
827 0 : if ( (nFlags & SCA_TAB_3D) == 0 )
828 0 : rRange.aStart.SetTab( mnCurTab );
829 0 : if ( (nFlags & SCA_TAB2_3D) == 0 )
830 0 : rRange.aEnd.SetTab( rRange.aStart.Tab() );
831 0 : return ( bAllowRange || rRange.aStart == rRange.aEnd );
832 : }
833 0 : else if ( ScRangeUtil::MakeRangeFromName( rInput, &mrDoc, mnCurTab, rRange, RUTL_NAMES, aDetails ) )
834 0 : return ( bAllowRange || rRange.aStart == rRange.aEnd );
835 :
836 0 : return false; // not recognized
837 : }
838 :
839 0 : bool ScOptSolverDlg::FindTimeout( sal_Int32& rTimeout )
840 : {
841 0 : bool bFound = false;
842 :
843 0 : if ( !maProperties.getLength() )
844 0 : maProperties = ScSolverUtil::GetDefaults( maEngine ); // get property defaults from component
845 :
846 0 : sal_Int32 nPropCount = maProperties.getLength();
847 0 : for (sal_Int32 nProp=0; nProp<nPropCount && !bFound; ++nProp)
848 : {
849 0 : const beans::PropertyValue& rValue = maProperties[nProp];
850 0 : if ( rValue.Name == SC_UNONAME_TIMEOUT )
851 0 : bFound = ( rValue.Value >>= rTimeout );
852 : }
853 0 : return bFound;
854 : }
855 :
856 0 : bool ScOptSolverDlg::CallSolver() // return true -> close dialog after calling
857 : {
858 : // show progress dialog
859 :
860 0 : ScopedVclPtrInstance< ScSolverProgressDialog > aProgress( this );
861 0 : sal_Int32 nTimeout = 0;
862 0 : if ( FindTimeout( nTimeout ) )
863 0 : aProgress->SetTimeLimit( nTimeout );
864 : else
865 0 : aProgress->HideTimeLimit();
866 0 : aProgress->Show();
867 0 : aProgress->Update();
868 0 : aProgress->Sync();
869 : // try to make sure the progress dialog is painted before continuing
870 0 : Application::Reschedule(true);
871 :
872 : // collect solver parameters
873 :
874 0 : ReadConditions();
875 :
876 0 : uno::Reference<sheet::XSpreadsheetDocument> xDocument( mpDocShell->GetModel(), uno::UNO_QUERY );
877 :
878 0 : ScRange aObjRange;
879 0 : if ( !ParseRef( aObjRange, m_pEdObjectiveCell->GetText(), false ) )
880 : {
881 0 : ShowError( false, m_pEdObjectiveCell );
882 0 : return false;
883 : }
884 0 : table::CellAddress aObjective( aObjRange.aStart.Tab(), aObjRange.aStart.Col(), aObjRange.aStart.Row() );
885 :
886 : // "changing cells" can be several ranges
887 0 : ScRangeList aVarRanges;
888 0 : if ( !ParseWithNames( aVarRanges, m_pEdVariableCells->GetText(), &mrDoc ) )
889 : {
890 0 : ShowError( false, m_pEdVariableCells );
891 0 : return false;
892 : }
893 0 : uno::Sequence<table::CellAddress> aVariables;
894 0 : sal_Int32 nVarPos = 0;
895 :
896 0 : for ( size_t nRangePos=0, nRange = aVarRanges.size(); nRangePos < nRange; ++nRangePos )
897 : {
898 0 : ScRange aRange(*aVarRanges[ nRangePos ] );
899 0 : aRange.Justify();
900 0 : SCTAB nTab = aRange.aStart.Tab();
901 :
902 : // resolve into single cells
903 :
904 0 : sal_Int32 nAdd = ( aRange.aEnd.Col() - aRange.aStart.Col() + 1 ) *
905 0 : ( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
906 0 : aVariables.realloc( nVarPos + nAdd );
907 :
908 0 : for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
909 0 : for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
910 0 : aVariables[nVarPos++] = table::CellAddress( nTab, nCol, nRow );
911 : }
912 :
913 0 : uno::Sequence<sheet::SolverConstraint> aConstraints;
914 0 : sal_Int32 nConstrPos = 0;
915 0 : for ( std::vector<ScOptConditionRow>::const_iterator aConstrIter = maConditions.begin();
916 0 : aConstrIter != maConditions.end(); ++aConstrIter )
917 : {
918 0 : if ( !aConstrIter->aLeftStr.isEmpty() )
919 : {
920 0 : sheet::SolverConstraint aConstraint;
921 : // order of list box entries must match enum values
922 0 : aConstraint.Operator = static_cast<sheet::SolverConstraintOperator>(aConstrIter->nOperator);
923 :
924 0 : ScRange aLeftRange;
925 0 : if ( !ParseRef( aLeftRange, aConstrIter->aLeftStr, true ) )
926 : {
927 0 : ShowError( true, NULL );
928 0 : return false;
929 : }
930 :
931 0 : bool bIsRange = false;
932 0 : ScRange aRightRange;
933 0 : if ( ParseRef( aRightRange, aConstrIter->aRightStr, true ) )
934 : {
935 0 : if ( aRightRange.aStart == aRightRange.aEnd )
936 0 : aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
937 0 : aRightRange.aStart.Col(), aRightRange.aStart.Row() );
938 0 : else if ( aRightRange.aEnd.Col()-aRightRange.aStart.Col() == aLeftRange.aEnd.Col()-aLeftRange.aStart.Col() &&
939 0 : aRightRange.aEnd.Row()-aRightRange.aStart.Row() == aLeftRange.aEnd.Row()-aLeftRange.aStart.Row() )
940 0 : bIsRange = true; // same size as "left" range, resolve into single cells
941 : else
942 : {
943 0 : ShowError( true, NULL );
944 0 : return false;
945 : }
946 : }
947 : else
948 : {
949 0 : sal_uInt32 nFormat = 0; //! explicit language?
950 0 : double fValue = 0.0;
951 0 : if ( mrDoc.GetFormatTable()->IsNumberFormat( aConstrIter->aRightStr, nFormat, fValue ) )
952 0 : aConstraint.Right <<= fValue;
953 0 : else if ( aConstraint.Operator != sheet::SolverConstraintOperator_INTEGER &&
954 0 : aConstraint.Operator != sheet::SolverConstraintOperator_BINARY )
955 : {
956 0 : ShowError( true, NULL );
957 0 : return false;
958 : }
959 : }
960 :
961 : // resolve into single cells
962 :
963 0 : sal_Int32 nAdd = ( aLeftRange.aEnd.Col() - aLeftRange.aStart.Col() + 1 ) *
964 0 : ( aLeftRange.aEnd.Row() - aLeftRange.aStart.Row() + 1 );
965 0 : aConstraints.realloc( nConstrPos + nAdd );
966 :
967 0 : for (SCROW nRow = aLeftRange.aStart.Row(); nRow <= aLeftRange.aEnd.Row(); ++nRow)
968 0 : for (SCCOL nCol = aLeftRange.aStart.Col(); nCol <= aLeftRange.aEnd.Col(); ++nCol)
969 : {
970 0 : aConstraint.Left = table::CellAddress( aLeftRange.aStart.Tab(), nCol, nRow );
971 0 : if ( bIsRange )
972 0 : aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
973 0 : aRightRange.aStart.Col() + ( nCol - aLeftRange.aStart.Col() ),
974 0 : aRightRange.aStart.Row() + ( nRow - aLeftRange.aStart.Row() ) );
975 :
976 0 : aConstraints[nConstrPos++] = aConstraint;
977 0 : }
978 : }
979 : }
980 :
981 0 : bool bMaximize = m_pRbMax->IsChecked();
982 0 : if ( m_pRbValue->IsChecked() )
983 : {
984 : // handle "value of" with an additional constraint (and then minimize)
985 :
986 0 : sheet::SolverConstraint aConstraint;
987 0 : aConstraint.Left = aObjective;
988 0 : aConstraint.Operator = sheet::SolverConstraintOperator_EQUAL;
989 :
990 0 : OUString aValStr = m_pEdTargetValue->GetText();
991 0 : ScRange aRightRange;
992 0 : if ( ParseRef( aRightRange, aValStr, false ) )
993 0 : aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
994 0 : aRightRange.aStart.Col(), aRightRange.aStart.Row() );
995 : else
996 : {
997 0 : sal_uInt32 nFormat = 0; //! explicit language?
998 0 : double fValue = 0.0;
999 0 : if ( mrDoc.GetFormatTable()->IsNumberFormat( aValStr, nFormat, fValue ) )
1000 0 : aConstraint.Right <<= fValue;
1001 : else
1002 : {
1003 0 : ShowError( false, m_pEdTargetValue );
1004 0 : return false;
1005 : }
1006 : }
1007 :
1008 0 : aConstraints.realloc( nConstrPos + 1 );
1009 0 : aConstraints[nConstrPos++] = aConstraint;
1010 : }
1011 :
1012 : // copy old document values
1013 :
1014 0 : sal_Int32 nVarCount = aVariables.getLength();
1015 0 : uno::Sequence<double> aOldValues;
1016 0 : aOldValues.realloc( nVarCount );
1017 0 : for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
1018 : {
1019 0 : ScAddress aCellPos;
1020 0 : ScUnoConversion::FillScAddress( aCellPos, aVariables[nVarPos] );
1021 0 : aOldValues[nVarPos] = mrDoc.GetValue( aCellPos );
1022 : }
1023 :
1024 : // create and initialize solver
1025 :
1026 0 : uno::Reference<sheet::XSolver> xSolver = ScSolverUtil::GetSolver( maEngine );
1027 : OSL_ENSURE( xSolver.is(), "can't get solver component" );
1028 0 : if ( !xSolver.is() )
1029 0 : return false;
1030 :
1031 0 : xSolver->setDocument( xDocument );
1032 0 : xSolver->setObjective( aObjective );
1033 0 : xSolver->setVariables( aVariables );
1034 0 : xSolver->setConstraints( aConstraints );
1035 0 : xSolver->setMaximize( bMaximize );
1036 :
1037 : // set options
1038 0 : uno::Reference<beans::XPropertySet> xOptProp(xSolver, uno::UNO_QUERY);
1039 0 : if ( xOptProp.is() )
1040 : {
1041 0 : sal_Int32 nPropCount = maProperties.getLength();
1042 0 : for (sal_Int32 nProp=0; nProp<nPropCount; ++nProp)
1043 : {
1044 0 : const beans::PropertyValue& rValue = maProperties[nProp];
1045 : try
1046 : {
1047 0 : xOptProp->setPropertyValue( rValue.Name, rValue.Value );
1048 : }
1049 0 : catch ( uno::Exception & )
1050 : {
1051 : OSL_FAIL("Exception in solver option property");
1052 : }
1053 : }
1054 : }
1055 :
1056 0 : xSolver->solve();
1057 0 : bool bSuccess = xSolver->getSuccess();
1058 :
1059 0 : aProgress->Hide();
1060 0 : bool bClose = false;
1061 0 : bool bRestore = true; // restore old values unless a solution is accepted
1062 0 : if ( bSuccess )
1063 : {
1064 : // put solution into document so it is visible when asking
1065 0 : uno::Sequence<double> aSolution = xSolver->getSolution();
1066 0 : if ( aSolution.getLength() == nVarCount )
1067 : {
1068 0 : mpDocShell->LockPaint();
1069 0 : ScDocFunc &rFunc = mpDocShell->GetDocFunc();
1070 0 : for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
1071 : {
1072 0 : ScAddress aCellPos;
1073 0 : ScUnoConversion::FillScAddress( aCellPos, aVariables[nVarPos] );
1074 0 : rFunc.SetValueCell(aCellPos, aSolution[nVarPos], false);
1075 : }
1076 0 : mpDocShell->UnlockPaint();
1077 : }
1078 : //! else error?
1079 :
1080 : // take formatted result from document (result value from component is ignored)
1081 : OUString aResultStr = mrDoc.GetString(
1082 : static_cast<SCCOL>(aObjective.Column), static_cast<SCROW>(aObjective.Row),
1083 0 : static_cast<SCTAB>(aObjective.Sheet));
1084 :
1085 0 : ScopedVclPtrInstance< ScSolverSuccessDialog > aDialog( this, aResultStr );
1086 0 : if ( aDialog->Execute() == RET_OK )
1087 : {
1088 : // keep results and close dialog
1089 0 : bRestore = false;
1090 0 : bClose = true;
1091 0 : }
1092 : }
1093 : else
1094 : {
1095 0 : OUString aError;
1096 0 : uno::Reference<sheet::XSolverDescription> xDesc( xSolver, uno::UNO_QUERY );
1097 0 : if ( xDesc.is() )
1098 0 : aError = xDesc->getStatusDescription(); // error description from component
1099 0 : ScopedVclPtrInstance< ScSolverNoSolutionDialog > aDialog( this, aError );
1100 0 : aDialog->Execute();
1101 : }
1102 :
1103 0 : if ( bRestore ) // restore old values
1104 : {
1105 0 : mpDocShell->LockPaint();
1106 0 : ScDocFunc &rFunc = mpDocShell->GetDocFunc();
1107 0 : for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
1108 : {
1109 0 : ScAddress aCellPos;
1110 0 : ScUnoConversion::FillScAddress( aCellPos, aVariables[nVarPos] );
1111 0 : rFunc.SetValueCell(aCellPos, aOldValues[nVarPos], false);
1112 : }
1113 0 : mpDocShell->UnlockPaint();
1114 : }
1115 :
1116 0 : return bClose;
1117 156 : }
1118 :
1119 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|