1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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"
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
48 OUString aDescription
;
50 ScSolverOptionsEntry() : nPosition(0) {}
52 bool operator< (const ScSolverOptionsEntry
& rOther
) const
54 return (ScGlobal::GetCollator()->compareString( aDescription
, rOther
.aDescription
) < 0);
58 //------------------------------------------------------------------
60 class ScSolverOptionsString
: public SvLBoxString
67 ScSolverOptionsString( SvTreeListEntry
* pEntry
, sal_uInt16 nFlags
, const OUString
& rStr
) :
68 SvLBoxString( pEntry
, nFlags
, rStr
),
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 OUString
aNormalStr( GetText() );
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
);
98 sTxt
+= rtl::math::doubleToUString( mfDoubleValue
,
99 rtl_math_StringFormat_Automatic
, rtl_math_DecimalPlaces_Max
,
100 ScGlobal::GetpLocaleData()->getNumDecimalSep()[0], true );
102 sTxt
+= OUString::number(mnIntValue
);
103 rDev
.SetFont( aFont
);
104 rDev
.DrawText( aNewPos
, sTxt
);
106 rDev
.SetFont( aOldFont
);
109 //------------------------------------------------------------------
111 ScSolverOptionsDialog::ScSolverOptionsDialog( Window
* pParent
,
112 const uno::Sequence
<OUString
>& rImplNames
,
113 const uno::Sequence
<OUString
>& rDescriptions
,
114 const OUString
& 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
),
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 OUString
aImplName( maImplNames
[nImpl
] );
148 OUString
aDescription( maDescriptions
[nImpl
] ); // user-visible descriptions in list box
149 maLbEngine
.InsertEntry( aDescription
);
150 if ( aImplName
== maEngine
)
153 if ( nSelect
< 0 ) // no (valid) engine given
155 if ( nImplCount
> 0 )
157 maEngine
= maImplNames
[0]; // use first implementation
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
174 ScSolverOptionsDialog::~ScSolverOptionsDialog()
176 delete mpCheckButtonData
;
179 const OUString
& 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
);
205 if ( pStringItem
->IsDouble() )
206 rValue
<<= pStringItem
->GetDoubleValue();
208 rValue
<<= pStringItem
->GetIntValue();
213 ScUnoHelpFunctions::SetBoolInAny( rValue
,
214 maLbSettings
.GetCheckButtonState( pEntry
) == SV_BUTTON_CHECKED
);
219 OSL_FAIL( "wrong count" );
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 OUString
aPropName( maProperties
[nPos
].Name
);
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
;
255 maLbSettings
.SetUpdateMode(false);
256 maLbSettings
.Clear();
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 OUString aVisName
= aDescriptions
[nPos
].aDescription
;
269 uno::Any aValue
= maProperties
[nPos
].Value
;
270 uno::TypeClass eClass
= aValue
.getValueTypeClass();
271 if ( eClass
== uno::TypeClass_BOOLEAN
)
274 pEntry
= new SvTreeListEntry
;
275 SvLBoxButton
* pButton
= new SvLBoxButton( pEntry
, SvLBoxButtonKind_enabledCheckbox
, 0, mpCheckButtonData
);
276 if ( ScUnoHelpFunctions::GetBoolFromAny( aValue
) )
277 pButton
->SetStateChecked();
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
) );
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
);
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();
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
);
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
);
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
)
363 IMPL_LINK_NOARG(ScSolverOptionsDialog
, SettingsDoubleClickHdl
)
369 IMPL_LINK_NOARG(ScSolverOptionsDialog
, EngineSelectHdl
)
371 sal_uInt16 nSelectPos
= maLbEngine
.GetSelectEntryPos();
372 if ( nSelectPos
< maImplNames
.getLength() )
374 OUString
aNewEngine( maImplNames
[nSelectPos
] );
375 if ( aNewEngine
!= maEngine
)
377 maEngine
= aNewEngine
;
378 ReadFromComponent(); // fill maProperties from component (using maEngine)
379 FillListBox(); // using maProperties
385 IMPL_LINK_NOARG(ScSolverOptionsDialog
, SettingsSelHdl
)
387 sal_Bool bCheckbox
= false;
389 SvTreeListEntry
* pEntry
= maLbSettings
.GetCurEntry();
392 SvLBoxItem
* pItem
= pEntry
->GetFirstItem(SV_ITEM_ID_LBOXBUTTON
);
393 if (pItem
&& pItem
->GetType() == SV_ITEM_ID_LBOXBUTTON
)
397 maBtnEdit
.Enable( !bCheckbox
);
402 //------------------------------------------------------------------
404 ScSolverIntegerDialog::ScSolverIntegerDialog(Window
* pParent
)
405 : ModalDialog( pParent
, "IntegerDialog",
406 "modules/scalc/ui/integerdialog.ui" )
408 get(m_pFrame
, "frame");
409 get(m_pNfValue
, "value");
412 void ScSolverIntegerDialog::SetOptionName( const OUString
& rName
)
414 m_pFrame
->set_label(rName
);
417 void ScSolverIntegerDialog::SetValue( sal_Int32 nValue
)
419 m_pNfValue
->SetValue( nValue
);
422 sal_Int32
ScSolverIntegerDialog::GetValue() const
424 sal_Int64 nValue
= m_pNfValue
->GetValue();
425 if ( nValue
< SAL_MIN_INT32
)
426 return SAL_MIN_INT32
;
427 if ( nValue
> SAL_MAX_INT32
)
428 return SAL_MAX_INT32
;
429 return (sal_Int32
) nValue
;
432 //------------------------------------------------------------------
434 ScSolverValueDialog::ScSolverValueDialog( Window
* pParent
)
435 : ModalDialog( pParent
, "DoubleDialog",
436 "modules/scalc/ui/doubledialog.ui" )
438 get(m_pFrame
, "frame");
439 get(m_pEdValue
, "value");
442 void ScSolverValueDialog::SetOptionName( const OUString
& rName
)
444 m_pFrame
->set_label(rName
);
447 void ScSolverValueDialog::SetValue( double fValue
)
449 m_pEdValue
->SetText( rtl::math::doubleToUString( fValue
,
450 rtl_math_StringFormat_Automatic
, rtl_math_DecimalPlaces_Max
,
451 ScGlobal::GetpLocaleData()->getNumDecimalSep()[0], true ) );
454 double ScSolverValueDialog::GetValue() const
456 OUString aInput
= m_pEdValue
->GetText();
458 const LocaleDataWrapper
* pLocaleData
= ScGlobal::GetpLocaleData();
459 rtl_math_ConversionStatus eStatus
= rtl_math_ConversionStatus_Ok
;
460 double fValue
= rtl::math::stringToDouble( aInput
,
461 pLocaleData
->getNumDecimalSep()[0],
462 pLocaleData
->getNumThousandSep()[0],
467 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */