/************************************************************************* * * 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 * * 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 #include #include #include #include #include #include #include #include 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, sal_uInt16 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, sal_uInt16 nFlags, SvLBoxEntry* pEntry ); }; void ScSolverOptionsString::Paint( const Point& rPos, SvLBox& rDev, sal_uInt16, 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& rImplNames, const uno::Sequence& rDescriptions, const String& rEngine, const uno::Sequence& 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.SetStyle( maLbSettings.GetStyle()|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 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(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& 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; nEntryPosGetEntry(nEntryPos); bool bHasData = false; sal_uInt16 nItemCount = pEntry->ItemCount(); for (sal_uInt16 nItemPos=0; nItemPosGetItem( nItemPos ); ScSolverOptionsString* pStringItem = dynamic_cast(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 xDesc( ScSolverUtil::GetSolver( maEngine ), uno::UNO_QUERY ); sal_Int32 nCount = maProperties.getLength(); std::vector aDescriptions( nCount ); for (sal_Int32 nPos=0; nPosgetPropertyDescription( 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 aNewSeq; aNewSeq.realloc( nCount ); for (sal_Int32 nPos=0; nPosSetStateChecked(); 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(sal_True); } void ScSolverOptionsDialog::ReadFromComponent() { maProperties = ScSolverUtil::GetDefaults( maEngine ); } void ScSolverOptionsDialog::EditOption() { SvLBoxEntry* pEntry = maLbSettings.GetCurEntry(); if (pEntry) { sal_uInt16 nItemCount = pEntry->ItemCount(); for (sal_uInt16 nPos=0; nPosGetItem( nPos ); ScSolverOptionsString* pStringItem = dynamic_cast(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 ) { sal_uInt16 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 ) { sal_Bool bCheckbox = sal_False; SvLBoxEntry* pEntry = maLbSettings.GetCurEntry(); if (pEntry) { SvLBoxItem* pItem = pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON); if ( pItem && pItem->IsA() == SV_ITEM_ID_LBOXBUTTON ) bCheckbox = sal_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; }