/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include "solveroptions.hxx" #include "solveroptions.hrc" #include "scresid.hxx" #include "global.hxx" #include "miscuno.hxx" #include "solverutil.hxx" #include #include #include #include #include "svtools/treelistentry.hxx" #include #include #include #include #include using namespace com::sun::star; /// Helper for sorting properties struct ScSolverOptionsEntry { sal_Int32 nPosition; OUString aDescription; ScSolverOptionsEntry() : nPosition(0) {} bool operator< (const ScSolverOptionsEntry& rOther) const { return (ScGlobal::GetCollator()->compareString( aDescription, rOther.aDescription ) < 0); } }; class ScSolverOptionsString : public SvLBoxString { bool mbIsDouble; double mfDoubleValue; sal_Int32 mnIntValue; public: ScSolverOptionsString( SvTreeListEntry* pEntry, sal_uInt16 nFlags, const OUString& 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, SvTreeListBox& rDev, const SvViewDataEntry* pView, const SvTreeListEntry* pEntry) SAL_OVERRIDE; }; void ScSolverOptionsString::Paint( const Point& rPos, SvTreeListBox& rDev, const SvViewDataEntry* /*pView*/, const SvTreeListEntry* /*pEntry*/) { //! move position? (SvxLinguTabPage: aPos.X() += 20) OUString aNormalStr( GetText() ); aNormalStr += ":"; rDev.DrawText( rPos, aNormalStr ); Point aNewPos( rPos ); aNewPos.X() += rDev.GetTextWidth( aNormalStr ); Font aOldFont( rDev.GetFont() ); Font aFont( aOldFont ); aFont.SetWeight( WEIGHT_BOLD ); OUString sTxt( ' ' ); if ( mbIsDouble ) sTxt += rtl::math::doubleToUString( mfDoubleValue, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, ScGlobal::GetpLocaleData()->getNumDecimalSep()[0], true ); else sTxt += OUString::number(mnIntValue); rDev.SetFont( aFont ); rDev.DrawText( aNewPos, sTxt ); rDev.SetFont( aOldFont ); } ScSolverOptionsDialog::ScSolverOptionsDialog( Window* pParent, const uno::Sequence& rImplNames, const uno::Sequence& rDescriptions, const OUString& rEngine, const uno::Sequence& rProperties ) : ModalDialog(pParent, "SolverOptionsDialog", "modules/scalc/ui/solveroptionsdialog.ui") , mpCheckButtonData(NULL) , maImplNames(rImplNames) , maDescriptions(rDescriptions) , maEngine(rEngine) , maProperties(rProperties) { get(m_pLbEngine, "engine"); get(m_pLbSettings, "settings"); get(m_pBtnEdit, "edit"); m_pLbEngine->SetSelectHdl( LINK( this, ScSolverOptionsDialog, EngineSelectHdl ) ); m_pBtnEdit->SetClickHdl( LINK( this, ScSolverOptionsDialog, ButtonHdl ) ); m_pLbSettings->SetStyle( m_pLbSettings->GetStyle()|WB_CLIPCHILDREN|WB_FORCE_MAKEVISIBLE ); m_pLbSettings->SetHighlightRange(); m_pLbSettings->SetSelectHdl( LINK( this, ScSolverOptionsDialog, SettingsSelHdl ) ); m_pLbSettings->SetDoubleClickHdl( LINK( this, ScSolverOptionsDialog, SettingsDoubleClickHdl ) ); sal_Int32 nSelect = -1; sal_Int32 nImplCount = maImplNames.getLength(); for (sal_Int32 nImpl=0; nImplInsertEntry( 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 = ""; maProperties.realloc(0); // don't use options from different engine } if ( nSelect >= 0 ) // select in list box m_pLbEngine->SelectEntryPos( static_cast(nSelect) ); if ( !maProperties.getLength() ) ReadFromComponent(); // fill maProperties from component (using maEngine) FillListBox(); // using maProperties } ScSolverOptionsDialog::~ScSolverOptionsDialog() { delete mpCheckButtonData; } const OUString& 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(); SvTreeList* pModel = m_pLbSettings->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, m_pLbSettings->GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED ); } } else { OSL_FAIL( "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.isEmpty() ) 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; nPosSetUpdateMode(false); m_pLbSettings->Clear(); OUString sEmpty; if (!mpCheckButtonData) mpCheckButtonData = new SvLBoxButtonData(m_pLbSettings); SvTreeList* pModel = m_pLbSettings->GetModel(); SvTreeListEntry* pEntry = NULL; for (sal_Int32 nPos=0; nPosSetStateChecked(); else pButton->SetStateUnchecked(); pEntry->AddItem( pButton ); pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), false ) ); pEntry->AddItem( new SvLBoxString( pEntry, 0, aVisName ) ); } else { // value entry pEntry = new SvTreeListEntry; pEntry->AddItem( new SvLBoxString( pEntry, 0, sEmpty ) ); // empty column pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), false ) ); 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 ); } m_pLbSettings->SetUpdateMode(true); } void ScSolverOptionsDialog::ReadFromComponent() { maProperties = ScSolverUtil::GetDefaults( maEngine ); } void ScSolverOptionsDialog::EditOption() { SvTreeListEntry* pEntry = m_pLbSettings->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() ); m_pLbSettings->InvalidateEntry( pEntry ); } } else { ScSolverIntegerDialog aIntDialog( this ); aIntDialog.SetOptionName( pStringItem->GetText() ); aIntDialog.SetValue( pStringItem->GetIntValue() ); if ( aIntDialog.Execute() == RET_OK ) { pStringItem->SetIntValue( aIntDialog.GetValue() ); m_pLbSettings->InvalidateEntry( pEntry ); } } } } } } IMPL_LINK( ScSolverOptionsDialog, ButtonHdl, PushButton*, pBtn ) { if (pBtn == m_pBtnEdit) EditOption(); return 0; } IMPL_LINK_NOARG(ScSolverOptionsDialog, SettingsDoubleClickHdl) { EditOption(); return 0; } IMPL_LINK_NOARG(ScSolverOptionsDialog, EngineSelectHdl) { sal_uInt16 nSelectPos = m_pLbEngine->GetSelectEntryPos(); if ( nSelectPos < maImplNames.getLength() ) { OUString aNewEngine( maImplNames[nSelectPos] ); if ( aNewEngine != maEngine ) { maEngine = aNewEngine; ReadFromComponent(); // fill maProperties from component (using maEngine) FillListBox(); // using maProperties } } return 0; } IMPL_LINK_NOARG(ScSolverOptionsDialog, SettingsSelHdl) { sal_Bool bCheckbox = false; SvTreeListEntry* pEntry = m_pLbSettings->GetCurEntry(); if (pEntry) { SvLBoxItem* pItem = pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON); if (pItem && pItem->GetType() == SV_ITEM_ID_LBOXBUTTON) bCheckbox = true; } m_pBtnEdit->Enable( !bCheckbox ); return 0; } ScSolverIntegerDialog::ScSolverIntegerDialog(Window * pParent) : ModalDialog( pParent, "IntegerDialog", "modules/scalc/ui/integerdialog.ui" ) { get(m_pFrame, "frame"); get(m_pNfValue, "value"); } void ScSolverIntegerDialog::SetOptionName( const OUString& rName ) { m_pFrame->set_label(rName); } void ScSolverIntegerDialog::SetValue( sal_Int32 nValue ) { m_pNfValue->SetValue( nValue ); } sal_Int32 ScSolverIntegerDialog::GetValue() const { sal_Int64 nValue = m_pNfValue->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, "DoubleDialog", "modules/scalc/ui/doubledialog.ui" ) { get(m_pFrame, "frame"); get(m_pEdValue, "value"); } void ScSolverValueDialog::SetOptionName( const OUString& rName ) { m_pFrame->set_label(rName); } void ScSolverValueDialog::SetValue( double fValue ) { m_pEdValue->SetText( rtl::math::doubleToUString( fValue, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, ScGlobal::GetpLocaleData()->getNumDecimalSep()[0], true ) ); } double ScSolverValueDialog::GetValue() const { OUString aInput = m_pEdValue->GetText(); const LocaleDataWrapper* pLocaleData = ScGlobal::GetpLocaleData(); rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok; double fValue = rtl::math::stringToDouble( aInput, pLocaleData->getNumDecimalSep()[0], pLocaleData->getNumThousandSep()[0], &eStatus, NULL ); return fValue; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */