xref: /AOO41X/main/sc/source/ui/miscdlgs/optsolver.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_sc.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir //----------------------------------------------------------------------------
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include "rangelst.hxx"
34*cdf0e10cSrcweir #include "scitems.hxx"
35*cdf0e10cSrcweir #include <sfx2/bindings.hxx>
36*cdf0e10cSrcweir #include <sfx2/imagemgr.hxx>
37*cdf0e10cSrcweir #include <svl/zforlist.hxx>
38*cdf0e10cSrcweir #include <vcl/msgbox.hxx>
39*cdf0e10cSrcweir #include <vcl/svapp.hxx>
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #include "uiitems.hxx"
42*cdf0e10cSrcweir #include "reffact.hxx"
43*cdf0e10cSrcweir #include "docsh.hxx"
44*cdf0e10cSrcweir #include "docfunc.hxx"
45*cdf0e10cSrcweir #include "cell.hxx"
46*cdf0e10cSrcweir #include "rangeutl.hxx"
47*cdf0e10cSrcweir #include "scresid.hxx"
48*cdf0e10cSrcweir #include "convuno.hxx"
49*cdf0e10cSrcweir #include "unonames.hxx"
50*cdf0e10cSrcweir #include "solveroptions.hxx"
51*cdf0e10cSrcweir #include "solverutil.hxx"
52*cdf0e10cSrcweir #include "optsolver.hrc"
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir #include "optsolver.hxx"
55*cdf0e10cSrcweir 
56*cdf0e10cSrcweir #include <com/sun/star/sheet/Solver.hpp>
57*cdf0e10cSrcweir #include <com/sun/star/sheet/XSolverDescription.hpp>
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir using namespace com::sun::star;
60*cdf0e10cSrcweir 
61*cdf0e10cSrcweir //----------------------------------------------------------------------------
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir ScSolverProgressDialog::ScSolverProgressDialog( Window* pParent )
64*cdf0e10cSrcweir     : ModelessDialog( pParent, ScResId( RID_SCDLG_SOLVER_PROGRESS ) ),
65*cdf0e10cSrcweir     maFtProgress    ( this, ScResId( FT_PROGRESS ) ),
66*cdf0e10cSrcweir     maFtTime        ( this, ScResId( FT_TIMELIMIT ) ),
67*cdf0e10cSrcweir     maFlButtons     ( this, ScResId( FL_BUTTONS ) ),
68*cdf0e10cSrcweir     maBtnOk         ( this, ScResId( BTN_OK ) )
69*cdf0e10cSrcweir {
70*cdf0e10cSrcweir     maBtnOk.Enable(sal_False);
71*cdf0e10cSrcweir     FreeResource();
72*cdf0e10cSrcweir }
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir ScSolverProgressDialog::~ScSolverProgressDialog()
75*cdf0e10cSrcweir {
76*cdf0e10cSrcweir }
77*cdf0e10cSrcweir 
78*cdf0e10cSrcweir void ScSolverProgressDialog::HideTimeLimit()
79*cdf0e10cSrcweir {
80*cdf0e10cSrcweir     maFtTime.Hide();
81*cdf0e10cSrcweir }
82*cdf0e10cSrcweir 
83*cdf0e10cSrcweir void ScSolverProgressDialog::SetTimeLimit( sal_Int32 nSeconds )
84*cdf0e10cSrcweir {
85*cdf0e10cSrcweir     String aOld = maFtTime.GetText();
86*cdf0e10cSrcweir     String aNew = aOld.GetToken(0,'#');
87*cdf0e10cSrcweir     aNew += String::CreateFromInt32( nSeconds );
88*cdf0e10cSrcweir     aNew += aOld.GetToken(1,'#');
89*cdf0e10cSrcweir     maFtTime.SetText( aNew );
90*cdf0e10cSrcweir }
91*cdf0e10cSrcweir 
92*cdf0e10cSrcweir //----------------------------------------------------------------------------
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir ScSolverNoSolutionDialog::ScSolverNoSolutionDialog( Window* pParent, const String& rErrorText )
95*cdf0e10cSrcweir     : ModalDialog( pParent, ScResId( RID_SCDLG_SOLVER_NOSOLUTION ) ),
96*cdf0e10cSrcweir     maFtNoSolution  ( this, ScResId( FT_NOSOLUTION ) ),
97*cdf0e10cSrcweir     maFtErrorText   ( this, ScResId( FT_ERRORTEXT ) ),
98*cdf0e10cSrcweir     maFlButtons     ( this, ScResId( FL_BUTTONS ) ),
99*cdf0e10cSrcweir     maBtnOk         ( this, ScResId( BTN_OK ) )
100*cdf0e10cSrcweir {
101*cdf0e10cSrcweir     maFtErrorText.SetText( rErrorText );
102*cdf0e10cSrcweir     FreeResource();
103*cdf0e10cSrcweir }
104*cdf0e10cSrcweir 
105*cdf0e10cSrcweir ScSolverNoSolutionDialog::~ScSolverNoSolutionDialog()
106*cdf0e10cSrcweir {
107*cdf0e10cSrcweir }
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir //----------------------------------------------------------------------------
110*cdf0e10cSrcweir 
111*cdf0e10cSrcweir ScSolverSuccessDialog::ScSolverSuccessDialog( Window* pParent, const String& rSolution )
112*cdf0e10cSrcweir     : ModalDialog( pParent, ScResId( RID_SCDLG_SOLVER_SUCCESS ) ),
113*cdf0e10cSrcweir     maFtSuccess     ( this, ScResId( FT_SUCCESS ) ),
114*cdf0e10cSrcweir     maFtResult      ( this, ScResId( FT_RESULT ) ),
115*cdf0e10cSrcweir     maFtQuestion    ( this, ScResId( FT_QUESTION ) ),
116*cdf0e10cSrcweir     maFlButtons     ( this, ScResId( FL_BUTTONS ) ),
117*cdf0e10cSrcweir     maBtnOk         ( this, ScResId( BTN_OK ) ),
118*cdf0e10cSrcweir     maBtnCancel     ( this, ScResId( BTN_CANCEL ) )
119*cdf0e10cSrcweir {
120*cdf0e10cSrcweir     String aMessage = maFtResult.GetText();
121*cdf0e10cSrcweir     aMessage.Append( (sal_Char) ' ' );
122*cdf0e10cSrcweir     aMessage.Append( rSolution );
123*cdf0e10cSrcweir     maFtResult.SetText( aMessage );
124*cdf0e10cSrcweir     FreeResource();
125*cdf0e10cSrcweir }
126*cdf0e10cSrcweir 
127*cdf0e10cSrcweir ScSolverSuccessDialog::~ScSolverSuccessDialog()
128*cdf0e10cSrcweir {
129*cdf0e10cSrcweir }
130*cdf0e10cSrcweir 
131*cdf0e10cSrcweir //----------------------------------------------------------------------------
132*cdf0e10cSrcweir 
133*cdf0e10cSrcweir ScCursorRefEdit::ScCursorRefEdit( ScAnyRefDlg* pParent, const ResId& rResId ) :
134*cdf0e10cSrcweir     formula::RefEdit( pParent, pParent, rResId )
135*cdf0e10cSrcweir {
136*cdf0e10cSrcweir }
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir void ScCursorRefEdit::SetCursorLinks( const Link& rUp, const Link& rDown )
139*cdf0e10cSrcweir {
140*cdf0e10cSrcweir     maCursorUpLink = rUp;
141*cdf0e10cSrcweir     maCursorDownLink = rDown;
142*cdf0e10cSrcweir }
143*cdf0e10cSrcweir 
144*cdf0e10cSrcweir void ScCursorRefEdit::KeyInput( const KeyEvent& rKEvt )
145*cdf0e10cSrcweir {
146*cdf0e10cSrcweir     KeyCode aCode = rKEvt.GetKeyCode();
147*cdf0e10cSrcweir     bool bUp = (aCode.GetCode() == KEY_UP);
148*cdf0e10cSrcweir     bool bDown = (aCode.GetCode() == KEY_DOWN);
149*cdf0e10cSrcweir     if ( !aCode.IsShift() && !aCode.IsMod1() && !aCode.IsMod2() && ( bUp || bDown ) )
150*cdf0e10cSrcweir     {
151*cdf0e10cSrcweir         if ( bUp )
152*cdf0e10cSrcweir             maCursorUpLink.Call( this );
153*cdf0e10cSrcweir         else
154*cdf0e10cSrcweir             maCursorDownLink.Call( this );
155*cdf0e10cSrcweir     }
156*cdf0e10cSrcweir     else
157*cdf0e10cSrcweir         formula::RefEdit::KeyInput( rKEvt );
158*cdf0e10cSrcweir }
159*cdf0e10cSrcweir 
160*cdf0e10cSrcweir //----------------------------------------------------------------------------
161*cdf0e10cSrcweir 
162*cdf0e10cSrcweir ScOptSolverSave::ScOptSolverSave( const String& rObjective, sal_Bool bMax, sal_Bool bMin, sal_Bool bValue,
163*cdf0e10cSrcweir                              const String& rTarget, const String& rVariable,
164*cdf0e10cSrcweir                              const std::vector<ScOptConditionRow>& rConditions,
165*cdf0e10cSrcweir                              const String& rEngine,
166*cdf0e10cSrcweir                              const uno::Sequence<beans::PropertyValue>& rProperties ) :
167*cdf0e10cSrcweir     maObjective( rObjective ),
168*cdf0e10cSrcweir     mbMax( bMax ),
169*cdf0e10cSrcweir     mbMin( bMin ),
170*cdf0e10cSrcweir     mbValue( bValue ),
171*cdf0e10cSrcweir     maTarget( rTarget ),
172*cdf0e10cSrcweir     maVariable( rVariable ),
173*cdf0e10cSrcweir     maConditions( rConditions ),
174*cdf0e10cSrcweir     maEngine( rEngine ),
175*cdf0e10cSrcweir     maProperties( rProperties )
176*cdf0e10cSrcweir {
177*cdf0e10cSrcweir }
178*cdf0e10cSrcweir 
179*cdf0e10cSrcweir //============================================================================
180*cdf0e10cSrcweir //  class ScOptSolverDlg
181*cdf0e10cSrcweir //----------------------------------------------------------------------------
182*cdf0e10cSrcweir 
183*cdf0e10cSrcweir ScOptSolverDlg::ScOptSolverDlg( SfxBindings* pB, SfxChildWindow* pCW, Window* pParent,
184*cdf0e10cSrcweir                           ScDocShell* pDocSh, ScAddress aCursorPos )
185*cdf0e10cSrcweir 
186*cdf0e10cSrcweir     :   ScAnyRefDlg         ( pB, pCW, pParent, RID_SCDLG_OPTSOLVER ),
187*cdf0e10cSrcweir         //
188*cdf0e10cSrcweir         maFtObjectiveCell   ( this, ScResId( FT_OBJECTIVECELL ) ),
189*cdf0e10cSrcweir         maEdObjectiveCell   ( this, this, ScResId( ED_OBJECTIVECELL ) ),
190*cdf0e10cSrcweir         maRBObjectiveCell   ( this, ScResId( IB_OBJECTIVECELL ), &maEdObjectiveCell, this ),
191*cdf0e10cSrcweir         maFtDirection       ( this, ScResId( FT_DIRECTION ) ),
192*cdf0e10cSrcweir         maRbMax             ( this, ScResId( RB_MAX ) ),
193*cdf0e10cSrcweir         maRbMin             ( this, ScResId( RB_MIN ) ),
194*cdf0e10cSrcweir         maRbValue           ( this, ScResId( RB_VALUE ) ),
195*cdf0e10cSrcweir         maEdTargetValue     ( this, this, ScResId( ED_TARGET ) ),
196*cdf0e10cSrcweir         maRBTargetValue     ( this, ScResId( IB_TARGET ), &maEdTargetValue, this ),
197*cdf0e10cSrcweir         maFtVariableCells   ( this, ScResId( FT_VARIABLECELLS ) ),
198*cdf0e10cSrcweir         maEdVariableCells   ( this, this, ScResId( ED_VARIABLECELLS ) ),
199*cdf0e10cSrcweir         maRBVariableCells   ( this, ScResId( IB_VARIABLECELLS ), &maEdVariableCells, this),
200*cdf0e10cSrcweir         maFlConditions      ( this, ScResId( FL_CONDITIONS ) ),
201*cdf0e10cSrcweir         maFtCellRef         ( this, ScResId( FT_CELLREF ) ),
202*cdf0e10cSrcweir         maEdLeft1           ( this, ScResId( ED_LEFT1 ) ),
203*cdf0e10cSrcweir         maRBLeft1           ( this, ScResId( IB_LEFT1 ), &maEdLeft1, this ),
204*cdf0e10cSrcweir         maFtOperator        ( this, ScResId( FT_OPERATOR ) ),
205*cdf0e10cSrcweir         maLbOp1             ( this, ScResId( LB_OP1 ) ),
206*cdf0e10cSrcweir         maFtConstraint      ( this, ScResId( FT_CONSTRAINT ) ),
207*cdf0e10cSrcweir         maEdRight1          ( this, ScResId( ED_RIGHT1 ) ),
208*cdf0e10cSrcweir         maRBRight1          ( this, ScResId( IB_RIGHT1 ), &maEdRight1, this ),
209*cdf0e10cSrcweir         maBtnDel1           ( this, ScResId( IB_DELETE1 ) ),
210*cdf0e10cSrcweir         maEdLeft2           ( this, ScResId( ED_LEFT2 ) ),
211*cdf0e10cSrcweir         maRBLeft2           ( this, ScResId( IB_LEFT2 ), &maEdLeft2, this ),
212*cdf0e10cSrcweir         maLbOp2             ( this, ScResId( LB_OP2 ) ),
213*cdf0e10cSrcweir         maEdRight2          ( this, ScResId( ED_RIGHT2 ) ),
214*cdf0e10cSrcweir         maRBRight2          ( this, ScResId( IB_RIGHT2 ), &maEdRight2, this ),
215*cdf0e10cSrcweir         maBtnDel2           ( this, ScResId( IB_DELETE2 ) ),
216*cdf0e10cSrcweir         maEdLeft3           ( this, ScResId( ED_LEFT3 ) ),
217*cdf0e10cSrcweir         maRBLeft3           ( this, ScResId( IB_LEFT3 ), &maEdLeft3, this ),
218*cdf0e10cSrcweir         maLbOp3             ( this, ScResId( LB_OP3 ) ),
219*cdf0e10cSrcweir         maEdRight3          ( this, ScResId( ED_RIGHT3 ) ),
220*cdf0e10cSrcweir         maRBRight3          ( this, ScResId( IB_RIGHT3 ), &maEdRight3, this ),
221*cdf0e10cSrcweir         maBtnDel3           ( this, ScResId( IB_DELETE3 ) ),
222*cdf0e10cSrcweir         maEdLeft4           ( this, ScResId( ED_LEFT4 ) ),
223*cdf0e10cSrcweir         maRBLeft4           ( this, ScResId( IB_LEFT4 ), &maEdLeft4, this ),
224*cdf0e10cSrcweir         maLbOp4             ( this, ScResId( LB_OP4 ) ),
225*cdf0e10cSrcweir         maEdRight4          ( this, ScResId( ED_RIGHT4 ) ),
226*cdf0e10cSrcweir         maRBRight4          ( this, ScResId( IB_RIGHT4 ), &maEdRight4, this ),
227*cdf0e10cSrcweir         maBtnDel4           ( this, ScResId( IB_DELETE4 ) ),
228*cdf0e10cSrcweir         maScrollBar         ( this, ScResId( SB_SCROLL ) ),
229*cdf0e10cSrcweir         maFlButtons         ( this, ScResId( FL_BUTTONS ) ),
230*cdf0e10cSrcweir         maBtnOpt            ( this, ScResId( BTN_OPTIONS ) ),
231*cdf0e10cSrcweir         maBtnHelp           ( this, ScResId( BTN_HELP ) ),
232*cdf0e10cSrcweir         maBtnCancel         ( this, ScResId( BTN_CLOSE ) ),
233*cdf0e10cSrcweir         maBtnSolve          ( this, ScResId( BTN_SOLVE ) ),
234*cdf0e10cSrcweir         maInputError        ( ScResId( STR_INVALIDINPUT ) ),
235*cdf0e10cSrcweir         maConditionError    ( ScResId( STR_INVALIDCONDITION ) ),
236*cdf0e10cSrcweir         //
237*cdf0e10cSrcweir         mpDocShell          ( pDocSh ),
238*cdf0e10cSrcweir         mpDoc               ( pDocSh->GetDocument() ),
239*cdf0e10cSrcweir         mnCurTab            ( aCursorPos.Tab() ),
240*cdf0e10cSrcweir         mpEdActive          ( NULL ),
241*cdf0e10cSrcweir         mbDlgLostFocus      ( false ),
242*cdf0e10cSrcweir         nScrollPos          ( 0 )
243*cdf0e10cSrcweir {
244*cdf0e10cSrcweir     mpLeftEdit[0]    = &maEdLeft1;
245*cdf0e10cSrcweir     mpLeftButton[0]  = &maRBLeft1;
246*cdf0e10cSrcweir     mpRightEdit[0]   = &maEdRight1;
247*cdf0e10cSrcweir     mpRightButton[0] = &maRBRight1;
248*cdf0e10cSrcweir     mpOperator[0]    = &maLbOp1;
249*cdf0e10cSrcweir     mpDelButton[0]   = &maBtnDel1;
250*cdf0e10cSrcweir 
251*cdf0e10cSrcweir     mpLeftEdit[1]    = &maEdLeft2;
252*cdf0e10cSrcweir     mpLeftButton[1]  = &maRBLeft2;
253*cdf0e10cSrcweir     mpRightEdit[1]   = &maEdRight2;
254*cdf0e10cSrcweir     mpRightButton[1] = &maRBRight2;
255*cdf0e10cSrcweir     mpOperator[1]    = &maLbOp2;
256*cdf0e10cSrcweir     mpDelButton[1]   = &maBtnDel2;
257*cdf0e10cSrcweir 
258*cdf0e10cSrcweir     mpLeftEdit[2]    = &maEdLeft3;
259*cdf0e10cSrcweir     mpLeftButton[2]  = &maRBLeft3;
260*cdf0e10cSrcweir     mpRightEdit[2]   = &maEdRight3;
261*cdf0e10cSrcweir     mpRightButton[2] = &maRBRight3;
262*cdf0e10cSrcweir     mpOperator[2]    = &maLbOp3;
263*cdf0e10cSrcweir     mpDelButton[2]   = &maBtnDel3;
264*cdf0e10cSrcweir 
265*cdf0e10cSrcweir     mpLeftEdit[3]    = &maEdLeft4;
266*cdf0e10cSrcweir     mpLeftButton[3]  = &maRBLeft4;
267*cdf0e10cSrcweir     mpRightEdit[3]   = &maEdRight4;
268*cdf0e10cSrcweir     mpRightButton[3] = &maRBRight4;
269*cdf0e10cSrcweir     mpOperator[3]    = &maLbOp4;
270*cdf0e10cSrcweir     mpDelButton[3]   = &maBtnDel4;
271*cdf0e10cSrcweir 
272*cdf0e10cSrcweir 	maRbMax.SetAccessibleRelationMemberOf(&maFtDirection);
273*cdf0e10cSrcweir 	maRbMin.SetAccessibleRelationMemberOf(&maFtDirection);
274*cdf0e10cSrcweir 	maRbValue.SetAccessibleRelationMemberOf(&maFtDirection);
275*cdf0e10cSrcweir 	maEdLeft2.SetAccessibleName(maFtCellRef.GetText());
276*cdf0e10cSrcweir     maLbOp2.SetAccessibleName(maFtOperator.GetText());
277*cdf0e10cSrcweir     maEdRight2.SetAccessibleName(maFtConstraint.GetText());
278*cdf0e10cSrcweir 	maEdLeft3.SetAccessibleName(maFtCellRef.GetText());
279*cdf0e10cSrcweir     maLbOp3.SetAccessibleName(maFtOperator.GetText());
280*cdf0e10cSrcweir     maEdRight3.SetAccessibleName(maFtConstraint.GetText());
281*cdf0e10cSrcweir 	maEdLeft4.SetAccessibleName(maFtCellRef.GetText());
282*cdf0e10cSrcweir     maLbOp4.SetAccessibleName(maFtOperator.GetText());
283*cdf0e10cSrcweir     maEdRight4.SetAccessibleName(maFtConstraint.GetText());
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir     Init( aCursorPos );
286*cdf0e10cSrcweir     FreeResource();
287*cdf0e10cSrcweir }
288*cdf0e10cSrcweir 
289*cdf0e10cSrcweir //----------------------------------------------------------------------------
290*cdf0e10cSrcweir 
291*cdf0e10cSrcweir ScOptSolverDlg::~ScOptSolverDlg()
292*cdf0e10cSrcweir {
293*cdf0e10cSrcweir }
294*cdf0e10cSrcweir 
295*cdf0e10cSrcweir //----------------------------------------------------------------------------
296*cdf0e10cSrcweir 
297*cdf0e10cSrcweir void ScOptSolverDlg::Init(const ScAddress& rCursorPos)
298*cdf0e10cSrcweir {
299*cdf0e10cSrcweir     // Get the "Delete Rows" commandimagelist images from sfx instead of
300*cdf0e10cSrcweir     // adding a second copy to sc (see ScTbxInsertCtrl::StateChanged)
301*cdf0e10cSrcweir 
302*cdf0e10cSrcweir     rtl::OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
303*cdf0e10cSrcweir     aSlotURL += rtl::OUString::valueOf( sal_Int32( SID_DEL_ROWS ) );
304*cdf0e10cSrcweir     uno::Reference<frame::XFrame> xFrame = GetBindings().GetActiveFrame();
305*cdf0e10cSrcweir     Image aDelNm = ::GetImage( xFrame, aSlotURL, sal_False, sal_False );
306*cdf0e10cSrcweir     Image aDelHC = ::GetImage( xFrame, aSlotURL, sal_False, sal_True );     // high contrast
307*cdf0e10cSrcweir 
308*cdf0e10cSrcweir     for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
309*cdf0e10cSrcweir     {
310*cdf0e10cSrcweir         mpDelButton[nRow]->SetModeImage( aDelNm, BMP_COLOR_NORMAL );
311*cdf0e10cSrcweir         mpDelButton[nRow]->SetModeImage( aDelHC, BMP_COLOR_HIGHCONTRAST );
312*cdf0e10cSrcweir     }
313*cdf0e10cSrcweir 
314*cdf0e10cSrcweir     maBtnOpt.SetClickHdl( LINK( this, ScOptSolverDlg, BtnHdl ) );
315*cdf0e10cSrcweir     maBtnCancel.SetClickHdl( LINK( this, ScOptSolverDlg, BtnHdl ) );
316*cdf0e10cSrcweir     maBtnSolve.SetClickHdl( LINK( this, ScOptSolverDlg, BtnHdl ) );
317*cdf0e10cSrcweir 
318*cdf0e10cSrcweir     Link aLink = LINK( this, ScOptSolverDlg, GetFocusHdl );
319*cdf0e10cSrcweir     maEdObjectiveCell.SetGetFocusHdl( aLink );
320*cdf0e10cSrcweir     maRBObjectiveCell.SetGetFocusHdl( aLink );
321*cdf0e10cSrcweir     maEdTargetValue.SetGetFocusHdl( aLink );
322*cdf0e10cSrcweir     maRBTargetValue.SetGetFocusHdl( aLink );
323*cdf0e10cSrcweir     maEdVariableCells.SetGetFocusHdl( aLink );
324*cdf0e10cSrcweir     maRBVariableCells.SetGetFocusHdl( aLink );
325*cdf0e10cSrcweir     maRbValue.SetGetFocusHdl( aLink );
326*cdf0e10cSrcweir     for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
327*cdf0e10cSrcweir     {
328*cdf0e10cSrcweir         mpLeftEdit[nRow]->SetGetFocusHdl( aLink );
329*cdf0e10cSrcweir         mpLeftButton[nRow]->SetGetFocusHdl( aLink );
330*cdf0e10cSrcweir         mpRightEdit[nRow]->SetGetFocusHdl( aLink );
331*cdf0e10cSrcweir         mpRightButton[nRow]->SetGetFocusHdl( aLink );
332*cdf0e10cSrcweir         mpOperator[nRow]->SetGetFocusHdl( aLink );
333*cdf0e10cSrcweir     }
334*cdf0e10cSrcweir 
335*cdf0e10cSrcweir     aLink = LINK( this, ScOptSolverDlg, LoseFocusHdl );
336*cdf0e10cSrcweir     maEdObjectiveCell.SetLoseFocusHdl( aLink );
337*cdf0e10cSrcweir     maRBObjectiveCell.SetLoseFocusHdl( aLink );
338*cdf0e10cSrcweir     maEdTargetValue.  SetLoseFocusHdl( aLink );
339*cdf0e10cSrcweir     maRBTargetValue.  SetLoseFocusHdl( aLink );
340*cdf0e10cSrcweir     maEdVariableCells.SetLoseFocusHdl( aLink );
341*cdf0e10cSrcweir     maRBVariableCells.SetLoseFocusHdl( aLink );
342*cdf0e10cSrcweir     for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
343*cdf0e10cSrcweir     {
344*cdf0e10cSrcweir         mpLeftEdit[nRow]->SetLoseFocusHdl( aLink );
345*cdf0e10cSrcweir         mpLeftButton[nRow]->SetLoseFocusHdl( aLink );
346*cdf0e10cSrcweir         mpRightEdit[nRow]->SetLoseFocusHdl( aLink );
347*cdf0e10cSrcweir         mpRightButton[nRow]->SetLoseFocusHdl( aLink );
348*cdf0e10cSrcweir     }
349*cdf0e10cSrcweir 
350*cdf0e10cSrcweir     Link aCursorUp = LINK( this, ScOptSolverDlg, CursorUpHdl );
351*cdf0e10cSrcweir     Link aCursorDown = LINK( this, ScOptSolverDlg, CursorDownHdl );
352*cdf0e10cSrcweir     Link aCondModify = LINK( this, ScOptSolverDlg, CondModifyHdl );
353*cdf0e10cSrcweir     for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
354*cdf0e10cSrcweir     {
355*cdf0e10cSrcweir         mpLeftEdit[nRow]->SetCursorLinks( aCursorUp, aCursorDown );
356*cdf0e10cSrcweir         mpRightEdit[nRow]->SetCursorLinks( aCursorUp, aCursorDown );
357*cdf0e10cSrcweir         mpLeftEdit[nRow]->SetModifyHdl( aCondModify );
358*cdf0e10cSrcweir         mpRightEdit[nRow]->SetModifyHdl( aCondModify );
359*cdf0e10cSrcweir         mpDelButton[nRow]->SetClickHdl( LINK( this, ScOptSolverDlg, DelBtnHdl ) );
360*cdf0e10cSrcweir         mpOperator[nRow]->SetSelectHdl( LINK( this, ScOptSolverDlg, SelectHdl ) );
361*cdf0e10cSrcweir     }
362*cdf0e10cSrcweir     maEdTargetValue.SetModifyHdl( LINK( this, ScOptSolverDlg, TargetModifyHdl ) );
363*cdf0e10cSrcweir 
364*cdf0e10cSrcweir     maScrollBar.SetEndScrollHdl( LINK( this, ScOptSolverDlg, ScrollHdl ) );
365*cdf0e10cSrcweir     maScrollBar.SetScrollHdl( LINK( this, ScOptSolverDlg, ScrollHdl ) );
366*cdf0e10cSrcweir 
367*cdf0e10cSrcweir     maScrollBar.SetPageSize( EDIT_ROW_COUNT );
368*cdf0e10cSrcweir     maScrollBar.SetVisibleSize( EDIT_ROW_COUNT );
369*cdf0e10cSrcweir     maScrollBar.SetLineSize( 1 );
370*cdf0e10cSrcweir     // Range is set in ShowConditions
371*cdf0e10cSrcweir 
372*cdf0e10cSrcweir     // get available solver implementations
373*cdf0e10cSrcweir     //! sort by descriptions?
374*cdf0e10cSrcweir     ScSolverUtil::GetImplementations( maImplNames, maDescriptions );
375*cdf0e10cSrcweir     sal_Int32 nImplCount = maImplNames.getLength();
376*cdf0e10cSrcweir 
377*cdf0e10cSrcweir     const ScOptSolverSave* pOldData = mpDocShell->GetSolverSaveData();
378*cdf0e10cSrcweir     if ( pOldData )
379*cdf0e10cSrcweir     {
380*cdf0e10cSrcweir         maEdObjectiveCell.SetRefString( pOldData->GetObjective() );
381*cdf0e10cSrcweir         maRbMax.Check( pOldData->GetMax() );
382*cdf0e10cSrcweir         maRbMin.Check( pOldData->GetMin() );
383*cdf0e10cSrcweir         maRbValue.Check( pOldData->GetValue() );
384*cdf0e10cSrcweir         maEdTargetValue.SetRefString( pOldData->GetTarget() );
385*cdf0e10cSrcweir         maEdVariableCells.SetRefString( pOldData->GetVariable() );
386*cdf0e10cSrcweir         maConditions = pOldData->GetConditions();
387*cdf0e10cSrcweir         maEngine = pOldData->GetEngine();
388*cdf0e10cSrcweir         maProperties = pOldData->GetProperties();
389*cdf0e10cSrcweir     }
390*cdf0e10cSrcweir     else
391*cdf0e10cSrcweir     {
392*cdf0e10cSrcweir         maRbMax.Check();
393*cdf0e10cSrcweir         String aCursorStr;
394*cdf0e10cSrcweir         if ( !mpDoc->GetRangeAtBlock( ScRange(rCursorPos), &aCursorStr ) )
395*cdf0e10cSrcweir             rCursorPos.Format( aCursorStr, SCA_ABS, NULL, mpDoc->GetAddressConvention() );
396*cdf0e10cSrcweir         maEdObjectiveCell.SetRefString( aCursorStr );
397*cdf0e10cSrcweir         if ( nImplCount > 0 )
398*cdf0e10cSrcweir             maEngine = maImplNames[0];  // use first implementation
399*cdf0e10cSrcweir     }
400*cdf0e10cSrcweir     ShowConditions();
401*cdf0e10cSrcweir 
402*cdf0e10cSrcweir     maEdObjectiveCell.GrabFocus();
403*cdf0e10cSrcweir     mpEdActive = &maEdObjectiveCell;
404*cdf0e10cSrcweir }
405*cdf0e10cSrcweir 
406*cdf0e10cSrcweir //----------------------------------------------------------------------------
407*cdf0e10cSrcweir 
408*cdf0e10cSrcweir void ScOptSolverDlg::ReadConditions()
409*cdf0e10cSrcweir {
410*cdf0e10cSrcweir     for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
411*cdf0e10cSrcweir     {
412*cdf0e10cSrcweir         ScOptConditionRow aRowEntry;
413*cdf0e10cSrcweir         aRowEntry.aLeftStr = mpLeftEdit[nRow]->GetText();
414*cdf0e10cSrcweir         aRowEntry.aRightStr = mpRightEdit[nRow]->GetText();
415*cdf0e10cSrcweir         aRowEntry.nOperator = mpOperator[nRow]->GetSelectEntryPos();
416*cdf0e10cSrcweir 
417*cdf0e10cSrcweir         long nVecPos = nScrollPos + nRow;
418*cdf0e10cSrcweir         if ( nVecPos >= (long)maConditions.size() && !aRowEntry.IsDefault() )
419*cdf0e10cSrcweir             maConditions.resize( nVecPos + 1 );
420*cdf0e10cSrcweir 
421*cdf0e10cSrcweir         if ( nVecPos < (long)maConditions.size() )
422*cdf0e10cSrcweir             maConditions[nVecPos] = aRowEntry;
423*cdf0e10cSrcweir 
424*cdf0e10cSrcweir         // remove default entries at the end
425*cdf0e10cSrcweir         size_t nSize = maConditions.size();
426*cdf0e10cSrcweir         while ( nSize > 0 && maConditions[ nSize-1 ].IsDefault() )
427*cdf0e10cSrcweir             --nSize;
428*cdf0e10cSrcweir         maConditions.resize( nSize );
429*cdf0e10cSrcweir     }
430*cdf0e10cSrcweir }
431*cdf0e10cSrcweir 
432*cdf0e10cSrcweir void ScOptSolverDlg::ShowConditions()
433*cdf0e10cSrcweir {
434*cdf0e10cSrcweir     for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
435*cdf0e10cSrcweir     {
436*cdf0e10cSrcweir         ScOptConditionRow aRowEntry;
437*cdf0e10cSrcweir 
438*cdf0e10cSrcweir         long nVecPos = nScrollPos + nRow;
439*cdf0e10cSrcweir         if ( nVecPos < (long)maConditions.size() )
440*cdf0e10cSrcweir             aRowEntry = maConditions[nVecPos];
441*cdf0e10cSrcweir 
442*cdf0e10cSrcweir         mpLeftEdit[nRow]->SetRefString( aRowEntry.aLeftStr );
443*cdf0e10cSrcweir         mpRightEdit[nRow]->SetRefString( aRowEntry.aRightStr );
444*cdf0e10cSrcweir         mpOperator[nRow]->SelectEntryPos( aRowEntry.nOperator );
445*cdf0e10cSrcweir     }
446*cdf0e10cSrcweir 
447*cdf0e10cSrcweir     // allow to scroll one page behind the visible or stored rows
448*cdf0e10cSrcweir     long nVisible = nScrollPos + EDIT_ROW_COUNT;
449*cdf0e10cSrcweir     long nMax = std::max( nVisible, (long) maConditions.size() );
450*cdf0e10cSrcweir     maScrollBar.SetRange( Range( 0, nMax + EDIT_ROW_COUNT ) );
451*cdf0e10cSrcweir     maScrollBar.SetThumbPos( nScrollPos );
452*cdf0e10cSrcweir 
453*cdf0e10cSrcweir     EnableButtons();
454*cdf0e10cSrcweir }
455*cdf0e10cSrcweir 
456*cdf0e10cSrcweir void ScOptSolverDlg::EnableButtons()
457*cdf0e10cSrcweir {
458*cdf0e10cSrcweir     for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
459*cdf0e10cSrcweir     {
460*cdf0e10cSrcweir         long nVecPos = nScrollPos + nRow;
461*cdf0e10cSrcweir         mpDelButton[nRow]->Enable( nVecPos < (long)maConditions.size() );
462*cdf0e10cSrcweir     }
463*cdf0e10cSrcweir }
464*cdf0e10cSrcweir 
465*cdf0e10cSrcweir //----------------------------------------------------------------------------
466*cdf0e10cSrcweir 
467*cdf0e10cSrcweir sal_Bool ScOptSolverDlg::Close()
468*cdf0e10cSrcweir {
469*cdf0e10cSrcweir     return DoClose( ScOptSolverDlgWrapper::GetChildWindowId() );
470*cdf0e10cSrcweir }
471*cdf0e10cSrcweir 
472*cdf0e10cSrcweir //----------------------------------------------------------------------------
473*cdf0e10cSrcweir 
474*cdf0e10cSrcweir void ScOptSolverDlg::SetActive()
475*cdf0e10cSrcweir {
476*cdf0e10cSrcweir     if ( mbDlgLostFocus )
477*cdf0e10cSrcweir     {
478*cdf0e10cSrcweir         mbDlgLostFocus = false;
479*cdf0e10cSrcweir         if( mpEdActive )
480*cdf0e10cSrcweir             mpEdActive->GrabFocus();
481*cdf0e10cSrcweir     }
482*cdf0e10cSrcweir     else
483*cdf0e10cSrcweir     {
484*cdf0e10cSrcweir         GrabFocus();
485*cdf0e10cSrcweir     }
486*cdf0e10cSrcweir     RefInputDone();
487*cdf0e10cSrcweir }
488*cdf0e10cSrcweir 
489*cdf0e10cSrcweir //----------------------------------------------------------------------------
490*cdf0e10cSrcweir 
491*cdf0e10cSrcweir void ScOptSolverDlg::SetReference( const ScRange& rRef, ScDocument* pDocP )
492*cdf0e10cSrcweir {
493*cdf0e10cSrcweir     if( mpEdActive )
494*cdf0e10cSrcweir     {
495*cdf0e10cSrcweir         if ( rRef.aStart != rRef.aEnd )
496*cdf0e10cSrcweir             RefInputStart(mpEdActive);
497*cdf0e10cSrcweir 
498*cdf0e10cSrcweir         // "target"/"value": single cell
499*cdf0e10cSrcweir         bool bSingle = ( mpEdActive == &maEdObjectiveCell || mpEdActive == &maEdTargetValue );
500*cdf0e10cSrcweir 
501*cdf0e10cSrcweir         String aStr;
502*cdf0e10cSrcweir         ScAddress aAdr = rRef.aStart;
503*cdf0e10cSrcweir         ScRange aNewRef( rRef );
504*cdf0e10cSrcweir         if ( bSingle )
505*cdf0e10cSrcweir             aNewRef.aEnd = aAdr;
506*cdf0e10cSrcweir 
507*cdf0e10cSrcweir         String aName;
508*cdf0e10cSrcweir         if ( pDocP->GetRangeAtBlock( aNewRef, &aName ) )            // named range: show name
509*cdf0e10cSrcweir             aStr = aName;
510*cdf0e10cSrcweir         else                                                        // format cell/range reference
511*cdf0e10cSrcweir         {
512*cdf0e10cSrcweir             sal_uInt16 nFmt = ( aAdr.Tab() == mnCurTab ) ? SCA_ABS : SCA_ABS_3D;
513*cdf0e10cSrcweir             if ( bSingle )
514*cdf0e10cSrcweir                 aAdr.Format( aStr, nFmt, pDocP, pDocP->GetAddressConvention() );
515*cdf0e10cSrcweir             else
516*cdf0e10cSrcweir                 rRef.Format( aStr, nFmt | SCR_ABS, pDocP, pDocP->GetAddressConvention() );
517*cdf0e10cSrcweir         }
518*cdf0e10cSrcweir 
519*cdf0e10cSrcweir         // variable cells can be several ranges, so only the selection is replaced
520*cdf0e10cSrcweir         if ( mpEdActive == &maEdVariableCells )
521*cdf0e10cSrcweir         {
522*cdf0e10cSrcweir             String aVal = mpEdActive->GetText();
523*cdf0e10cSrcweir             Selection aSel = mpEdActive->GetSelection();
524*cdf0e10cSrcweir             aSel.Justify();
525*cdf0e10cSrcweir             aVal.Erase( (xub_StrLen)aSel.Min(), (xub_StrLen)aSel.Len() );
526*cdf0e10cSrcweir             aVal.Insert( aStr, (xub_StrLen)aSel.Min() );
527*cdf0e10cSrcweir             Selection aNewSel( aSel.Min(), aSel.Min()+aStr.Len() );
528*cdf0e10cSrcweir             mpEdActive->SetRefString( aVal );
529*cdf0e10cSrcweir             mpEdActive->SetSelection( aNewSel );
530*cdf0e10cSrcweir         }
531*cdf0e10cSrcweir         else
532*cdf0e10cSrcweir             mpEdActive->SetRefString( aStr );
533*cdf0e10cSrcweir 
534*cdf0e10cSrcweir         ReadConditions();
535*cdf0e10cSrcweir         EnableButtons();
536*cdf0e10cSrcweir 
537*cdf0e10cSrcweir         // select "Value of" if a ref is input into "target" edit
538*cdf0e10cSrcweir         if ( mpEdActive == &maEdTargetValue )
539*cdf0e10cSrcweir             maRbValue.Check();
540*cdf0e10cSrcweir     }
541*cdf0e10cSrcweir }
542*cdf0e10cSrcweir 
543*cdf0e10cSrcweir //----------------------------------------------------------------------------
544*cdf0e10cSrcweir 
545*cdf0e10cSrcweir sal_Bool ScOptSolverDlg::IsRefInputMode() const
546*cdf0e10cSrcweir {
547*cdf0e10cSrcweir     return mpEdActive != NULL;
548*cdf0e10cSrcweir }
549*cdf0e10cSrcweir 
550*cdf0e10cSrcweir //----------------------------------------------------------------------------
551*cdf0e10cSrcweir // Handler:
552*cdf0e10cSrcweir 
553*cdf0e10cSrcweir IMPL_LINK( ScOptSolverDlg, BtnHdl, PushButton*, pBtn )
554*cdf0e10cSrcweir {
555*cdf0e10cSrcweir     if ( pBtn == &maBtnSolve || pBtn == &maBtnCancel )
556*cdf0e10cSrcweir     {
557*cdf0e10cSrcweir         bool bSolve = ( pBtn == &maBtnSolve );
558*cdf0e10cSrcweir 
559*cdf0e10cSrcweir         SetDispatcherLock( sal_False );
560*cdf0e10cSrcweir         SwitchToDocument();
561*cdf0e10cSrcweir 
562*cdf0e10cSrcweir         bool bClose = true;
563*cdf0e10cSrcweir         if ( bSolve )
564*cdf0e10cSrcweir             bClose = CallSolver();
565*cdf0e10cSrcweir 
566*cdf0e10cSrcweir         if ( bClose )
567*cdf0e10cSrcweir         {
568*cdf0e10cSrcweir             // Close: write dialog settings to DocShell for subsequent calls
569*cdf0e10cSrcweir             ReadConditions();
570*cdf0e10cSrcweir             ScOptSolverSave aSave(
571*cdf0e10cSrcweir                 maEdObjectiveCell.GetText(), maRbMax.IsChecked(), maRbMin.IsChecked(), maRbValue.IsChecked(),
572*cdf0e10cSrcweir                 maEdTargetValue.GetText(), maEdVariableCells.GetText(), maConditions, maEngine, maProperties );
573*cdf0e10cSrcweir             mpDocShell->SetSolverSaveData( aSave );
574*cdf0e10cSrcweir             Close();
575*cdf0e10cSrcweir         }
576*cdf0e10cSrcweir         else
577*cdf0e10cSrcweir         {
578*cdf0e10cSrcweir             // no solution -> dialog is kept open
579*cdf0e10cSrcweir             SetDispatcherLock( sal_True );
580*cdf0e10cSrcweir         }
581*cdf0e10cSrcweir     }
582*cdf0e10cSrcweir     else if ( pBtn == &maBtnOpt )
583*cdf0e10cSrcweir     {
584*cdf0e10cSrcweir         //! move options dialog to UI lib?
585*cdf0e10cSrcweir         ScSolverOptionsDialog* pOptDlg =
586*cdf0e10cSrcweir             new ScSolverOptionsDialog( this, maImplNames, maDescriptions, maEngine, maProperties );
587*cdf0e10cSrcweir         if ( pOptDlg->Execute() == RET_OK )
588*cdf0e10cSrcweir         {
589*cdf0e10cSrcweir             maEngine = pOptDlg->GetEngine();
590*cdf0e10cSrcweir             maProperties = pOptDlg->GetProperties();
591*cdf0e10cSrcweir         }
592*cdf0e10cSrcweir         delete pOptDlg;
593*cdf0e10cSrcweir     }
594*cdf0e10cSrcweir 
595*cdf0e10cSrcweir     return 0;
596*cdf0e10cSrcweir }
597*cdf0e10cSrcweir 
598*cdf0e10cSrcweir //----------------------------------------------------------------------------
599*cdf0e10cSrcweir 
600*cdf0e10cSrcweir IMPL_LINK( ScOptSolverDlg, GetFocusHdl, Control*, pCtrl )
601*cdf0e10cSrcweir {
602*cdf0e10cSrcweir     Edit* pEdit = NULL;
603*cdf0e10cSrcweir     mpEdActive = NULL;
604*cdf0e10cSrcweir 
605*cdf0e10cSrcweir     if( pCtrl == &maEdObjectiveCell || pCtrl == &maRBObjectiveCell )
606*cdf0e10cSrcweir         pEdit = mpEdActive = &maEdObjectiveCell;
607*cdf0e10cSrcweir     else if( pCtrl == &maEdTargetValue || pCtrl == &maRBTargetValue )
608*cdf0e10cSrcweir         pEdit = mpEdActive = &maEdTargetValue;
609*cdf0e10cSrcweir     else if( pCtrl == &maEdVariableCells || pCtrl == &maRBVariableCells )
610*cdf0e10cSrcweir         pEdit = mpEdActive = &maEdVariableCells;
611*cdf0e10cSrcweir     for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
612*cdf0e10cSrcweir     {
613*cdf0e10cSrcweir         if( pCtrl == mpLeftEdit[nRow] || pCtrl == mpLeftButton[nRow] )
614*cdf0e10cSrcweir             pEdit = mpEdActive = mpLeftEdit[nRow];
615*cdf0e10cSrcweir         else if( pCtrl == mpRightEdit[nRow] || pCtrl == mpRightButton[nRow] )
616*cdf0e10cSrcweir             pEdit = mpEdActive = mpRightEdit[nRow];
617*cdf0e10cSrcweir         else if( pCtrl == mpOperator[nRow] )    // focus on "operator" list box
618*cdf0e10cSrcweir             mpEdActive = mpRightEdit[nRow];     // use right edit for ref input, but don't change selection
619*cdf0e10cSrcweir     }
620*cdf0e10cSrcweir     if( pCtrl == &maRbValue )                   // focus on "Value of" radio button
621*cdf0e10cSrcweir         mpEdActive = &maEdTargetValue;          // use value edit for ref input, but don't change selection
622*cdf0e10cSrcweir 
623*cdf0e10cSrcweir     if( pEdit )
624*cdf0e10cSrcweir         pEdit->SetSelection( Selection( 0, SELECTION_MAX ) );
625*cdf0e10cSrcweir 
626*cdf0e10cSrcweir     return 0;
627*cdf0e10cSrcweir }
628*cdf0e10cSrcweir 
629*cdf0e10cSrcweir //----------------------------------------------------------------------------
630*cdf0e10cSrcweir 
631*cdf0e10cSrcweir IMPL_LINK( ScOptSolverDlg, LoseFocusHdl, Control*, EMPTYARG )
632*cdf0e10cSrcweir {
633*cdf0e10cSrcweir     mbDlgLostFocus = !IsActive();
634*cdf0e10cSrcweir     return 0;
635*cdf0e10cSrcweir }
636*cdf0e10cSrcweir 
637*cdf0e10cSrcweir //----------------------------------------------------------------------------
638*cdf0e10cSrcweir 
639*cdf0e10cSrcweir IMPL_LINK( ScOptSolverDlg, DelBtnHdl, PushButton*, pBtn )
640*cdf0e10cSrcweir {
641*cdf0e10cSrcweir     for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
642*cdf0e10cSrcweir         if( pBtn == mpDelButton[nRow] )
643*cdf0e10cSrcweir         {
644*cdf0e10cSrcweir             sal_Bool bHadFocus = pBtn->HasFocus();
645*cdf0e10cSrcweir 
646*cdf0e10cSrcweir             ReadConditions();
647*cdf0e10cSrcweir             long nVecPos = nScrollPos + nRow;
648*cdf0e10cSrcweir             if ( nVecPos < (long)maConditions.size() )
649*cdf0e10cSrcweir             {
650*cdf0e10cSrcweir                 maConditions.erase( maConditions.begin() + nVecPos );
651*cdf0e10cSrcweir                 ShowConditions();
652*cdf0e10cSrcweir 
653*cdf0e10cSrcweir                 if ( bHadFocus && !pBtn->IsEnabled() )
654*cdf0e10cSrcweir                 {
655*cdf0e10cSrcweir                     // If the button is disabled, focus would normally move to the next control,
656*cdf0e10cSrcweir                     // (left edit of the next row). Move it to left edit of this row instead.
657*cdf0e10cSrcweir 
658*cdf0e10cSrcweir                     mpEdActive = mpLeftEdit[nRow];
659*cdf0e10cSrcweir                     mpEdActive->GrabFocus();
660*cdf0e10cSrcweir                 }
661*cdf0e10cSrcweir             }
662*cdf0e10cSrcweir         }
663*cdf0e10cSrcweir 
664*cdf0e10cSrcweir     return 0;
665*cdf0e10cSrcweir }
666*cdf0e10cSrcweir 
667*cdf0e10cSrcweir //----------------------------------------------------------------------------
668*cdf0e10cSrcweir 
669*cdf0e10cSrcweir IMPL_LINK( ScOptSolverDlg, TargetModifyHdl, Edit*, EMPTYARG )
670*cdf0e10cSrcweir {
671*cdf0e10cSrcweir     // modify handler for the target edit:
672*cdf0e10cSrcweir     //  select "Value of" if something is input into the edit
673*cdf0e10cSrcweir     if ( maEdTargetValue.GetText().Len() )
674*cdf0e10cSrcweir         maRbValue.Check();
675*cdf0e10cSrcweir     return 0;
676*cdf0e10cSrcweir }
677*cdf0e10cSrcweir 
678*cdf0e10cSrcweir IMPL_LINK( ScOptSolverDlg, CondModifyHdl, Edit*, EMPTYARG )
679*cdf0e10cSrcweir {
680*cdf0e10cSrcweir     // modify handler for the condition edits, just to enable/disable "delete" buttons
681*cdf0e10cSrcweir     ReadConditions();
682*cdf0e10cSrcweir     EnableButtons();
683*cdf0e10cSrcweir     return 0;
684*cdf0e10cSrcweir }
685*cdf0e10cSrcweir 
686*cdf0e10cSrcweir IMPL_LINK( ScOptSolverDlg, SelectHdl, ListBox*, EMPTYARG )
687*cdf0e10cSrcweir {
688*cdf0e10cSrcweir     // select handler for operator list boxes, just to enable/disable "delete" buttons
689*cdf0e10cSrcweir     ReadConditions();
690*cdf0e10cSrcweir     EnableButtons();
691*cdf0e10cSrcweir     return 0;
692*cdf0e10cSrcweir }
693*cdf0e10cSrcweir 
694*cdf0e10cSrcweir IMPL_LINK( ScOptSolverDlg, ScrollHdl, ScrollBar*, EMPTYARG )
695*cdf0e10cSrcweir {
696*cdf0e10cSrcweir     ReadConditions();
697*cdf0e10cSrcweir     nScrollPos = maScrollBar.GetThumbPos();
698*cdf0e10cSrcweir     ShowConditions();
699*cdf0e10cSrcweir     if( mpEdActive )
700*cdf0e10cSrcweir         mpEdActive->SetSelection( Selection( 0, SELECTION_MAX ) );
701*cdf0e10cSrcweir 	return 0;
702*cdf0e10cSrcweir }
703*cdf0e10cSrcweir 
704*cdf0e10cSrcweir IMPL_LINK( ScOptSolverDlg, CursorUpHdl, ScCursorRefEdit*, pEdit )
705*cdf0e10cSrcweir {
706*cdf0e10cSrcweir     if ( pEdit == mpLeftEdit[0] || pEdit == mpRightEdit[0] )
707*cdf0e10cSrcweir     {
708*cdf0e10cSrcweir         if ( nScrollPos > 0 )
709*cdf0e10cSrcweir         {
710*cdf0e10cSrcweir             ReadConditions();
711*cdf0e10cSrcweir             --nScrollPos;
712*cdf0e10cSrcweir             ShowConditions();
713*cdf0e10cSrcweir             if( mpEdActive )
714*cdf0e10cSrcweir                 mpEdActive->SetSelection( Selection( 0, SELECTION_MAX ) );
715*cdf0e10cSrcweir         }
716*cdf0e10cSrcweir     }
717*cdf0e10cSrcweir     else
718*cdf0e10cSrcweir     {
719*cdf0e10cSrcweir         formula::RefEdit* pFocus = NULL;
720*cdf0e10cSrcweir         for ( sal_uInt16 nRow = 1; nRow < EDIT_ROW_COUNT; ++nRow )      // second row or below: move focus
721*cdf0e10cSrcweir         {
722*cdf0e10cSrcweir             if ( pEdit == mpLeftEdit[nRow] )
723*cdf0e10cSrcweir                 pFocus = mpLeftEdit[nRow-1];
724*cdf0e10cSrcweir             else if ( pEdit == mpRightEdit[nRow] )
725*cdf0e10cSrcweir                 pFocus = mpRightEdit[nRow-1];
726*cdf0e10cSrcweir         }
727*cdf0e10cSrcweir         if (pFocus)
728*cdf0e10cSrcweir         {
729*cdf0e10cSrcweir             mpEdActive = pFocus;
730*cdf0e10cSrcweir             pFocus->GrabFocus();
731*cdf0e10cSrcweir         }
732*cdf0e10cSrcweir     }
733*cdf0e10cSrcweir 
734*cdf0e10cSrcweir     return 0;
735*cdf0e10cSrcweir }
736*cdf0e10cSrcweir 
737*cdf0e10cSrcweir IMPL_LINK( ScOptSolverDlg, CursorDownHdl, ScCursorRefEdit*, pEdit )
738*cdf0e10cSrcweir {
739*cdf0e10cSrcweir     if ( pEdit == mpLeftEdit[EDIT_ROW_COUNT-1] || pEdit == mpRightEdit[EDIT_ROW_COUNT-1] )
740*cdf0e10cSrcweir     {
741*cdf0e10cSrcweir         //! limit scroll position?
742*cdf0e10cSrcweir         ReadConditions();
743*cdf0e10cSrcweir         ++nScrollPos;
744*cdf0e10cSrcweir         ShowConditions();
745*cdf0e10cSrcweir         if( mpEdActive )
746*cdf0e10cSrcweir             mpEdActive->SetSelection( Selection( 0, SELECTION_MAX ) );
747*cdf0e10cSrcweir     }
748*cdf0e10cSrcweir     else
749*cdf0e10cSrcweir     {
750*cdf0e10cSrcweir         formula::RefEdit* pFocus = NULL;
751*cdf0e10cSrcweir         for ( sal_uInt16 nRow = 0; nRow+1 < EDIT_ROW_COUNT; ++nRow )      // before last row: move focus
752*cdf0e10cSrcweir         {
753*cdf0e10cSrcweir             if ( pEdit == mpLeftEdit[nRow] )
754*cdf0e10cSrcweir                 pFocus = mpLeftEdit[nRow+1];
755*cdf0e10cSrcweir             else if ( pEdit == mpRightEdit[nRow] )
756*cdf0e10cSrcweir                 pFocus = mpRightEdit[nRow+1];
757*cdf0e10cSrcweir         }
758*cdf0e10cSrcweir         if (pFocus)
759*cdf0e10cSrcweir         {
760*cdf0e10cSrcweir             mpEdActive = pFocus;
761*cdf0e10cSrcweir             pFocus->GrabFocus();
762*cdf0e10cSrcweir         }
763*cdf0e10cSrcweir     }
764*cdf0e10cSrcweir 
765*cdf0e10cSrcweir     return 0;
766*cdf0e10cSrcweir }
767*cdf0e10cSrcweir 
768*cdf0e10cSrcweir //----------------------------------------------------------------------------
769*cdf0e10cSrcweir 
770*cdf0e10cSrcweir void ScOptSolverDlg::ShowError( bool bCondition, formula::RefEdit* pFocus )
771*cdf0e10cSrcweir {
772*cdf0e10cSrcweir     String aMessage = bCondition ? maConditionError : maInputError;
773*cdf0e10cSrcweir     ErrorBox( this, WinBits( WB_OK | WB_DEF_OK ), aMessage ).Execute();
774*cdf0e10cSrcweir     if (pFocus)
775*cdf0e10cSrcweir     {
776*cdf0e10cSrcweir         mpEdActive = pFocus;
777*cdf0e10cSrcweir         pFocus->GrabFocus();
778*cdf0e10cSrcweir     }
779*cdf0e10cSrcweir }
780*cdf0e10cSrcweir 
781*cdf0e10cSrcweir //----------------------------------------------------------------------------
782*cdf0e10cSrcweir 
783*cdf0e10cSrcweir bool ScOptSolverDlg::ParseRef( ScRange& rRange, const String& rInput, bool bAllowRange )
784*cdf0e10cSrcweir {
785*cdf0e10cSrcweir     ScRangeUtil aRangeUtil;
786*cdf0e10cSrcweir     ScAddress::Details aDetails(mpDoc->GetAddressConvention(), 0, 0);
787*cdf0e10cSrcweir     sal_uInt16 nFlags = rRange.ParseAny( rInput, mpDoc, aDetails );
788*cdf0e10cSrcweir     if ( nFlags & SCA_VALID )
789*cdf0e10cSrcweir     {
790*cdf0e10cSrcweir         if ( (nFlags & SCA_TAB_3D) == 0 )
791*cdf0e10cSrcweir             rRange.aStart.SetTab( mnCurTab );
792*cdf0e10cSrcweir         if ( (nFlags & SCA_TAB2_3D) == 0 )
793*cdf0e10cSrcweir             rRange.aEnd.SetTab( rRange.aStart.Tab() );
794*cdf0e10cSrcweir         return ( bAllowRange || rRange.aStart == rRange.aEnd );
795*cdf0e10cSrcweir     }
796*cdf0e10cSrcweir     else if ( aRangeUtil.MakeRangeFromName( rInput, mpDoc, mnCurTab, rRange, RUTL_NAMES, aDetails ) )
797*cdf0e10cSrcweir         return ( bAllowRange || rRange.aStart == rRange.aEnd );
798*cdf0e10cSrcweir 
799*cdf0e10cSrcweir     return false;   // not recognized
800*cdf0e10cSrcweir }
801*cdf0e10cSrcweir 
802*cdf0e10cSrcweir bool ScOptSolverDlg::FindTimeout( sal_Int32& rTimeout )
803*cdf0e10cSrcweir {
804*cdf0e10cSrcweir     bool bFound = false;
805*cdf0e10cSrcweir 
806*cdf0e10cSrcweir     if ( !maProperties.getLength() )
807*cdf0e10cSrcweir         maProperties = ScSolverUtil::GetDefaults( maEngine );   // get property defaults from component
808*cdf0e10cSrcweir 
809*cdf0e10cSrcweir     sal_Int32 nPropCount = maProperties.getLength();
810*cdf0e10cSrcweir     for (sal_Int32 nProp=0; nProp<nPropCount && !bFound; ++nProp)
811*cdf0e10cSrcweir     {
812*cdf0e10cSrcweir         const beans::PropertyValue& rValue = maProperties[nProp];
813*cdf0e10cSrcweir         if ( rValue.Name.equalsAscii( SC_UNONAME_TIMEOUT ) )
814*cdf0e10cSrcweir             bFound = ( rValue.Value >>= rTimeout );
815*cdf0e10cSrcweir     }
816*cdf0e10cSrcweir     return bFound;
817*cdf0e10cSrcweir }
818*cdf0e10cSrcweir 
819*cdf0e10cSrcweir bool ScOptSolverDlg::CallSolver()       // return true -> close dialog after calling
820*cdf0e10cSrcweir {
821*cdf0e10cSrcweir     // show progress dialog
822*cdf0e10cSrcweir 
823*cdf0e10cSrcweir     ScSolverProgressDialog aProgress( this );
824*cdf0e10cSrcweir     sal_Int32 nTimeout = 0;
825*cdf0e10cSrcweir     if ( FindTimeout( nTimeout ) )
826*cdf0e10cSrcweir         aProgress.SetTimeLimit( nTimeout );
827*cdf0e10cSrcweir     else
828*cdf0e10cSrcweir         aProgress.HideTimeLimit();
829*cdf0e10cSrcweir     aProgress.Show();
830*cdf0e10cSrcweir     aProgress.Update();
831*cdf0e10cSrcweir     aProgress.Sync();
832*cdf0e10cSrcweir     // try to make sure the progress dialog is painted before continuing
833*cdf0e10cSrcweir     Application::Reschedule(true);
834*cdf0e10cSrcweir 
835*cdf0e10cSrcweir     // collect solver parameters
836*cdf0e10cSrcweir 
837*cdf0e10cSrcweir     ReadConditions();
838*cdf0e10cSrcweir 
839*cdf0e10cSrcweir     uno::Reference<sheet::XSpreadsheetDocument> xDocument( mpDocShell->GetModel(), uno::UNO_QUERY );
840*cdf0e10cSrcweir 
841*cdf0e10cSrcweir     ScRange aObjRange;
842*cdf0e10cSrcweir     if ( !ParseRef( aObjRange, maEdObjectiveCell.GetText(), false ) )
843*cdf0e10cSrcweir     {
844*cdf0e10cSrcweir         ShowError( false, &maEdObjectiveCell );
845*cdf0e10cSrcweir         return false;
846*cdf0e10cSrcweir     }
847*cdf0e10cSrcweir     table::CellAddress aObjective( aObjRange.aStart.Tab(), aObjRange.aStart.Col(), aObjRange.aStart.Row() );
848*cdf0e10cSrcweir 
849*cdf0e10cSrcweir     // "changing cells" can be several ranges
850*cdf0e10cSrcweir     ScRangeList aVarRanges;
851*cdf0e10cSrcweir     if ( !ParseWithNames( aVarRanges, maEdVariableCells.GetText(), mpDoc ) )
852*cdf0e10cSrcweir     {
853*cdf0e10cSrcweir         ShowError( false, &maEdVariableCells );
854*cdf0e10cSrcweir         return false;
855*cdf0e10cSrcweir     }
856*cdf0e10cSrcweir     uno::Sequence<table::CellAddress> aVariables;
857*cdf0e10cSrcweir     sal_Int32 nVarPos = 0;
858*cdf0e10cSrcweir    	sal_uLong nRangeCount = aVarRanges.Count();
859*cdf0e10cSrcweir     for (sal_uLong nRangePos=0; nRangePos<nRangeCount; ++nRangePos)
860*cdf0e10cSrcweir     {
861*cdf0e10cSrcweir         ScRange aRange(*aVarRanges.GetObject(nRangePos));
862*cdf0e10cSrcweir         aRange.Justify();
863*cdf0e10cSrcweir         SCTAB nTab = aRange.aStart.Tab();
864*cdf0e10cSrcweir 
865*cdf0e10cSrcweir         // resolve into single cells
866*cdf0e10cSrcweir 
867*cdf0e10cSrcweir         sal_Int32 nAdd = ( aRange.aEnd.Col() - aRange.aStart.Col() + 1 ) *
868*cdf0e10cSrcweir                          ( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
869*cdf0e10cSrcweir         aVariables.realloc( nVarPos + nAdd );
870*cdf0e10cSrcweir 
871*cdf0e10cSrcweir         for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
872*cdf0e10cSrcweir             for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
873*cdf0e10cSrcweir                 aVariables[nVarPos++] = table::CellAddress( nTab, nCol, nRow );
874*cdf0e10cSrcweir     }
875*cdf0e10cSrcweir 
876*cdf0e10cSrcweir     uno::Sequence<sheet::SolverConstraint> aConstraints;
877*cdf0e10cSrcweir     sal_Int32 nConstrPos = 0;
878*cdf0e10cSrcweir     for ( std::vector<ScOptConditionRow>::const_iterator aConstrIter = maConditions.begin();
879*cdf0e10cSrcweir           aConstrIter != maConditions.end(); ++aConstrIter )
880*cdf0e10cSrcweir     {
881*cdf0e10cSrcweir         if ( aConstrIter->aLeftStr.Len() )
882*cdf0e10cSrcweir         {
883*cdf0e10cSrcweir             sheet::SolverConstraint aConstraint;
884*cdf0e10cSrcweir             // order of list box entries must match enum values
885*cdf0e10cSrcweir             aConstraint.Operator = static_cast<sheet::SolverConstraintOperator>(aConstrIter->nOperator);
886*cdf0e10cSrcweir 
887*cdf0e10cSrcweir             ScRange aLeftRange;
888*cdf0e10cSrcweir             if ( !ParseRef( aLeftRange, aConstrIter->aLeftStr, true ) )
889*cdf0e10cSrcweir             {
890*cdf0e10cSrcweir                 ShowError( true, NULL );
891*cdf0e10cSrcweir                 return false;
892*cdf0e10cSrcweir             }
893*cdf0e10cSrcweir 
894*cdf0e10cSrcweir             bool bIsRange = false;
895*cdf0e10cSrcweir             ScRange aRightRange;
896*cdf0e10cSrcweir             if ( ParseRef( aRightRange, aConstrIter->aRightStr, true ) )
897*cdf0e10cSrcweir             {
898*cdf0e10cSrcweir                 if ( aRightRange.aStart == aRightRange.aEnd )
899*cdf0e10cSrcweir                     aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
900*cdf0e10cSrcweir                                                               aRightRange.aStart.Col(), aRightRange.aStart.Row() );
901*cdf0e10cSrcweir                 else if ( aRightRange.aEnd.Col()-aRightRange.aStart.Col() == aLeftRange.aEnd.Col()-aLeftRange.aStart.Col() &&
902*cdf0e10cSrcweir                           aRightRange.aEnd.Row()-aRightRange.aStart.Row() == aLeftRange.aEnd.Row()-aLeftRange.aStart.Row() )
903*cdf0e10cSrcweir                     bIsRange = true;    // same size as "left" range, resolve into single cells
904*cdf0e10cSrcweir                 else
905*cdf0e10cSrcweir                 {
906*cdf0e10cSrcweir                     ShowError( true, NULL );
907*cdf0e10cSrcweir                     return false;
908*cdf0e10cSrcweir                 }
909*cdf0e10cSrcweir             }
910*cdf0e10cSrcweir             else
911*cdf0e10cSrcweir             {
912*cdf0e10cSrcweir                 sal_uInt32 nFormat = 0;     //! explicit language?
913*cdf0e10cSrcweir                 double fValue = 0.0;
914*cdf0e10cSrcweir                 if ( mpDoc->GetFormatTable()->IsNumberFormat( aConstrIter->aRightStr, nFormat, fValue ) )
915*cdf0e10cSrcweir                     aConstraint.Right <<= fValue;
916*cdf0e10cSrcweir                 else if ( aConstraint.Operator != sheet::SolverConstraintOperator_INTEGER &&
917*cdf0e10cSrcweir                           aConstraint.Operator != sheet::SolverConstraintOperator_BINARY )
918*cdf0e10cSrcweir                 {
919*cdf0e10cSrcweir                     ShowError( true, NULL );
920*cdf0e10cSrcweir                     return false;
921*cdf0e10cSrcweir                 }
922*cdf0e10cSrcweir             }
923*cdf0e10cSrcweir 
924*cdf0e10cSrcweir             // resolve into single cells
925*cdf0e10cSrcweir 
926*cdf0e10cSrcweir             sal_Int32 nAdd = ( aLeftRange.aEnd.Col() - aLeftRange.aStart.Col() + 1 ) *
927*cdf0e10cSrcweir                              ( aLeftRange.aEnd.Row() - aLeftRange.aStart.Row() + 1 );
928*cdf0e10cSrcweir             aConstraints.realloc( nConstrPos + nAdd );
929*cdf0e10cSrcweir 
930*cdf0e10cSrcweir             for (SCROW nRow = aLeftRange.aStart.Row(); nRow <= aLeftRange.aEnd.Row(); ++nRow)
931*cdf0e10cSrcweir                 for (SCCOL nCol = aLeftRange.aStart.Col(); nCol <= aLeftRange.aEnd.Col(); ++nCol)
932*cdf0e10cSrcweir                 {
933*cdf0e10cSrcweir                     aConstraint.Left = table::CellAddress( aLeftRange.aStart.Tab(), nCol, nRow );
934*cdf0e10cSrcweir                     if ( bIsRange )
935*cdf0e10cSrcweir                         aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
936*cdf0e10cSrcweir                             aRightRange.aStart.Col() + ( nCol - aLeftRange.aStart.Col() ),
937*cdf0e10cSrcweir                             aRightRange.aStart.Row() + ( nRow - aLeftRange.aStart.Row() ) );
938*cdf0e10cSrcweir 
939*cdf0e10cSrcweir                     aConstraints[nConstrPos++] = aConstraint;
940*cdf0e10cSrcweir                 }
941*cdf0e10cSrcweir         }
942*cdf0e10cSrcweir     }
943*cdf0e10cSrcweir 
944*cdf0e10cSrcweir     sal_Bool bMaximize = maRbMax.IsChecked();
945*cdf0e10cSrcweir     if ( maRbValue.IsChecked() )
946*cdf0e10cSrcweir     {
947*cdf0e10cSrcweir         // handle "value of" with an additional constraint (and then minimize)
948*cdf0e10cSrcweir 
949*cdf0e10cSrcweir         sheet::SolverConstraint aConstraint;
950*cdf0e10cSrcweir         aConstraint.Left     = aObjective;
951*cdf0e10cSrcweir         aConstraint.Operator = sheet::SolverConstraintOperator_EQUAL;
952*cdf0e10cSrcweir 
953*cdf0e10cSrcweir         String aValStr = maEdTargetValue.GetText();
954*cdf0e10cSrcweir         ScRange aRightRange;
955*cdf0e10cSrcweir         if ( ParseRef( aRightRange, aValStr, false ) )
956*cdf0e10cSrcweir             aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
957*cdf0e10cSrcweir                                                       aRightRange.aStart.Col(), aRightRange.aStart.Row() );
958*cdf0e10cSrcweir         else
959*cdf0e10cSrcweir         {
960*cdf0e10cSrcweir             sal_uInt32 nFormat = 0;     //! explicit language?
961*cdf0e10cSrcweir             double fValue = 0.0;
962*cdf0e10cSrcweir             if ( mpDoc->GetFormatTable()->IsNumberFormat( aValStr, nFormat, fValue ) )
963*cdf0e10cSrcweir                 aConstraint.Right <<= fValue;
964*cdf0e10cSrcweir             else
965*cdf0e10cSrcweir             {
966*cdf0e10cSrcweir                 ShowError( false, &maEdTargetValue );
967*cdf0e10cSrcweir                 return false;
968*cdf0e10cSrcweir             }
969*cdf0e10cSrcweir         }
970*cdf0e10cSrcweir 
971*cdf0e10cSrcweir         aConstraints.realloc( nConstrPos + 1 );
972*cdf0e10cSrcweir         aConstraints[nConstrPos++] = aConstraint;
973*cdf0e10cSrcweir     }
974*cdf0e10cSrcweir 
975*cdf0e10cSrcweir     // copy old document values
976*cdf0e10cSrcweir 
977*cdf0e10cSrcweir     sal_Int32 nVarCount = aVariables.getLength();
978*cdf0e10cSrcweir     uno::Sequence<double> aOldValues;
979*cdf0e10cSrcweir     aOldValues.realloc( nVarCount );
980*cdf0e10cSrcweir     for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
981*cdf0e10cSrcweir     {
982*cdf0e10cSrcweir         ScAddress aCellPos;
983*cdf0e10cSrcweir         ScUnoConversion::FillScAddress( aCellPos, aVariables[nVarPos] );
984*cdf0e10cSrcweir         aOldValues[nVarPos] = mpDoc->GetValue( aCellPos );
985*cdf0e10cSrcweir     }
986*cdf0e10cSrcweir 
987*cdf0e10cSrcweir     // create and initialize solver
988*cdf0e10cSrcweir 
989*cdf0e10cSrcweir     uno::Reference<sheet::XSolver> xSolver = ScSolverUtil::GetSolver( maEngine );
990*cdf0e10cSrcweir     DBG_ASSERT( xSolver.is(), "can't get solver component" );
991*cdf0e10cSrcweir     if ( !xSolver.is() )
992*cdf0e10cSrcweir         return false;
993*cdf0e10cSrcweir 
994*cdf0e10cSrcweir     xSolver->setDocument( xDocument );
995*cdf0e10cSrcweir     xSolver->setObjective( aObjective );
996*cdf0e10cSrcweir     xSolver->setVariables( aVariables );
997*cdf0e10cSrcweir     xSolver->setConstraints( aConstraints );
998*cdf0e10cSrcweir     xSolver->setMaximize( bMaximize );
999*cdf0e10cSrcweir 
1000*cdf0e10cSrcweir     // set options
1001*cdf0e10cSrcweir     uno::Reference<beans::XPropertySet> xOptProp(xSolver, uno::UNO_QUERY);
1002*cdf0e10cSrcweir     if ( xOptProp.is() )
1003*cdf0e10cSrcweir     {
1004*cdf0e10cSrcweir         sal_Int32 nPropCount = maProperties.getLength();
1005*cdf0e10cSrcweir         for (sal_Int32 nProp=0; nProp<nPropCount; ++nProp)
1006*cdf0e10cSrcweir         {
1007*cdf0e10cSrcweir             const beans::PropertyValue& rValue = maProperties[nProp];
1008*cdf0e10cSrcweir             try
1009*cdf0e10cSrcweir             {
1010*cdf0e10cSrcweir                 xOptProp->setPropertyValue( rValue.Name, rValue.Value );
1011*cdf0e10cSrcweir             }
1012*cdf0e10cSrcweir             catch ( uno::Exception & )
1013*cdf0e10cSrcweir             {
1014*cdf0e10cSrcweir                 DBG_ERRORFILE("Exception in solver option property");
1015*cdf0e10cSrcweir             }
1016*cdf0e10cSrcweir         }
1017*cdf0e10cSrcweir     }
1018*cdf0e10cSrcweir 
1019*cdf0e10cSrcweir     xSolver->solve();
1020*cdf0e10cSrcweir     sal_Bool bSuccess = xSolver->getSuccess();
1021*cdf0e10cSrcweir 
1022*cdf0e10cSrcweir     aProgress.Hide();
1023*cdf0e10cSrcweir     bool bClose = false;
1024*cdf0e10cSrcweir     bool bRestore = true;   // restore old values unless a solution is accepted
1025*cdf0e10cSrcweir     if ( bSuccess )
1026*cdf0e10cSrcweir     {
1027*cdf0e10cSrcweir         // put solution into document so it is visible when asking
1028*cdf0e10cSrcweir         uno::Sequence<double> aSolution = xSolver->getSolution();
1029*cdf0e10cSrcweir         if ( aSolution.getLength() == nVarCount )
1030*cdf0e10cSrcweir         {
1031*cdf0e10cSrcweir             mpDocShell->LockPaint();
1032*cdf0e10cSrcweir             ScDocFunc aFunc(*mpDocShell);
1033*cdf0e10cSrcweir             for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
1034*cdf0e10cSrcweir             {
1035*cdf0e10cSrcweir                 ScAddress aCellPos;
1036*cdf0e10cSrcweir                 ScUnoConversion::FillScAddress( aCellPos, aVariables[nVarPos] );
1037*cdf0e10cSrcweir                 aFunc.PutCell( aCellPos, new ScValueCell( aSolution[nVarPos] ), sal_True );
1038*cdf0e10cSrcweir             }
1039*cdf0e10cSrcweir             mpDocShell->UnlockPaint();
1040*cdf0e10cSrcweir         }
1041*cdf0e10cSrcweir         //! else error?
1042*cdf0e10cSrcweir 
1043*cdf0e10cSrcweir         // take formatted result from document (result value from component is ignored)
1044*cdf0e10cSrcweir         String aResultStr;
1045*cdf0e10cSrcweir         mpDoc->GetString( (SCCOL)aObjective.Column, (SCROW)aObjective.Row, (SCTAB)aObjective.Sheet, aResultStr );
1046*cdf0e10cSrcweir         ScSolverSuccessDialog aDialog( this, aResultStr );
1047*cdf0e10cSrcweir         if ( aDialog.Execute() == RET_OK )
1048*cdf0e10cSrcweir         {
1049*cdf0e10cSrcweir             // keep results and close dialog
1050*cdf0e10cSrcweir             bRestore = false;
1051*cdf0e10cSrcweir             bClose = true;
1052*cdf0e10cSrcweir         }
1053*cdf0e10cSrcweir     }
1054*cdf0e10cSrcweir     else
1055*cdf0e10cSrcweir     {
1056*cdf0e10cSrcweir         rtl::OUString aError;
1057*cdf0e10cSrcweir         uno::Reference<sheet::XSolverDescription> xDesc( xSolver, uno::UNO_QUERY );
1058*cdf0e10cSrcweir         if ( xDesc.is() )
1059*cdf0e10cSrcweir             aError = xDesc->getStatusDescription();         // error description from component
1060*cdf0e10cSrcweir         ScSolverNoSolutionDialog aDialog( this, aError );
1061*cdf0e10cSrcweir         aDialog.Execute();
1062*cdf0e10cSrcweir     }
1063*cdf0e10cSrcweir 
1064*cdf0e10cSrcweir     if ( bRestore )         // restore old values
1065*cdf0e10cSrcweir     {
1066*cdf0e10cSrcweir         mpDocShell->LockPaint();
1067*cdf0e10cSrcweir         ScDocFunc aFunc(*mpDocShell);
1068*cdf0e10cSrcweir         for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
1069*cdf0e10cSrcweir         {
1070*cdf0e10cSrcweir             ScAddress aCellPos;
1071*cdf0e10cSrcweir             ScUnoConversion::FillScAddress( aCellPos, aVariables[nVarPos] );
1072*cdf0e10cSrcweir             aFunc.PutCell( aCellPos, new ScValueCell( aOldValues[nVarPos] ), sal_True );
1073*cdf0e10cSrcweir         }
1074*cdf0e10cSrcweir         mpDocShell->UnlockPaint();
1075*cdf0e10cSrcweir     }
1076*cdf0e10cSrcweir 
1077*cdf0e10cSrcweir     return bClose;
1078*cdf0e10cSrcweir }
1079*cdf0e10cSrcweir 
1080