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