1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: solveroptions.cxx,v $
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"
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>
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
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
82 ScSolverOptionsString( SvLBoxEntry
* pEntry
, USHORT nFlags
, const String
& rStr
) :
83 SvLBoxString( pEntry
, nFlags
, rStr
),
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
);
113 sTxt
+= (String
)rtl::math::doubleToUString( mfDoubleValue
,
114 rtl_math_StringFormat_Automatic
, rtl_math_DecimalPlaces_Max
,
115 ScGlobal::GetpLocaleData()->getNumDecimalSep().GetChar(0), true );
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
),
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
)
168 if ( nSelect
< 0 ) // no (valid) engine given
170 if ( nImplCount
> 0 )
172 maEngine
= maImplNames
[0]; // use first implementation
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
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
);
220 if ( pStringItem
->IsDouble() )
221 rValue
<<= pStringItem
->GetDoubleValue();
223 rValue
<<= pStringItem
->GetIntValue();
228 ScUnoHelpFunctions::SetBoolInAny( rValue
,
229 maLbSettings
.GetCheckButtonState( pEntry
) == SV_BUTTON_CHECKED
);
234 DBG_ERRORFILE( "wrong count" );
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
;
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
;
270 maLbSettings
.SetUpdateMode(FALSE
);
271 maLbSettings
.Clear();
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
)
289 pEntry
= new SvLBoxEntry
;
290 SvLBoxButton
* pButton
= new SvLBoxButton( pEntry
, SvLBoxButtonKind_enabledCheckbox
, 0, mpCheckButtonData
);
291 if ( ScUnoHelpFunctions::GetBoolFromAny( aValue
) )
292 pButton
->SetStateChecked();
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
) );
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
);
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();
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
);
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
);
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
)
378 IMPL_LINK( ScSolverOptionsDialog
, SettingsDoubleClickHdl
, SvTreeListBox
*, EMPTYARG
)
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
400 IMPL_LINK( ScSolverOptionsDialog
, SettingsSelHdl
, SvxCheckListBox
*, EMPTYARG
)
402 BOOL bCheckbox
= FALSE
;
404 SvLBoxEntry
* pEntry
= maLbSettings
.GetCurEntry();
407 SvLBoxItem
* pItem
= pEntry
->GetFirstItem(SV_ITEM_ID_LBOXBUTTON
);
408 if ( pItem
&& pItem
->IsA() == SV_ITEM_ID_LBOXBUTTON
)
412 maBtnEdit
.Enable( !bCheckbox
);
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
) )
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
) )
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),