update dev300-m58
[ooovba.git] / sc / source / ui / miscdlgs / solveroptions.cxx
blob37937617b8349f1f34d08740c69519ff36a1e5a8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: solveroptions.cxx,v $
10 * $Revision: 1.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 //------------------------------------------------------------------
36 #include "solveroptions.hxx"
37 #include "solveroptions.hrc"
38 #include "scresid.hxx"
39 #include "global.hxx"
40 #include "miscuno.hxx"
41 #include "solverutil.hxx"
43 #include <rtl/math.hxx>
44 #include <vcl/msgbox.hxx>
45 #include <unotools/collatorwrapper.hxx>
46 #include <unotools/localedatawrapper.hxx>
48 #include <algorithm>
50 #include <com/sun/star/sheet/Solver.hpp>
51 #include <com/sun/star/sheet/XSolverDescription.hpp>
52 #include <com/sun/star/beans/PropertyValue.hpp>
53 #include <com/sun/star/beans/XPropertySet.hpp>
55 using namespace com::sun::star;
57 //==================================================================
59 /// Helper for sorting properties
60 struct ScSolverOptionsEntry
62 sal_Int32 nPosition;
63 rtl::OUString aDescription;
65 ScSolverOptionsEntry() : nPosition(0) {}
67 bool operator< (const ScSolverOptionsEntry& rOther) const
69 return ( ScGlobal::GetCollator()->compareString( aDescription, rOther.aDescription ) == COMPARE_LESS );
73 //------------------------------------------------------------------
75 class ScSolverOptionsString : public SvLBoxString
77 bool mbIsDouble;
78 double mfDoubleValue;
79 sal_Int32 mnIntValue;
81 public:
82 ScSolverOptionsString( SvLBoxEntry* pEntry, USHORT nFlags, const String& rStr ) :
83 SvLBoxString( pEntry, nFlags, rStr ),
84 mbIsDouble( false ),
85 mfDoubleValue( 0.0 ),
86 mnIntValue( 0 ) {}
88 bool IsDouble() const { return mbIsDouble; }
89 double GetDoubleValue() const { return mfDoubleValue; }
90 sal_Int32 GetIntValue() const { return mnIntValue; }
92 void SetDoubleValue( double fNew ) { mbIsDouble = true; mfDoubleValue = fNew; }
93 void SetIntValue( sal_Int32 nNew ) { mbIsDouble = false; mnIntValue = nNew; }
95 virtual void Paint( const Point& rPos, SvLBox& rDev, USHORT nFlags, SvLBoxEntry* pEntry );
98 void ScSolverOptionsString::Paint( const Point& rPos, SvLBox& rDev, USHORT, SvLBoxEntry* /* pEntry */ )
100 //! move position? (SvxLinguTabPage: aPos.X() += 20)
101 String aNormalStr( GetText() );
102 aNormalStr.Append( (sal_Unicode) ':' );
103 rDev.DrawText( rPos, aNormalStr );
105 Point aNewPos( rPos );
106 aNewPos.X() += rDev.GetTextWidth( aNormalStr );
107 Font aOldFont( rDev.GetFont() );
108 Font aFont( aOldFont );
109 aFont.SetWeight( WEIGHT_BOLD );
111 String sTxt( ' ' );
112 if ( mbIsDouble )
113 sTxt += (String)rtl::math::doubleToUString( mfDoubleValue,
114 rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
115 ScGlobal::GetpLocaleData()->getNumDecimalSep().GetChar(0), true );
116 else
117 sTxt += String::CreateFromInt32( mnIntValue );
118 rDev.SetFont( aFont );
119 rDev.DrawText( aNewPos, sTxt );
121 rDev.SetFont( aOldFont );
124 //------------------------------------------------------------------
126 ScSolverOptionsDialog::ScSolverOptionsDialog( Window* pParent,
127 const uno::Sequence<rtl::OUString>& rImplNames,
128 const uno::Sequence<rtl::OUString>& rDescriptions,
129 const String& rEngine,
130 const uno::Sequence<beans::PropertyValue>& rProperties )
131 : ModalDialog( pParent, ScResId( RID_SCDLG_SOLVEROPTIONS ) ),
132 maFtEngine ( this, ScResId( FT_ENGINE ) ),
133 maLbEngine ( this, ScResId( LB_ENGINE ) ),
134 maFtSettings ( this, ScResId( FT_SETTINGS ) ),
135 maLbSettings ( this, ScResId( LB_SETTINGS ) ),
136 maBtnEdit ( this, ScResId( BTN_EDIT ) ),
137 maFlButtons ( this, ScResId( FL_BUTTONS ) ),
138 maBtnHelp ( this, ScResId( BTN_HELP ) ),
139 maBtnOk ( this, ScResId( BTN_OK ) ),
140 maBtnCancel ( this, ScResId( BTN_CANCEL ) ),
141 mpCheckButtonData( NULL ),
142 maImplNames( rImplNames ),
143 maDescriptions( rDescriptions ),
144 maEngine( rEngine ),
145 maProperties( rProperties )
147 maLbEngine.SetSelectHdl( LINK( this, ScSolverOptionsDialog, EngineSelectHdl ) );
149 maBtnEdit.SetClickHdl( LINK( this, ScSolverOptionsDialog, ButtonHdl ) );
151 maLbSettings.SetWindowBits( WB_CLIPCHILDREN|WB_FORCE_MAKEVISIBLE );
152 maLbSettings.SetHelpId( HID_SC_SOLVEROPTIONS_LB );
153 maLbSettings.SetHighlightRange();
155 maLbSettings.SetSelectHdl( LINK( this, ScSolverOptionsDialog, SettingsSelHdl ) );
156 maLbSettings.SetDoubleClickHdl( LINK( this, ScSolverOptionsDialog, SettingsDoubleClickHdl ) );
158 sal_Int32 nSelect = -1;
159 sal_Int32 nImplCount = maImplNames.getLength();
160 for (sal_Int32 nImpl=0; nImpl<nImplCount; ++nImpl)
162 String aImplName( maImplNames[nImpl] );
163 String aDescription( maDescriptions[nImpl] ); // user-visible descriptions in list box
164 maLbEngine.InsertEntry( aDescription );
165 if ( aImplName == maEngine )
166 nSelect = nImpl;
168 if ( nSelect < 0 ) // no (valid) engine given
170 if ( nImplCount > 0 )
172 maEngine = maImplNames[0]; // use first implementation
173 nSelect = 0;
175 else
176 maEngine.Erase();
177 maProperties.realloc(0); // don't use options from different engine
179 if ( nSelect >= 0 ) // select in list box
180 maLbEngine.SelectEntryPos( static_cast<USHORT>(nSelect) );
182 if ( !maProperties.getLength() )
183 ReadFromComponent(); // fill maProperties from component (using maEngine)
184 FillListBox(); // using maProperties
186 FreeResource();
189 ScSolverOptionsDialog::~ScSolverOptionsDialog()
191 delete mpCheckButtonData;
194 const String& ScSolverOptionsDialog::GetEngine() const
196 return maEngine; // already updated in selection handler
199 const uno::Sequence<beans::PropertyValue>& ScSolverOptionsDialog::GetProperties()
201 // update maProperties from list box content
202 // order of entries in list box and maProperties is the same
203 sal_Int32 nEntryCount = maProperties.getLength();
204 SvLBoxTreeList* pModel = maLbSettings.GetModel();
205 if ( nEntryCount == (sal_Int32)pModel->GetEntryCount() )
207 for (sal_Int32 nEntryPos=0; nEntryPos<nEntryCount; ++nEntryPos)
209 uno::Any& rValue = maProperties[nEntryPos].Value;
210 SvLBoxEntry* pEntry = pModel->GetEntry(nEntryPos);
212 bool bHasData = false;
213 USHORT nItemCount = pEntry->ItemCount();
214 for (USHORT nItemPos=0; nItemPos<nItemCount && !bHasData; ++nItemPos)
216 SvLBoxItem* pItem = pEntry->GetItem( nItemPos );
217 ScSolverOptionsString* pStringItem = dynamic_cast<ScSolverOptionsString*>(pItem);
218 if ( pStringItem )
220 if ( pStringItem->IsDouble() )
221 rValue <<= pStringItem->GetDoubleValue();
222 else
223 rValue <<= pStringItem->GetIntValue();
224 bHasData = true;
227 if ( !bHasData )
228 ScUnoHelpFunctions::SetBoolInAny( rValue,
229 maLbSettings.GetCheckButtonState( pEntry ) == SV_BUTTON_CHECKED );
232 else
234 DBG_ERRORFILE( "wrong count" );
237 return maProperties;
240 void ScSolverOptionsDialog::FillListBox()
242 // get property descriptions, sort by them
244 uno::Reference<sheet::XSolverDescription> xDesc( ScSolverUtil::GetSolver( maEngine ), uno::UNO_QUERY );
245 sal_Int32 nCount = maProperties.getLength();
246 std::vector<ScSolverOptionsEntry> aDescriptions( nCount );
247 for (sal_Int32 nPos=0; nPos<nCount; nPos++)
249 rtl::OUString aPropName( maProperties[nPos].Name );
250 rtl::OUString aVisName;
251 if ( xDesc.is() )
252 aVisName = xDesc->getPropertyDescription( aPropName );
253 if ( !aVisName.getLength() )
254 aVisName = aPropName;
255 aDescriptions[nPos].nPosition = nPos;
256 aDescriptions[nPos].aDescription = aVisName;
258 std::sort( aDescriptions.begin(), aDescriptions.end() );
260 // also update maProperties to the order of descriptions
262 uno::Sequence<beans::PropertyValue> aNewSeq;
263 aNewSeq.realloc( nCount );
264 for (sal_Int32 nPos=0; nPos<nCount; nPos++)
265 aNewSeq[nPos] = maProperties[ aDescriptions[nPos].nPosition ];
266 maProperties = aNewSeq;
268 // fill the list box
270 maLbSettings.SetUpdateMode(FALSE);
271 maLbSettings.Clear();
273 String sEmpty;
274 if (!mpCheckButtonData)
275 mpCheckButtonData = new SvLBoxButtonData( &maLbSettings );
277 SvLBoxTreeList* pModel = maLbSettings.GetModel();
278 SvLBoxEntry* pEntry = NULL;
280 for (sal_Int32 nPos=0; nPos<nCount; nPos++)
282 rtl::OUString aVisName = aDescriptions[nPos].aDescription;
284 uno::Any aValue = maProperties[nPos].Value;
285 uno::TypeClass eClass = aValue.getValueTypeClass();
286 if ( eClass == uno::TypeClass_BOOLEAN )
288 // check box entry
289 pEntry = new SvLBoxEntry;
290 SvLBoxButton* pButton = new SvLBoxButton( pEntry, SvLBoxButtonKind_enabledCheckbox, 0, mpCheckButtonData );
291 if ( ScUnoHelpFunctions::GetBoolFromAny( aValue ) )
292 pButton->SetStateChecked();
293 else
294 pButton->SetStateUnchecked();
295 pEntry->AddItem( pButton );
296 pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), 0 ) );
297 pEntry->AddItem( new SvLBoxString( pEntry, 0, aVisName ) );
299 else
301 // value entry
302 pEntry = new SvLBoxEntry;
303 pEntry->AddItem( new SvLBoxString( pEntry, 0, sEmpty ) ); // empty column
304 pEntry->AddItem( new SvLBoxContextBmp( pEntry, 0, Image(), Image(), 0 ) );
305 ScSolverOptionsString* pItem = new ScSolverOptionsString( pEntry, 0, aVisName );
306 if ( eClass == uno::TypeClass_DOUBLE )
308 double fDoubleValue = 0.0;
309 if ( aValue >>= fDoubleValue )
310 pItem->SetDoubleValue( fDoubleValue );
312 else
314 sal_Int32 nIntValue = 0;
315 if ( aValue >>= nIntValue )
316 pItem->SetIntValue( nIntValue );
318 pEntry->AddItem( pItem );
320 pModel->Insert( pEntry );
323 maLbSettings.SetUpdateMode(TRUE);
326 void ScSolverOptionsDialog::ReadFromComponent()
328 maProperties = ScSolverUtil::GetDefaults( maEngine );
331 void ScSolverOptionsDialog::EditOption()
333 SvLBoxEntry* pEntry = maLbSettings.GetCurEntry();
334 if (pEntry)
336 USHORT nItemCount = pEntry->ItemCount();
337 for (USHORT nPos=0; nPos<nItemCount; ++nPos)
339 SvLBoxItem* pItem = pEntry->GetItem( nPos );
340 ScSolverOptionsString* pStringItem = dynamic_cast<ScSolverOptionsString*>(pItem);
341 if ( pStringItem )
343 if ( pStringItem->IsDouble() )
345 ScSolverValueDialog aValDialog( this );
346 aValDialog.SetOptionName( pStringItem->GetText() );
347 aValDialog.SetValue( pStringItem->GetDoubleValue() );
348 if ( aValDialog.Execute() == RET_OK )
350 pStringItem->SetDoubleValue( aValDialog.GetValue() );
351 maLbSettings.InvalidateEntry( pEntry );
354 else
356 ScSolverIntegerDialog aIntDialog( this );
357 aIntDialog.SetOptionName( pStringItem->GetText() );
358 aIntDialog.SetValue( pStringItem->GetIntValue() );
359 if ( aIntDialog.Execute() == RET_OK )
361 pStringItem->SetIntValue( aIntDialog.GetValue() );
362 maLbSettings.InvalidateEntry( pEntry );
370 IMPL_LINK( ScSolverOptionsDialog, ButtonHdl, PushButton*, pBtn )
372 if ( pBtn == &maBtnEdit )
373 EditOption();
375 return 0;
378 IMPL_LINK( ScSolverOptionsDialog, SettingsDoubleClickHdl, SvTreeListBox*, EMPTYARG )
380 EditOption();
381 return 0;
384 IMPL_LINK( ScSolverOptionsDialog, EngineSelectHdl, ListBox*, EMPTYARG )
386 USHORT nSelectPos = maLbEngine.GetSelectEntryPos();
387 if ( nSelectPos < maImplNames.getLength() )
389 String aNewEngine( maImplNames[nSelectPos] );
390 if ( aNewEngine != maEngine )
392 maEngine = aNewEngine;
393 ReadFromComponent(); // fill maProperties from component (using maEngine)
394 FillListBox(); // using maProperties
397 return 0;
400 IMPL_LINK( ScSolverOptionsDialog, SettingsSelHdl, SvxCheckListBox*, EMPTYARG )
402 BOOL bCheckbox = FALSE;
404 SvLBoxEntry* pEntry = maLbSettings.GetCurEntry();
405 if (pEntry)
407 SvLBoxItem* pItem = pEntry->GetFirstItem(SV_ITEM_ID_LBOXBUTTON);
408 if ( pItem && pItem->IsA() == SV_ITEM_ID_LBOXBUTTON )
409 bCheckbox = TRUE;
412 maBtnEdit.Enable( !bCheckbox );
414 return 0;
417 //------------------------------------------------------------------
419 ScSolverIntegerDialog::ScSolverIntegerDialog( Window * pParent )
420 : ModalDialog( pParent, ScResId( RID_SCDLG_SOLVER_INTEGER ) ),
421 maFtName ( this, ScResId( FT_OPTIONNAME ) ),
422 maNfValue ( this, ScResId( NF_VALUE ) ),
423 maFlButtons ( this, ScResId( FL_BUTTONS ) ),
424 maBtnOk ( this, ScResId( BTN_OK ) ),
425 maBtnCancel ( this, ScResId( BTN_CANCEL ) )
427 FreeResource();
430 ScSolverIntegerDialog::~ScSolverIntegerDialog()
434 void ScSolverIntegerDialog::SetOptionName( const String& rName )
436 maFtName.SetText( rName );
439 void ScSolverIntegerDialog::SetValue( sal_Int32 nValue )
441 maNfValue.SetValue( nValue );
444 sal_Int32 ScSolverIntegerDialog::GetValue() const
446 sal_Int64 nValue = maNfValue.GetValue();
447 if ( nValue < SAL_MIN_INT32 )
448 return SAL_MIN_INT32;
449 if ( nValue > SAL_MAX_INT32 )
450 return SAL_MAX_INT32;
451 return (sal_Int32) nValue;
454 //------------------------------------------------------------------
456 ScSolverValueDialog::ScSolverValueDialog( Window * pParent )
457 : ModalDialog( pParent, ScResId( RID_SCDLG_SOLVER_DOUBLE ) ),
458 maFtName ( this, ScResId( FT_OPTIONNAME ) ),
459 maEdValue ( this, ScResId( ED_VALUE ) ),
460 maFlButtons ( this, ScResId( FL_BUTTONS ) ),
461 maBtnOk ( this, ScResId( BTN_OK ) ),
462 maBtnCancel ( this, ScResId( BTN_CANCEL ) )
464 FreeResource();
467 ScSolverValueDialog::~ScSolverValueDialog()
471 void ScSolverValueDialog::SetOptionName( const String& rName )
473 maFtName.SetText( rName );
476 void ScSolverValueDialog::SetValue( double fValue )
478 maEdValue.SetText( rtl::math::doubleToUString( fValue,
479 rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
480 ScGlobal::GetpLocaleData()->getNumDecimalSep().GetChar(0), true ) );
483 double ScSolverValueDialog::GetValue() const
485 String aInput = maEdValue.GetText();
487 const LocaleDataWrapper* pLocaleData = ScGlobal::GetpLocaleData();
488 rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
489 double fValue = rtl::math::stringToDouble( aInput,
490 pLocaleData->getNumDecimalSep().GetChar(0),
491 pLocaleData->getNumThousandSep().GetChar(0),
492 &eStatus, NULL );
493 return fValue;