Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / sc / source / ui / miscdlgs / solveroptions.cxx
blob2d660778915ad16e9ff86240c0674a21b0b440bb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "solveroptions.hxx"
21 #include "solveroptions.hrc"
22 #include "scresid.hxx"
23 #include "global.hxx"
24 #include "miscuno.hxx"
25 #include "solverutil.hxx"
27 #include <rtl/math.hxx>
28 #include <vcl/msgbox.hxx>
29 #include <unotools/collatorwrapper.hxx>
30 #include <unotools/localedatawrapper.hxx>
31 #include "svtools/treelistentry.hxx"
33 #include <algorithm>
35 #include <com/sun/star/sheet/Solver.hpp>
36 #include <com/sun/star/sheet/XSolverDescription.hpp>
37 #include <com/sun/star/beans/PropertyValue.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
40 using namespace com::sun::star;
42 //==================================================================
44 /// Helper for sorting properties
45 struct ScSolverOptionsEntry
47 sal_Int32 nPosition;
48 rtl::OUString aDescription;
50 ScSolverOptionsEntry() : nPosition(0) {}
52 bool operator< (const ScSolverOptionsEntry& rOther) const
54 return ( ScGlobal::GetCollator()->compareString( aDescription, rOther.aDescription ) == COMPARE_LESS );
58 //------------------------------------------------------------------
60 class ScSolverOptionsString : public SvLBoxString
62 bool mbIsDouble;
63 double mfDoubleValue;
64 sal_Int32 mnIntValue;
66 public:
67 ScSolverOptionsString( SvTreeListEntry* pEntry, sal_uInt16 nFlags, const String& rStr ) :
68 SvLBoxString( pEntry, nFlags, rStr ),
69 mbIsDouble( false ),
70 mfDoubleValue( 0.0 ),
71 mnIntValue( 0 ) {}
73 bool IsDouble() const { return mbIsDouble; }
74 double GetDoubleValue() const { return mfDoubleValue; }
75 sal_Int32 GetIntValue() const { return mnIntValue; }
77 void SetDoubleValue( double fNew ) { mbIsDouble = true; mfDoubleValue = fNew; }
78 void SetIntValue( sal_Int32 nNew ) { mbIsDouble = false; mnIntValue = nNew; }
80 virtual void Paint(const Point& rPos, SvTreeListBox& rDev, const SvViewDataEntry* pView, const SvTreeListEntry* pEntry);
83 void ScSolverOptionsString::Paint( const Point& rPos, SvTreeListBox& rDev, const SvViewDataEntry* /*pView*/, const SvTreeListEntry* /*pEntry*/)
85 //! move position? (SvxLinguTabPage: aPos.X() += 20)
86 String aNormalStr( GetText() );
87 aNormalStr.Append( (sal_Unicode) ':' );
88 rDev.DrawText( rPos, aNormalStr );
90 Point aNewPos( rPos );
91 aNewPos.X() += rDev.GetTextWidth( aNormalStr );
92 Font aOldFont( rDev.GetFont() );
93 Font aFont( aOldFont );
94 aFont.SetWeight( WEIGHT_BOLD );
96 rtl::OUString sTxt( ' ' );
97 if ( mbIsDouble )
98 sTxt += rtl::math::doubleToUString( mfDoubleValue,
99 rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
100 ScGlobal::GetpLocaleData()->getNumDecimalSep()[0], true );
101 else
102 sTxt += rtl::OUString::valueOf(mnIntValue);
103 rDev.SetFont( aFont );
104 rDev.DrawText( aNewPos, sTxt );
106 rDev.SetFont( aOldFont );
109 //------------------------------------------------------------------
111 ScSolverOptionsDialog::ScSolverOptionsDialog( Window* pParent,
112 const uno::Sequence<rtl::OUString>& rImplNames,
113 const uno::Sequence<rtl::OUString>& rDescriptions,
114 const String& rEngine,
115 const uno::Sequence<beans::PropertyValue>& rProperties )
116 : ModalDialog( pParent, ScResId( RID_SCDLG_SOLVEROPTIONS ) ),
117 maFtEngine ( this, ScResId( FT_ENGINE ) ),
118 maLbEngine ( this, ScResId( LB_ENGINE ) ),
119 maFtSettings ( this, ScResId( FT_SETTINGS ) ),
120 maLbSettings ( this, ScResId( LB_SETTINGS ) ),
121 maBtnEdit ( this, ScResId( BTN_EDIT ) ),
122 maFlButtons ( this, ScResId( FL_BUTTONS ) ),
123 maBtnHelp ( this, ScResId( BTN_HELP ) ),
124 maBtnOk ( this, ScResId( BTN_OK ) ),
125 maBtnCancel ( this, ScResId( BTN_CANCEL ) ),
126 mpCheckButtonData( NULL ),
127 maImplNames( rImplNames ),
128 maDescriptions( rDescriptions ),
129 maEngine( rEngine ),
130 maProperties( rProperties )
132 maLbEngine.SetSelectHdl( LINK( this, ScSolverOptionsDialog, EngineSelectHdl ) );
134 maBtnEdit.SetClickHdl( LINK( this, ScSolverOptionsDialog, ButtonHdl ) );
136 maLbSettings.SetStyle( maLbSettings.GetStyle()|WB_CLIPCHILDREN|WB_FORCE_MAKEVISIBLE );
137 maLbSettings.SetHelpId( HID_SC_SOLVEROPTIONS_LB );
138 maLbSettings.SetHighlightRange();
140 maLbSettings.SetSelectHdl( LINK( this, ScSolverOptionsDialog, SettingsSelHdl ) );
141 maLbSettings.SetDoubleClickHdl( LINK( this, ScSolverOptionsDialog, SettingsDoubleClickHdl ) );
143 sal_Int32 nSelect = -1;
144 sal_Int32 nImplCount = maImplNames.getLength();
145 for (sal_Int32 nImpl=0; nImpl<nImplCount; ++nImpl)
147 String aImplName( maImplNames[nImpl] );
148 String aDescription( maDescriptions[nImpl] ); // user-visible descriptions in list box
149 maLbEngine.InsertEntry( aDescription );
150 if ( aImplName == maEngine )
151 nSelect = nImpl;
153 if ( nSelect < 0 ) // no (valid) engine given
155 if ( nImplCount > 0 )
157 maEngine = maImplNames[0]; // use first implementation
158 nSelect = 0;
160 else
161 maEngine.Erase();
162 maProperties.realloc(0); // don't use options from different engine
164 if ( nSelect >= 0 ) // select in list box
165 maLbEngine.SelectEntryPos( static_cast<sal_uInt16>(nSelect) );
167 if ( !maProperties.getLength() )
168 ReadFromComponent(); // fill maProperties from component (using maEngine)
169 FillListBox(); // using maProperties
171 FreeResource();
174 ScSolverOptionsDialog::~ScSolverOptionsDialog()
176 delete mpCheckButtonData;
179 const String& ScSolverOptionsDialog::GetEngine() const
181 return maEngine; // already updated in selection handler
184 const uno::Sequence<beans::PropertyValue>& ScSolverOptionsDialog::GetProperties()
186 // update maProperties from list box content
187 // order of entries in list box and maProperties is the same
188 sal_Int32 nEntryCount = maProperties.getLength();
189 SvTreeList* pModel = maLbSettings.GetModel();
190 if ( nEntryCount == (sal_Int32)pModel->GetEntryCount() )
192 for (sal_Int32 nEntryPos=0; nEntryPos<nEntryCount; ++nEntryPos)
194 uno::Any& rValue = maProperties[nEntryPos].Value;
195 SvTreeListEntry* pEntry = pModel->GetEntry(nEntryPos);
197 bool bHasData = false;
198 sal_uInt16 nItemCount = pEntry->ItemCount();
199 for (sal_uInt16 nItemPos=0; nItemPos<nItemCount && !bHasData; ++nItemPos)
201 SvLBoxItem* pItem = pEntry->GetItem( nItemPos );
202 ScSolverOptionsString* pStringItem = dynamic_cast<ScSolverOptionsString*>(pItem);
203 if ( pStringItem )
205 if ( pStringItem->IsDouble() )
206 rValue <<= pStringItem->GetDoubleValue();
207 else
208 rValue <<= pStringItem->GetIntValue();
209 bHasData = true;
212 if ( !bHasData )
213 ScUnoHelpFunctions::SetBoolInAny( rValue,
214 maLbSettings.GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED );
217 else
219 OSL_FAIL( "wrong count" );
222 return maProperties;
225 void ScSolverOptionsDialog::FillListBox()
227 // get property descriptions, sort by them
229 uno::Reference<sheet::XSolverDescription> xDesc( ScSolverUtil::GetSolver( maEngine ), uno::UNO_QUERY );
230 sal_Int32 nCount = maProperties.getLength();
231 std::vector<ScSolverOptionsEntry> aDescriptions( nCount );
232 for (sal_Int32 nPos=0; nPos<nCount; nPos++)
234 rtl::OUString aPropName( maProperties[nPos].Name );
235 rtl::OUString aVisName;
236 if ( xDesc.is() )
237 aVisName = xDesc->getPropertyDescription( aPropName );
238 if ( aVisName.isEmpty() )
239 aVisName = aPropName;
240 aDescriptions[nPos].nPosition = nPos;
241 aDescriptions[nPos].aDescription = aVisName;
243 std::sort( aDescriptions.begin(), aDescriptions.end() );
245 // also update maProperties to the order of descriptions
247 uno::Sequence<beans::PropertyValue> aNewSeq;
248 aNewSeq.realloc( nCount );
249 for (sal_Int32 nPos=0; nPos<nCount; nPos++)
250 aNewSeq[nPos] = maProperties[ aDescriptions[nPos].nPosition ];
251 maProperties = aNewSeq;
253 // fill the list box
255 maLbSettings.SetUpdateMode(false);
256 maLbSettings.Clear();
258 String sEmpty;
259 if (!mpCheckButtonData)
260 mpCheckButtonData = new SvLBoxButtonData( &maLbSettings );
262 SvTreeList* pModel = maLbSettings.GetModel();
263 SvTreeListEntry* pEntry = NULL;
265 for (sal_Int32 nPos=0; nPos<nCount; nPos++)
267 rtl::OUString aVisName = aDescriptions[nPos].aDescription;
269 uno::Any aValue = maProperties[nPos].Value;
270 uno::TypeClass eClass = aValue.getValueTypeClass();
271 if ( eClass == uno::TypeClass_BOOLEAN )
273 // check box entry
274 pEntry = new SvTreeListEntry;
275 SvLBoxButton* pButton = new SvLBoxButton( pEntry, SvLBoxButtonKind_enabledCheckbox, 0, mpCheckButtonData );
276 if ( ScUnoHelpFunctions::GetBoolFromAny( aValue ) )
277 pButton->SetStateChecked();
278 else
279 pButton->SetStateUnchecked();
280 pEntry->AddItem( pButton );
281 pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), 0 ) );
282 pEntry->AddItem( new SvLBoxString( pEntry, 0, aVisName ) );
284 else
286 // value entry
287 pEntry = new SvTreeListEntry;
288 pEntry->AddItem( new SvLBoxString( pEntry, 0, sEmpty ) ); // empty column
289 pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), 0 ) );
290 ScSolverOptionsString* pItem = new ScSolverOptionsString( pEntry, 0, aVisName );
291 if ( eClass == uno::TypeClass_DOUBLE )
293 double fDoubleValue = 0.0;
294 if ( aValue >>= fDoubleValue )
295 pItem->SetDoubleValue( fDoubleValue );
297 else
299 sal_Int32 nIntValue = 0;
300 if ( aValue >>= nIntValue )
301 pItem->SetIntValue( nIntValue );
303 pEntry->AddItem( pItem );
305 pModel->Insert( pEntry );
308 maLbSettings.SetUpdateMode(sal_True);
311 void ScSolverOptionsDialog::ReadFromComponent()
313 maProperties = ScSolverUtil::GetDefaults( maEngine );
316 void ScSolverOptionsDialog::EditOption()
318 SvTreeListEntry* pEntry = maLbSettings.GetCurEntry();
319 if (pEntry)
321 sal_uInt16 nItemCount = pEntry->ItemCount();
322 for (sal_uInt16 nPos=0; nPos<nItemCount; ++nPos)
324 SvLBoxItem* pItem = pEntry->GetItem( nPos );
325 ScSolverOptionsString* pStringItem = dynamic_cast<ScSolverOptionsString*>(pItem);
326 if ( pStringItem )
328 if ( pStringItem->IsDouble() )
330 ScSolverValueDialog aValDialog( this );
331 aValDialog.SetOptionName( pStringItem->GetText() );
332 aValDialog.SetValue( pStringItem->GetDoubleValue() );
333 if ( aValDialog.Execute() == RET_OK )
335 pStringItem->SetDoubleValue( aValDialog.GetValue() );
336 maLbSettings.InvalidateEntry( pEntry );
339 else
341 ScSolverIntegerDialog aIntDialog( this );
342 aIntDialog.SetOptionName( pStringItem->GetText() );
343 aIntDialog.SetValue( pStringItem->GetIntValue() );
344 if ( aIntDialog.Execute() == RET_OK )
346 pStringItem->SetIntValue( aIntDialog.GetValue() );
347 maLbSettings.InvalidateEntry( pEntry );
355 IMPL_LINK( ScSolverOptionsDialog, ButtonHdl, PushButton*, pBtn )
357 if ( pBtn == &maBtnEdit )
358 EditOption();
360 return 0;
363 IMPL_LINK_NOARG(ScSolverOptionsDialog, SettingsDoubleClickHdl)
365 EditOption();
366 return 0;
369 IMPL_LINK_NOARG(ScSolverOptionsDialog, EngineSelectHdl)
371 sal_uInt16 nSelectPos = maLbEngine.GetSelectEntryPos();
372 if ( nSelectPos < maImplNames.getLength() )
374 String aNewEngine( maImplNames[nSelectPos] );
375 if ( aNewEngine != maEngine )
377 maEngine = aNewEngine;
378 ReadFromComponent(); // fill maProperties from component (using maEngine)
379 FillListBox(); // using maProperties
382 return 0;
385 IMPL_LINK_NOARG(ScSolverOptionsDialog, SettingsSelHdl)
387 sal_Bool bCheckbox = false;
389 SvTreeListEntry* pEntry = maLbSettings.GetCurEntry();
390 if (pEntry)
392 SvLBoxItem* pItem = pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON);
393 if (pItem && pItem->GetType() == SV_ITEM_ID_LBOXBUTTON)
394 bCheckbox = true;
397 maBtnEdit.Enable( !bCheckbox );
399 return 0;
402 //------------------------------------------------------------------
404 ScSolverIntegerDialog::ScSolverIntegerDialog( Window * pParent )
405 : ModalDialog( pParent, ScResId( RID_SCDLG_SOLVER_INTEGER ) ),
406 maFtName ( this, ScResId( FT_OPTIONNAME ) ),
407 maNfValue ( this, ScResId( NF_VALUE ) ),
408 maFlButtons ( this, ScResId( FL_BUTTONS ) ),
409 maBtnOk ( this, ScResId( BTN_OK ) ),
410 maBtnCancel ( this, ScResId( BTN_CANCEL ) )
412 FreeResource();
415 ScSolverIntegerDialog::~ScSolverIntegerDialog()
419 void ScSolverIntegerDialog::SetOptionName( const String& rName )
421 maFtName.SetText( rName );
424 void ScSolverIntegerDialog::SetValue( sal_Int32 nValue )
426 maNfValue.SetValue( nValue );
429 sal_Int32 ScSolverIntegerDialog::GetValue() const
431 sal_Int64 nValue = maNfValue.GetValue();
432 if ( nValue < SAL_MIN_INT32 )
433 return SAL_MIN_INT32;
434 if ( nValue > SAL_MAX_INT32 )
435 return SAL_MAX_INT32;
436 return (sal_Int32) nValue;
439 //------------------------------------------------------------------
441 ScSolverValueDialog::ScSolverValueDialog( Window * pParent )
442 : ModalDialog( pParent, ScResId( RID_SCDLG_SOLVER_DOUBLE ) ),
443 maFtName ( this, ScResId( FT_OPTIONNAME ) ),
444 maEdValue ( this, ScResId( ED_VALUE ) ),
445 maFlButtons ( this, ScResId( FL_BUTTONS ) ),
446 maBtnOk ( this, ScResId( BTN_OK ) ),
447 maBtnCancel ( this, ScResId( BTN_CANCEL ) )
449 FreeResource();
452 ScSolverValueDialog::~ScSolverValueDialog()
456 void ScSolverValueDialog::SetOptionName( const String& rName )
458 maFtName.SetText( rName );
461 void ScSolverValueDialog::SetValue( double fValue )
463 maEdValue.SetText( rtl::math::doubleToUString( fValue,
464 rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
465 ScGlobal::GetpLocaleData()->getNumDecimalSep()[0], true ) );
468 double ScSolverValueDialog::GetValue() const
470 String aInput = maEdValue.GetText();
472 const LocaleDataWrapper* pLocaleData = ScGlobal::GetpLocaleData();
473 rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
474 double fValue = rtl::math::stringToDouble( aInput,
475 pLocaleData->getNumDecimalSep()[0],
476 pLocaleData->getNumThousandSep()[0],
477 &eStatus, NULL );
478 return fValue;
481 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */