diff options
Diffstat (limited to 'sc/source/ui/miscdlgs/solveroptions.cxx')
-rw-r--r-- | sc/source/ui/miscdlgs/solveroptions.cxx | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/sc/source/ui/miscdlgs/solveroptions.cxx b/sc/source/ui/miscdlgs/solveroptions.cxx new file mode 100644 index 000000000000..05ccd3553ef5 --- /dev/null +++ b/sc/source/ui/miscdlgs/solveroptions.cxx @@ -0,0 +1,494 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +//------------------------------------------------------------------ + +#include "solveroptions.hxx" +#include "solveroptions.hrc" +#include "scresid.hxx" +#include "global.hxx" +#include "miscuno.hxx" +#include "solverutil.hxx" + +#include <rtl/math.hxx> +#include <vcl/msgbox.hxx> +#include <unotools/collatorwrapper.hxx> +#include <unotools/localedatawrapper.hxx> + +#include <algorithm> + +#include <com/sun/star/sheet/Solver.hpp> +#include <com/sun/star/sheet/XSolverDescription.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> + +using namespace com::sun::star; + +//================================================================== + +/// Helper for sorting properties +struct ScSolverOptionsEntry +{ + sal_Int32 nPosition; + rtl::OUString aDescription; + + ScSolverOptionsEntry() : nPosition(0) {} + + bool operator< (const ScSolverOptionsEntry& rOther) const + { + return ( ScGlobal::GetCollator()->compareString( aDescription, rOther.aDescription ) == COMPARE_LESS ); + } +}; + +//------------------------------------------------------------------ + +class ScSolverOptionsString : public SvLBoxString +{ + bool mbIsDouble; + double mfDoubleValue; + sal_Int32 mnIntValue; + +public: + ScSolverOptionsString( SvLBoxEntry* pEntry, USHORT nFlags, const String& rStr ) : + SvLBoxString( pEntry, nFlags, rStr ), + mbIsDouble( false ), + mfDoubleValue( 0.0 ), + mnIntValue( 0 ) {} + + bool IsDouble() const { return mbIsDouble; } + double GetDoubleValue() const { return mfDoubleValue; } + sal_Int32 GetIntValue() const { return mnIntValue; } + + void SetDoubleValue( double fNew ) { mbIsDouble = true; mfDoubleValue = fNew; } + void SetIntValue( sal_Int32 nNew ) { mbIsDouble = false; mnIntValue = nNew; } + + virtual void Paint( const Point& rPos, SvLBox& rDev, USHORT nFlags, SvLBoxEntry* pEntry ); +}; + +void ScSolverOptionsString::Paint( const Point& rPos, SvLBox& rDev, USHORT, SvLBoxEntry* /* pEntry */ ) +{ + //! move position? (SvxLinguTabPage: aPos.X() += 20) + String aNormalStr( GetText() ); + aNormalStr.Append( (sal_Unicode) ':' ); + rDev.DrawText( rPos, aNormalStr ); + + Point aNewPos( rPos ); + aNewPos.X() += rDev.GetTextWidth( aNormalStr ); + Font aOldFont( rDev.GetFont() ); + Font aFont( aOldFont ); + aFont.SetWeight( WEIGHT_BOLD ); + + String sTxt( ' ' ); + if ( mbIsDouble ) + sTxt += (String)rtl::math::doubleToUString( mfDoubleValue, + rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, + ScGlobal::GetpLocaleData()->getNumDecimalSep().GetChar(0), true ); + else + sTxt += String::CreateFromInt32( mnIntValue ); + rDev.SetFont( aFont ); + rDev.DrawText( aNewPos, sTxt ); + + rDev.SetFont( aOldFont ); +} + +//------------------------------------------------------------------ + +ScSolverOptionsDialog::ScSolverOptionsDialog( Window* pParent, + const uno::Sequence<rtl::OUString>& rImplNames, + const uno::Sequence<rtl::OUString>& rDescriptions, + const String& rEngine, + const uno::Sequence<beans::PropertyValue>& rProperties ) + : ModalDialog( pParent, ScResId( RID_SCDLG_SOLVEROPTIONS ) ), + maFtEngine ( this, ScResId( FT_ENGINE ) ), + maLbEngine ( this, ScResId( LB_ENGINE ) ), + maFtSettings ( this, ScResId( FT_SETTINGS ) ), + maLbSettings ( this, ScResId( LB_SETTINGS ) ), + maBtnEdit ( this, ScResId( BTN_EDIT ) ), + maFlButtons ( this, ScResId( FL_BUTTONS ) ), + maBtnHelp ( this, ScResId( BTN_HELP ) ), + maBtnOk ( this, ScResId( BTN_OK ) ), + maBtnCancel ( this, ScResId( BTN_CANCEL ) ), + mpCheckButtonData( NULL ), + maImplNames( rImplNames ), + maDescriptions( rDescriptions ), + maEngine( rEngine ), + maProperties( rProperties ) +{ + maLbEngine.SetSelectHdl( LINK( this, ScSolverOptionsDialog, EngineSelectHdl ) ); + + maBtnEdit.SetClickHdl( LINK( this, ScSolverOptionsDialog, ButtonHdl ) ); + + maLbSettings.SetWindowBits( WB_CLIPCHILDREN|WB_FORCE_MAKEVISIBLE ); + maLbSettings.SetHelpId( HID_SC_SOLVEROPTIONS_LB ); + maLbSettings.SetHighlightRange(); + + maLbSettings.SetSelectHdl( LINK( this, ScSolverOptionsDialog, SettingsSelHdl ) ); + maLbSettings.SetDoubleClickHdl( LINK( this, ScSolverOptionsDialog, SettingsDoubleClickHdl ) ); + + sal_Int32 nSelect = -1; + sal_Int32 nImplCount = maImplNames.getLength(); + for (sal_Int32 nImpl=0; nImpl<nImplCount; ++nImpl) + { + String aImplName( maImplNames[nImpl] ); + String aDescription( maDescriptions[nImpl] ); // user-visible descriptions in list box + maLbEngine.InsertEntry( aDescription ); + if ( aImplName == maEngine ) + nSelect = nImpl; + } + if ( nSelect < 0 ) // no (valid) engine given + { + if ( nImplCount > 0 ) + { + maEngine = maImplNames[0]; // use first implementation + nSelect = 0; + } + else + maEngine.Erase(); + maProperties.realloc(0); // don't use options from different engine + } + if ( nSelect >= 0 ) // select in list box + maLbEngine.SelectEntryPos( static_cast<USHORT>(nSelect) ); + + if ( !maProperties.getLength() ) + ReadFromComponent(); // fill maProperties from component (using maEngine) + FillListBox(); // using maProperties + + FreeResource(); +} + +ScSolverOptionsDialog::~ScSolverOptionsDialog() +{ + delete mpCheckButtonData; +} + +const String& ScSolverOptionsDialog::GetEngine() const +{ + return maEngine; // already updated in selection handler +} + +const uno::Sequence<beans::PropertyValue>& ScSolverOptionsDialog::GetProperties() +{ + // update maProperties from list box content + // order of entries in list box and maProperties is the same + sal_Int32 nEntryCount = maProperties.getLength(); + SvLBoxTreeList* pModel = maLbSettings.GetModel(); + if ( nEntryCount == (sal_Int32)pModel->GetEntryCount() ) + { + for (sal_Int32 nEntryPos=0; nEntryPos<nEntryCount; ++nEntryPos) + { + uno::Any& rValue = maProperties[nEntryPos].Value; + SvLBoxEntry* pEntry = pModel->GetEntry(nEntryPos); + + bool bHasData = false; + USHORT nItemCount = pEntry->ItemCount(); + for (USHORT nItemPos=0; nItemPos<nItemCount && !bHasData; ++nItemPos) + { + SvLBoxItem* pItem = pEntry->GetItem( nItemPos ); + ScSolverOptionsString* pStringItem = dynamic_cast<ScSolverOptionsString*>(pItem); + if ( pStringItem ) + { + if ( pStringItem->IsDouble() ) + rValue <<= pStringItem->GetDoubleValue(); + else + rValue <<= pStringItem->GetIntValue(); + bHasData = true; + } + } + if ( !bHasData ) + ScUnoHelpFunctions::SetBoolInAny( rValue, + maLbSettings.GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED ); + } + } + else + { + DBG_ERRORFILE( "wrong count" ); + } + + return maProperties; +} + +void ScSolverOptionsDialog::FillListBox() +{ + // get property descriptions, sort by them + + uno::Reference<sheet::XSolverDescription> xDesc( ScSolverUtil::GetSolver( maEngine ), uno::UNO_QUERY ); + sal_Int32 nCount = maProperties.getLength(); + std::vector<ScSolverOptionsEntry> aDescriptions( nCount ); + for (sal_Int32 nPos=0; nPos<nCount; nPos++) + { + rtl::OUString aPropName( maProperties[nPos].Name ); + rtl::OUString aVisName; + if ( xDesc.is() ) + aVisName = xDesc->getPropertyDescription( aPropName ); + if ( !aVisName.getLength() ) + aVisName = aPropName; + aDescriptions[nPos].nPosition = nPos; + aDescriptions[nPos].aDescription = aVisName; + } + std::sort( aDescriptions.begin(), aDescriptions.end() ); + + // also update maProperties to the order of descriptions + + uno::Sequence<beans::PropertyValue> aNewSeq; + aNewSeq.realloc( nCount ); + for (sal_Int32 nPos=0; nPos<nCount; nPos++) + aNewSeq[nPos] = maProperties[ aDescriptions[nPos].nPosition ]; + maProperties = aNewSeq; + + // fill the list box + + maLbSettings.SetUpdateMode(FALSE); + maLbSettings.Clear(); + + String sEmpty; + if (!mpCheckButtonData) + mpCheckButtonData = new SvLBoxButtonData( &maLbSettings ); + + SvLBoxTreeList* pModel = maLbSettings.GetModel(); + SvLBoxEntry* pEntry = NULL; + + for (sal_Int32 nPos=0; nPos<nCount; nPos++) + { + rtl::OUString aVisName = aDescriptions[nPos].aDescription; + + uno::Any aValue = maProperties[nPos].Value; + uno::TypeClass eClass = aValue.getValueTypeClass(); + if ( eClass == uno::TypeClass_BOOLEAN ) + { + // check box entry + pEntry = new SvLBoxEntry; + SvLBoxButton* pButton = new SvLBoxButton( pEntry, SvLBoxButtonKind_enabledCheckbox, 0, mpCheckButtonData ); + if ( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ) + pButton->SetStateChecked(); + else + pButton->SetStateUnchecked(); + pEntry->AddItem( pButton ); + pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), 0 ) ); + pEntry->AddItem( new SvLBoxString( pEntry, 0, aVisName ) ); + } + else + { + // value entry + pEntry = new SvLBoxEntry; + pEntry->AddItem( new SvLBoxString( pEntry, 0, sEmpty ) ); // empty column + pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), 0 ) ); + ScSolverOptionsString* pItem = new ScSolverOptionsString( pEntry, 0, aVisName ); + if ( eClass == uno::TypeClass_DOUBLE ) + { + double fDoubleValue = 0.0; + if ( aValue >>= fDoubleValue ) + pItem->SetDoubleValue( fDoubleValue ); + } + else + { + sal_Int32 nIntValue = 0; + if ( aValue >>= nIntValue ) + pItem->SetIntValue( nIntValue ); + } + pEntry->AddItem( pItem ); + } + pModel->Insert( pEntry ); + } + + maLbSettings.SetUpdateMode(TRUE); +} + +void ScSolverOptionsDialog::ReadFromComponent() +{ + maProperties = ScSolverUtil::GetDefaults( maEngine ); +} + +void ScSolverOptionsDialog::EditOption() +{ + SvLBoxEntry* pEntry = maLbSettings.GetCurEntry(); + if (pEntry) + { + USHORT nItemCount = pEntry->ItemCount(); + for (USHORT nPos=0; nPos<nItemCount; ++nPos) + { + SvLBoxItem* pItem = pEntry->GetItem( nPos ); + ScSolverOptionsString* pStringItem = dynamic_cast<ScSolverOptionsString*>(pItem); + if ( pStringItem ) + { + if ( pStringItem->IsDouble() ) + { + ScSolverValueDialog aValDialog( this ); + aValDialog.SetOptionName( pStringItem->GetText() ); + aValDialog.SetValue( pStringItem->GetDoubleValue() ); + if ( aValDialog.Execute() == RET_OK ) + { + pStringItem->SetDoubleValue( aValDialog.GetValue() ); + maLbSettings.InvalidateEntry( pEntry ); + } + } + else + { + ScSolverIntegerDialog aIntDialog( this ); + aIntDialog.SetOptionName( pStringItem->GetText() ); + aIntDialog.SetValue( pStringItem->GetIntValue() ); + if ( aIntDialog.Execute() == RET_OK ) + { + pStringItem->SetIntValue( aIntDialog.GetValue() ); + maLbSettings.InvalidateEntry( pEntry ); + } + } + } + } + } +} + +IMPL_LINK( ScSolverOptionsDialog, ButtonHdl, PushButton*, pBtn ) +{ + if ( pBtn == &maBtnEdit ) + EditOption(); + + return 0; +} + +IMPL_LINK( ScSolverOptionsDialog, SettingsDoubleClickHdl, SvTreeListBox*, EMPTYARG ) +{ + EditOption(); + return 0; +} + +IMPL_LINK( ScSolverOptionsDialog, EngineSelectHdl, ListBox*, EMPTYARG ) +{ + USHORT nSelectPos = maLbEngine.GetSelectEntryPos(); + if ( nSelectPos < maImplNames.getLength() ) + { + String aNewEngine( maImplNames[nSelectPos] ); + if ( aNewEngine != maEngine ) + { + maEngine = aNewEngine; + ReadFromComponent(); // fill maProperties from component (using maEngine) + FillListBox(); // using maProperties + } + } + return 0; +} + +IMPL_LINK( ScSolverOptionsDialog, SettingsSelHdl, SvxCheckListBox*, EMPTYARG ) +{ + BOOL bCheckbox = FALSE; + + SvLBoxEntry* pEntry = maLbSettings.GetCurEntry(); + if (pEntry) + { + SvLBoxItem* pItem = pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON); + if ( pItem && pItem->IsA() == SV_ITEM_ID_LBOXBUTTON ) + bCheckbox = TRUE; + } + + maBtnEdit.Enable( !bCheckbox ); + + return 0; +} + +//------------------------------------------------------------------ + +ScSolverIntegerDialog::ScSolverIntegerDialog( Window * pParent ) + : ModalDialog( pParent, ScResId( RID_SCDLG_SOLVER_INTEGER ) ), + maFtName ( this, ScResId( FT_OPTIONNAME ) ), + maNfValue ( this, ScResId( NF_VALUE ) ), + maFlButtons ( this, ScResId( FL_BUTTONS ) ), + maBtnOk ( this, ScResId( BTN_OK ) ), + maBtnCancel ( this, ScResId( BTN_CANCEL ) ) +{ + FreeResource(); +} + +ScSolverIntegerDialog::~ScSolverIntegerDialog() +{ +} + +void ScSolverIntegerDialog::SetOptionName( const String& rName ) +{ + maFtName.SetText( rName ); +} + +void ScSolverIntegerDialog::SetValue( sal_Int32 nValue ) +{ + maNfValue.SetValue( nValue ); +} + +sal_Int32 ScSolverIntegerDialog::GetValue() const +{ + sal_Int64 nValue = maNfValue.GetValue(); + if ( nValue < SAL_MIN_INT32 ) + return SAL_MIN_INT32; + if ( nValue > SAL_MAX_INT32 ) + return SAL_MAX_INT32; + return (sal_Int32) nValue; +} + +//------------------------------------------------------------------ + +ScSolverValueDialog::ScSolverValueDialog( Window * pParent ) + : ModalDialog( pParent, ScResId( RID_SCDLG_SOLVER_DOUBLE ) ), + maFtName ( this, ScResId( FT_OPTIONNAME ) ), + maEdValue ( this, ScResId( ED_VALUE ) ), + maFlButtons ( this, ScResId( FL_BUTTONS ) ), + maBtnOk ( this, ScResId( BTN_OK ) ), + maBtnCancel ( this, ScResId( BTN_CANCEL ) ) +{ + FreeResource(); +} + +ScSolverValueDialog::~ScSolverValueDialog() +{ +} + +void ScSolverValueDialog::SetOptionName( const String& rName ) +{ + maFtName.SetText( rName ); +} + +void ScSolverValueDialog::SetValue( double fValue ) +{ + maEdValue.SetText( rtl::math::doubleToUString( fValue, + rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, + ScGlobal::GetpLocaleData()->getNumDecimalSep().GetChar(0), true ) ); +} + +double ScSolverValueDialog::GetValue() const +{ + String aInput = maEdValue.GetText(); + + const LocaleDataWrapper* pLocaleData = ScGlobal::GetpLocaleData(); + rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok; + double fValue = rtl::math::stringToDouble( aInput, + pLocaleData->getNumDecimalSep().GetChar(0), + pLocaleData->getNumThousandSep().GetChar(0), + &eStatus, NULL ); + return fValue; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |