LCOV - code coverage report
Current view: top level - sc/source/ui/miscdlgs - optsolver.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 691 0.1 %
Date: 2015-06-13 12:38:46 Functions: 2 59 3.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11