1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_chart2.hxx"
30 
31 #include "res_ErrorBar.hxx"
32 #include "res_ErrorBar_IDs.hrc"
33 #include "ResId.hxx"
34 #include "Strings.hrc"
35 #include "Bitmaps.hrc"
36 #include "Bitmaps_HC.hrc"
37 #include "RangeSelectionHelper.hxx"
38 // for RANGE_SELECTION_INVALID_RANGE_BACKGROUND_COLOR
39 #include "TabPageNotifiable.hxx"
40 #include "macros.hxx"
41 
42 #include <rtl/math.hxx>
43 #include <vcl/dialog.hxx>
44 #include <svl/stritem.hxx>
45 
46 using namespace ::com::sun::star;
47 
48 namespace
49 {
50 void lcl_enableRangeChoosing( bool bEnable, Dialog * pDialog )
51 {
52     if( pDialog )
53     {
54         pDialog->Show( bEnable ? sal_False : sal_True );
55         pDialog->SetModalInputMode( bEnable ? sal_False : sal_True );
56     }
57 }
58 
59 sal_uInt16 lcl_getLbEntryPosByErrorKind( SvxChartKindError eErrorKind )
60 {
61     sal_uInt16 nResult = 0;
62     switch( eErrorKind )
63     {
64         // for these cases select the default in the list box
65         case CHERROR_NONE:
66         case CHERROR_PERCENT:
67         case CHERROR_CONST:
68         case CHERROR_RANGE:
69             nResult = CHART_LB_FUNCTION_STD_DEV;
70             break;
71         case CHERROR_VARIANT:
72             nResult = CHART_LB_FUNCTION_VARIANCE;
73             break;
74         case CHERROR_SIGMA:
75             nResult = CHART_LB_FUNCTION_STD_DEV;
76             break;
77         case CHERROR_BIGERROR:
78             nResult = CHART_LB_FUNCTION_ERROR_MARGIN;
79             break;
80         case CHERROR_STDERROR:
81             nResult = CHART_LB_FUNCTION_STD_ERROR;
82             break;
83     }
84     return nResult;
85 }
86 } // anonymous namespace
87 
88 
89 //.............................................................................
90 namespace chart
91 {
92 //.............................................................................
93 
94 // macro for selecting a normal or high contrast bitmap the stack variable
95 // bIsHighContrast must exist and reflect the correct state
96 #define SELECT_IMAGE(name) Image( SchResId( bIsHighContrast ? name ## _HC : name ))
97 
98 enum StatIndicator
99 {
100     INDICATE_BOTH,
101     INDICATE_UP,
102     INDICATE_DOWN
103 };
104 
105 ErrorBarResources::ErrorBarResources( Window* pParent, Dialog * pParentDialog,
106                                       const SfxItemSet& rInAttrs, bool bNoneAvailable,
107                                       tErrorBarType eType /* = ERROR_BAR_Y */ ) :
108 
109         m_aFlErrorCategory( pParent, SchResId( FL_ERROR )),
110         m_aRbNone( pParent, SchResId( RB_NONE )),
111         m_aRbConst( pParent, SchResId( RB_CONST )),
112         m_aRbPercent( pParent, SchResId( RB_PERCENT )),
113         m_aRbFunction( pParent, SchResId( RB_FUNCTION )),
114         m_aRbRange( pParent, SchResId( RB_RANGE )),
115         m_aLbFunction( pParent, SchResId( LB_FUNCTION )),
116 
117         m_aFlParameters( pParent, SchResId( FL_PARAMETERS )),
118         m_aFtPositive( pParent, SchResId( FT_POSITIVE )),
119         m_aMfPositive( pParent, SchResId( MF_POSITIVE )),
120         m_aEdRangePositive( pParent, SchResId( ED_RANGE_POSITIVE )),
121         m_aIbRangePositive( pParent, SchResId( IB_RANGE_POSITIVE )),
122         m_aFtNegative( pParent, SchResId( FT_NEGATIVE )),
123         m_aMfNegative( pParent, SchResId( MF_NEGATIVE )),
124         m_aEdRangeNegative( pParent, SchResId( ED_RANGE_NEGATIVE )),
125         m_aIbRangeNegative( pParent, SchResId( IB_RANGE_NEGATIVE )),
126         m_aCbSyncPosNeg( pParent, SchResId( CB_SYN_POS_NEG )),
127 
128         m_aFlIndicate( pParent, SchResId( FL_INDICATE )),
129         m_aRbBoth( pParent, SchResId( RB_BOTH )),
130         m_aRbPositive( pParent, SchResId( RB_POSITIVE )),
131         m_aRbNegative( pParent, SchResId( RB_NEGATIVE )),
132         m_aFiBoth( pParent, SchResId( FI_BOTH )),
133         m_aFiPositive( pParent, SchResId( FI_POSITIVE )),
134         m_aFiNegative( pParent, SchResId( FI_NEGATIVE )),
135 
136         m_eErrorKind( CHERROR_NONE ),
137         m_eIndicate( CHINDICATE_BOTH ),
138         m_bErrorKindUnique( true ),
139         m_bIndicatorUnique( true ),
140         m_bPlusUnique( true ),
141         m_bMinusUnique( true ),
142         m_bRangePosUnique( true ),
143         m_bRangeNegUnique( true ),
144         m_bNoneAvailable( bNoneAvailable ),
145         m_eErrorBarType( eType ),
146         m_nConstDecimalDigits( 1 ),
147         m_nConstSpinSize( 1 ),
148         m_pParentWindow( pParent ),
149         m_pParentDialog( pParentDialog ),
150         m_pCurrentRangeChoosingField( 0 ),
151         m_bHasInternalDataProvider( true ),
152         m_bDisableDataTableDialog( false )
153 {
154     if( m_bNoneAvailable )
155         m_aRbNone.SetClickHdl( LINK( this, ErrorBarResources, CategoryChosen ));
156     else
157         m_aRbNone.Hide();
158 
159     m_aRbConst.SetClickHdl( LINK( this, ErrorBarResources, CategoryChosen ));
160     m_aRbPercent.SetClickHdl( LINK( this, ErrorBarResources, CategoryChosen ));
161     m_aRbFunction.SetClickHdl( LINK( this, ErrorBarResources, CategoryChosen ));
162     m_aRbRange.SetClickHdl( LINK( this, ErrorBarResources, CategoryChosen ));
163     m_aLbFunction.SetSelectHdl( LINK( this, ErrorBarResources, CategoryChosen ));
164 
165     m_aCbSyncPosNeg.Check( sal_False );
166     m_aCbSyncPosNeg.SetToggleHdl( LINK( this, ErrorBarResources, SynchronizePosAndNeg ));
167 
168     m_aMfPositive.SetModifyHdl( LINK( this, ErrorBarResources, PosValueChanged ));
169     m_aEdRangePositive.SetModifyHdl( LINK( this, ErrorBarResources, RangeChanged ));
170     m_aEdRangeNegative.SetModifyHdl( LINK( this, ErrorBarResources, RangeChanged ));
171 
172     m_aRbPositive.SetClickHdl( LINK( this, ErrorBarResources, IndicatorChanged ));
173     m_aRbNegative.SetClickHdl( LINK( this, ErrorBarResources, IndicatorChanged ));
174     m_aRbBoth.SetClickHdl( LINK( this, ErrorBarResources, IndicatorChanged ));
175 
176     m_aIbRangePositive.SetClickHdl( LINK( this, ErrorBarResources, ChooseRange ));
177     m_aIbRangeNegative.SetClickHdl( LINK( this, ErrorBarResources, ChooseRange ));
178     m_aIbRangePositive.SetQuickHelpText( String( SchResId( STR_TIP_SELECT_RANGE )));
179     m_aIbRangeNegative.SetQuickHelpText( String( SchResId( STR_TIP_SELECT_RANGE )));
180 
181     FillValueSets();
182     Reset( rInAttrs );
183 }
184 
185 ErrorBarResources::~ErrorBarResources()
186 {
187 }
188 
189 void ErrorBarResources::SetErrorBarType( tErrorBarType eNewType )
190 {
191     if( m_eErrorBarType != eNewType )
192     {
193         m_eErrorBarType = eNewType;
194         FillValueSets();
195     }
196 }
197 
198 void ErrorBarResources::SetChartDocumentForRangeChoosing(
199     const uno::Reference< chart2::XChartDocument > & xChartDocument )
200 {
201     if( xChartDocument.is())
202     {
203         m_bHasInternalDataProvider = xChartDocument->hasInternalDataProvider();
204         uno::Reference< beans::XPropertySet > xProps( xChartDocument, uno::UNO_QUERY );
205         if ( xProps.is() )
206         {
207             try
208             {
209                 xProps->getPropertyValue( C2U( "DisableDataTableDialog" ) ) >>= m_bDisableDataTableDialog;
210             }
211             catch( uno::Exception& e )
212             {
213                 ASSERT_EXCEPTION( e );
214             }
215         }
216     }
217     m_apRangeSelectionHelper.reset( new RangeSelectionHelper( xChartDocument ));
218 
219     // has internal data provider => rename "cell range" to "from data"
220     OSL_ASSERT( m_apRangeSelectionHelper.get());
221     if( m_bHasInternalDataProvider )
222     {
223         m_aRbRange.SetText( String( SchResId( STR_CONTROLTEXT_ERROR_BARS_FROM_DATA )));
224     }
225 
226     if( m_aRbRange.IsChecked())
227     {
228         isRangeFieldContentValid( m_aEdRangePositive );
229         isRangeFieldContentValid( m_aEdRangeNegative );
230     }
231 }
232 
233 void ErrorBarResources::SetAxisMinorStepWidthForErrorBarDecimals( double fMinorStepWidth )
234 {
235     if( fMinorStepWidth < 0 )
236         fMinorStepWidth = -fMinorStepWidth;
237 
238     sal_Int32 nExponent = static_cast< sal_Int32 >( ::rtl::math::approxFloor( log10( fMinorStepWidth )));
239     if( nExponent <= 0 )
240     {
241         // one digit precision more
242         m_nConstDecimalDigits = static_cast< sal_uInt16 >( (-nExponent) + 1 );
243         m_nConstSpinSize = 10;
244     }
245     else
246     {
247         m_nConstDecimalDigits = 0;
248         m_nConstSpinSize = static_cast< sal_Int64 >( pow( 10.0, (int)nExponent ));
249     }
250 }
251 
252 void ErrorBarResources::UpdateControlStates()
253 {
254     // function
255     bool bIsFunction = m_aRbFunction.IsChecked();
256     m_aLbFunction.Enable( bIsFunction );
257 
258     // range buttons
259     m_aRbRange.Enable( !m_bHasInternalDataProvider || !m_bDisableDataTableDialog );
260     bool bShowRange = ( m_aRbRange.IsChecked());
261     bool bCanChooseRange =
262         ( bShowRange &&
263           m_apRangeSelectionHelper.get() &&
264           m_apRangeSelectionHelper->hasRangeSelection());
265 
266     m_aMfPositive.Show( ! bShowRange );
267     m_aMfNegative.Show( ! bShowRange );
268 
269     // use range but without range chooser => hide controls
270     m_aEdRangePositive.Show( bShowRange && ! m_bHasInternalDataProvider );
271     m_aIbRangePositive.Show( bCanChooseRange );
272     m_aEdRangeNegative.Show( bShowRange && ! m_bHasInternalDataProvider );
273     m_aIbRangeNegative.Show( bCanChooseRange );
274 
275     bool bShowPosNegAndSync = ! (bShowRange && m_bHasInternalDataProvider);
276     m_aFtPositive.Show( bShowPosNegAndSync );
277     m_aFtNegative.Show( bShowPosNegAndSync );
278     m_aCbSyncPosNeg.Show( bShowPosNegAndSync );
279     m_aFlParameters.Show( bShowPosNegAndSync );
280 
281     // unit for metric fields
282     bool bIsErrorMargin(
283         ( m_aRbFunction.IsChecked()) &&
284         ( m_aLbFunction.GetSelectEntryPos() == CHART_LB_FUNCTION_ERROR_MARGIN ));
285     bool bIsPercentage( m_aRbPercent.IsChecked() || bIsErrorMargin );
286     String aCustomUnit;
287 
288     if( bIsPercentage )
289     {
290         aCustomUnit = String( RTL_CONSTASCII_USTRINGPARAM( " %" ));
291         m_aMfPositive.SetDecimalDigits( 1 );
292         m_aMfPositive.SetSpinSize( 10 );
293         m_aMfNegative.SetDecimalDigits( 1 );
294         m_aMfNegative.SetSpinSize( 10 );
295     }
296     else
297     {
298         m_aMfPositive.SetDecimalDigits( m_nConstDecimalDigits );
299         m_aMfPositive.SetSpinSize( m_nConstSpinSize );
300         m_aMfNegative.SetDecimalDigits( m_nConstDecimalDigits );
301         m_aMfNegative.SetSpinSize( m_nConstSpinSize );
302     }
303     m_aMfPositive.SetCustomUnitText( aCustomUnit );
304     m_aMfNegative.SetCustomUnitText( aCustomUnit );
305 
306     // positive and negative value fields
307     bool bPosEnabled = ( m_aRbPositive.IsChecked() || m_aRbBoth.IsChecked());
308     bool bNegEnabled = ( m_aRbNegative.IsChecked() || m_aRbBoth.IsChecked());
309     if( !( bPosEnabled || bNegEnabled ))
310     {
311         // all three controls are not checked -> ambiguous state
312         bPosEnabled = true;
313         bNegEnabled = true;
314     }
315 
316     // functions with only one parameter
317     bool bOneParameterCategory =
318         bIsErrorMargin || m_aRbPercent.IsChecked();
319     if( bOneParameterCategory )
320     {
321         m_aCbSyncPosNeg.Check();
322     }
323 
324     if( m_aCbSyncPosNeg.IsChecked())
325     {
326         bPosEnabled = true;
327         bNegEnabled = false;
328     }
329 
330     // all functions except error margin take no arguments
331     if( m_aRbFunction.IsChecked() &&
332         ( m_aLbFunction.GetSelectEntryPos() != CHART_LB_FUNCTION_ERROR_MARGIN ))
333     {
334         bPosEnabled = false;
335         bNegEnabled = false;
336     }
337 
338     // enable/disable pos/neg fields
339     m_aFtPositive.Enable( bPosEnabled );
340     m_aFtNegative.Enable( bNegEnabled );
341     if( bShowRange )
342     {
343         m_aEdRangePositive.Enable( bPosEnabled );
344         m_aIbRangePositive.Enable( bPosEnabled );
345         m_aEdRangeNegative.Enable( bNegEnabled );
346         m_aIbRangeNegative.Enable( bNegEnabled );
347     }
348     else
349     {
350         m_aMfPositive.Enable( bPosEnabled );
351         m_aMfNegative.Enable( bNegEnabled );
352     }
353 
354     m_aCbSyncPosNeg.Enable(
355         !bOneParameterCategory &&
356         ( bPosEnabled || bNegEnabled ));
357 
358     // mark invalid entries in the range fields
359     if( bShowRange && ! m_bHasInternalDataProvider )
360     {
361         isRangeFieldContentValid( m_aEdRangePositive );
362         isRangeFieldContentValid( m_aEdRangeNegative );
363     }
364 }
365 
366 IMPL_LINK( ErrorBarResources, CategoryChosen, void *,  )
367 {
368     m_bErrorKindUnique = true;
369     SvxChartKindError eOldError = m_eErrorKind;
370 
371     if( m_aRbNone.IsChecked())
372         m_eErrorKind = CHERROR_NONE;
373     else if( m_aRbConst.IsChecked())
374         m_eErrorKind = CHERROR_CONST;
375     else if( m_aRbPercent.IsChecked())
376         m_eErrorKind = CHERROR_PERCENT;
377     else if( m_aRbRange.IsChecked())
378         m_eErrorKind = CHERROR_RANGE;
379     else if( m_aRbFunction.IsChecked())
380     {
381         if( m_aLbFunction.GetSelectEntryCount() == 1 )
382         {
383             switch( m_aLbFunction.GetSelectEntryPos())
384             {
385                 case CHART_LB_FUNCTION_STD_ERROR:
386                     m_eErrorKind = CHERROR_STDERROR; break;
387                 case CHART_LB_FUNCTION_STD_DEV:
388                     m_eErrorKind = CHERROR_SIGMA; break;
389                 case CHART_LB_FUNCTION_VARIANCE:
390                     m_eErrorKind = CHERROR_VARIANT; break;
391                 case CHART_LB_FUNCTION_ERROR_MARGIN:
392                     m_eErrorKind = CHERROR_BIGERROR; break;
393                 default:
394                     m_bErrorKindUnique = false;
395             }
396         }
397         else
398             m_bErrorKindUnique = false;
399     }
400     else
401     {
402         OSL_ENSURE( false, "Unknown category chosen" );
403         m_bErrorKindUnique = false;
404     }
405 
406     // changed to range
407     if( m_eErrorKind == CHERROR_RANGE &&
408         eOldError != CHERROR_RANGE )
409     {
410         m_aCbSyncPosNeg.Check(
411             (m_aEdRangePositive.GetText().Len() > 0) &&
412             m_aEdRangePositive.GetText().Equals(
413                 m_aEdRangeNegative.GetText()));
414     }
415     // changed from range
416     else if( m_eErrorKind != CHERROR_RANGE &&
417         eOldError == CHERROR_RANGE )
418     {
419         m_aCbSyncPosNeg.Check(
420             m_aMfPositive.GetValue() == m_aMfNegative.GetValue());
421     }
422 
423     UpdateControlStates();
424     return 0;
425 }
426 
427 IMPL_LINK( ErrorBarResources, SynchronizePosAndNeg, void *, EMPTYARG )
428 {
429     UpdateControlStates();
430     PosValueChanged( 0 );
431     return 0;
432 }
433 
434 IMPL_LINK( ErrorBarResources, PosValueChanged, void *, EMPTYARG )
435 {
436     if( m_aCbSyncPosNeg.IsChecked())
437     {
438         if( m_aRbRange.IsChecked())
439         {
440             m_aEdRangeNegative.SetText( m_aEdRangePositive.GetText());
441             m_bRangeNegUnique = m_bRangePosUnique;
442         }
443         else
444             m_aMfNegative.SetValue( m_aMfPositive.GetValue());
445     }
446 
447     return 0;
448 }
449 
450 IMPL_LINK( ErrorBarResources, IndicatorChanged, void *, EMPTYARG )
451 {
452     m_bIndicatorUnique = true;
453     if( m_aRbBoth.IsChecked())
454         m_eIndicate = CHINDICATE_BOTH;
455     else if( m_aRbPositive.IsChecked())
456         m_eIndicate = CHINDICATE_UP;
457     else if( m_aRbNegative.IsChecked())
458         m_eIndicate = CHINDICATE_DOWN;
459     else
460         m_bIndicatorUnique = false;
461 
462     UpdateControlStates();
463     return 0;
464 }
465 
466 IMPL_LINK( ErrorBarResources, ChooseRange, RangeSelectionButton *, pButton )
467 {
468     OSL_ASSERT( m_apRangeSelectionHelper.get());
469     if( ! m_apRangeSelectionHelper.get())
470         return 0;
471     OSL_ASSERT( m_pCurrentRangeChoosingField == 0 );
472 
473     ::rtl::OUString aUIString;
474     if( pButton == &m_aIbRangePositive )
475     {
476         m_pCurrentRangeChoosingField = &m_aEdRangePositive;
477         aUIString = String( SchResId( STR_DATA_SELECT_RANGE_FOR_POSITIVE_ERRORBARS ));
478     }
479     else
480     {
481         m_pCurrentRangeChoosingField = &m_aEdRangeNegative;
482         aUIString = String( SchResId( STR_DATA_SELECT_RANGE_FOR_NEGATIVE_ERRORBARS ));
483     }
484 
485     OSL_ASSERT( m_pParentDialog );
486     if( m_pParentDialog )
487     {
488         lcl_enableRangeChoosing( true, m_pParentDialog );
489         m_apRangeSelectionHelper->chooseRange(
490             m_pCurrentRangeChoosingField->GetText(),
491             aUIString, *this );
492     }
493     else
494         m_pCurrentRangeChoosingField = 0;
495 
496     return 0;
497 }
498 
499 IMPL_LINK( ErrorBarResources, RangeChanged, Edit *, pEdit )
500 {
501     if( pEdit == & m_aEdRangePositive )
502     {
503         m_bRangePosUnique = true;
504         PosValueChanged( 0 );
505     }
506     else
507     {
508         m_bRangeNegUnique = true;
509     }
510 
511     isRangeFieldContentValid( *pEdit );
512 
513     return 0;
514 }
515 
516 void ErrorBarResources::Reset(const SfxItemSet& rInAttrs)
517 {
518 	const SfxPoolItem *pPoolItem = NULL;
519     SfxItemState aState = SFX_ITEM_UNKNOWN;
520 
521     // category
522  	m_eErrorKind = CHERROR_NONE;
523     aState = rInAttrs.GetItemState( SCHATTR_STAT_KIND_ERROR, sal_True, &pPoolItem );
524     m_bErrorKindUnique = ( aState != SFX_ITEM_DONTCARE );
525 
526     if( aState == SFX_ITEM_SET )
527         m_eErrorKind = ((const SvxChartKindErrorItem*) pPoolItem)->GetValue();
528 
529     m_aLbFunction.SelectEntryPos( lcl_getLbEntryPosByErrorKind( m_eErrorKind ));
530 
531     if( m_bErrorKindUnique )
532     {
533         switch( m_eErrorKind )
534         {
535             case CHERROR_NONE:
536                 m_aRbNone.Check();
537                 break;
538             case CHERROR_PERCENT:
539                 m_aRbPercent.Check();
540                 break;
541             case CHERROR_CONST:
542                 m_aRbConst.Check();
543                 break;
544             case CHERROR_STDERROR:
545             case CHERROR_VARIANT:
546             case CHERROR_SIGMA:
547             case CHERROR_BIGERROR:
548                 m_aRbFunction.Check();
549                 break;
550             case CHERROR_RANGE:
551                 m_aRbRange.Check();
552                 break;
553         }
554     }
555     else
556     {
557         m_aRbNone.Check( sal_False );
558         m_aRbConst.Check( sal_False );
559         m_aRbPercent.Check( sal_False );
560         m_aRbFunction.Check( sal_False );
561     }
562 
563     // parameters
564     aState = rInAttrs.GetItemState( SCHATTR_STAT_CONSTPLUS, sal_True, &pPoolItem );
565     m_bPlusUnique = ( aState != SFX_ITEM_DONTCARE );
566     double fPlusValue = 0.0;
567     if( aState == SFX_ITEM_SET )
568     {
569         fPlusValue = ((const SvxDoubleItem*) pPoolItem)->GetValue();
570         sal_Int32 nPlusValue = static_cast< sal_Int32 >( fPlusValue * pow(10.0,m_aMfPositive.GetDecimalDigits()) );
571 		m_aMfPositive.SetValue( nPlusValue );
572     }
573 
574     aState = rInAttrs.GetItemState( SCHATTR_STAT_CONSTMINUS, sal_True, &pPoolItem );
575     m_bMinusUnique = ( aState != SFX_ITEM_DONTCARE );
576     double fMinusValue = 0.0;
577     if( aState == SFX_ITEM_SET )
578     {
579         fMinusValue = ((const SvxDoubleItem*) pPoolItem)->GetValue();
580         sal_Int32 nMinusValue = static_cast< sal_Int32 >( fMinusValue * pow(10.0,m_aMfNegative.GetDecimalDigits()) );
581 		m_aMfNegative.SetValue( nMinusValue );
582 
583         if( m_eErrorKind != CHERROR_RANGE &&
584             fPlusValue == fMinusValue )
585             m_aCbSyncPosNeg.Check();
586     }
587 
588     // indicator
589     aState = rInAttrs.GetItemState( SCHATTR_STAT_INDICATE, sal_True, &pPoolItem );
590     m_bIndicatorUnique = ( aState != SFX_ITEM_DONTCARE );
591     if( aState == SFX_ITEM_SET)
592 		m_eIndicate = ((const SvxChartIndicateItem * ) pPoolItem)->GetValue();
593 
594     if( m_bIndicatorUnique )
595     {
596         switch( m_eIndicate )
597         {
598             case CHINDICATE_NONE :
599                 // no longer used, use both as default
600                 m_eIndicate = CHINDICATE_BOTH;
601                 // fall-through intended to BOTH
602             case CHINDICATE_BOTH :
603                 m_aRbBoth.Check(); break;
604             case CHINDICATE_UP :
605                 m_aRbPositive.Check(); break;
606             case CHINDICATE_DOWN :
607                 m_aRbNegative.Check(); break;
608         }
609     }
610     else
611     {
612         m_aRbBoth.Check( sal_False );
613         m_aRbPositive.Check( sal_False );
614         m_aRbNegative.Check( sal_False );
615     }
616 
617     // ranges
618     aState = rInAttrs.GetItemState( SCHATTR_STAT_RANGE_POS, sal_True, &pPoolItem );
619     m_bRangePosUnique = ( aState != SFX_ITEM_DONTCARE );
620     if( aState == SFX_ITEM_SET )
621     {
622         String sRangePositive = (static_cast< const SfxStringItem * >( pPoolItem ))->GetValue();
623         m_aEdRangePositive.SetText( sRangePositive );
624     }
625 
626     aState = rInAttrs.GetItemState( SCHATTR_STAT_RANGE_NEG, sal_True, &pPoolItem );
627     m_bRangeNegUnique = ( aState != SFX_ITEM_DONTCARE );
628     if( aState == SFX_ITEM_SET )
629     {
630         String sRangeNegative = (static_cast< const SfxStringItem * >( pPoolItem ))->GetValue();
631         m_aEdRangeNegative.SetText( sRangeNegative );
632         if( m_eErrorKind == CHERROR_RANGE &&
633             sRangeNegative.Len() > 0 &&
634             sRangeNegative.Equals( m_aEdRangePositive.GetText()))
635             m_aCbSyncPosNeg.Check();
636     }
637 
638     UpdateControlStates();
639 }
640 
641 sal_Bool ErrorBarResources::FillItemSet(SfxItemSet& rOutAttrs) const
642 {
643     if( m_bErrorKindUnique )
644         rOutAttrs.Put( SvxChartKindErrorItem( m_eErrorKind, SCHATTR_STAT_KIND_ERROR ));
645     if( m_bIndicatorUnique )
646         rOutAttrs.Put( SvxChartIndicateItem( m_eIndicate, SCHATTR_STAT_INDICATE ));
647 
648     if( m_bErrorKindUnique )
649     {
650         if( m_eErrorKind == CHERROR_RANGE )
651         {
652             String aPosRange;
653             String aNegRange;
654             if( m_bHasInternalDataProvider )
655             {
656                 // the strings aPosRange/aNegRange have to be set to a non-empty
657                 // arbitrary string to generate error-bar sequences
658                 aPosRange.Assign( sal_Unicode('x'));
659                 aNegRange = aPosRange;
660             }
661             else
662             {
663                 aPosRange = m_aEdRangePositive.GetText();
664                 if( m_aCbSyncPosNeg.IsChecked())
665                     aNegRange = aPosRange;
666                 else
667                     aNegRange = m_aEdRangeNegative.GetText();
668             }
669 
670             if( m_bRangePosUnique )
671                 rOutAttrs.Put( SfxStringItem( SCHATTR_STAT_RANGE_POS, aPosRange ));
672             if( m_bRangeNegUnique )
673                 rOutAttrs.Put( SfxStringItem( SCHATTR_STAT_RANGE_NEG, aNegRange ));
674         }
675         else if( m_eErrorKind == CHERROR_CONST ||
676                  m_eErrorKind == CHERROR_PERCENT ||
677                  m_eErrorKind == CHERROR_BIGERROR )
678         {
679             double fPosValue = static_cast< double >( m_aMfPositive.GetValue()) /
680                 pow( 10.0, m_aMfPositive.GetDecimalDigits());
681             double fNegValue = 0.0;
682 
683             if( m_aCbSyncPosNeg.IsChecked())
684                 fNegValue = fPosValue;
685             else
686                 fNegValue = static_cast< double >( m_aMfNegative.GetValue()) /
687                     pow( 10.0, m_aMfNegative.GetDecimalDigits());
688 
689             rOutAttrs.Put( SvxDoubleItem( fPosValue, SCHATTR_STAT_CONSTPLUS ));
690             rOutAttrs.Put( SvxDoubleItem( fNegValue, SCHATTR_STAT_CONSTMINUS ));
691         }
692     }
693 
694 	return sal_True;
695 }
696 
697 void ErrorBarResources::FillValueSets()
698 {
699     bool bIsHighContrast = ( true && m_aRbConst.GetSettings().GetStyleSettings().GetHighContrastMode() );
700 
701     // do not scale images, show then centered
702 //     m_aFiPositive.SetStyle( (m_aFiPositive.GetStyle() & (~WB_SCALE)) | WB_CENTER );
703 //     m_aFiNegative.SetStyle( (m_aFiNegative.GetStyle() & (~WB_SCALE)) | WB_CENTER );
704 //     m_aFiBoth.SetStyle( (m_aFiBoth.GetStyle() & (~WB_SCALE)) | WB_CENTER );
705 
706     if( m_eErrorBarType == ERROR_BAR_Y )
707     {
708         m_aFiNegative.SetImage( SELECT_IMAGE( BMP_INDICATE_DOWN ));
709         m_aFiPositive.SetImage( SELECT_IMAGE( BMP_INDICATE_UP ));
710         m_aFiBoth.SetImage( SELECT_IMAGE( BMP_INDICATE_BOTH_VERTI ));
711     }
712     else if( m_eErrorBarType == ERROR_BAR_X )
713     {
714         m_aFiNegative.SetImage( SELECT_IMAGE( BMP_INDICATE_LEFT ));
715         m_aFiPositive.SetImage( SELECT_IMAGE( BMP_INDICATE_RIGHT ));
716         m_aFiBoth.SetImage( SELECT_IMAGE( BMP_INDICATE_BOTH_HORI ));
717     }
718 }
719 
720 void ErrorBarResources::listeningFinished(
721     const ::rtl::OUString & rNewRange )
722 {
723     OSL_ASSERT( m_apRangeSelectionHelper.get());
724     if( ! m_apRangeSelectionHelper.get())
725         return;
726 
727     // rNewRange becomes invalid after removing the listener
728     ::rtl::OUString aRange( rNewRange );
729 
730 //     m_rDialogModel.startControllerLockTimer();
731 
732     // stop listening
733     m_apRangeSelectionHelper->stopRangeListening();
734 
735     // change edit field
736     if( m_pParentWindow )
737     {
738         m_pParentWindow->ToTop();
739         m_pParentWindow->GrabFocus();
740     }
741 
742     if( m_pCurrentRangeChoosingField )
743     {
744         m_pCurrentRangeChoosingField->SetText( String( aRange ));
745         m_pCurrentRangeChoosingField->GrabFocus();
746         PosValueChanged( 0 );
747     }
748 
749     m_pCurrentRangeChoosingField = 0;
750 
751     UpdateControlStates();
752     OSL_ASSERT( m_pParentDialog );
753     if( m_pParentDialog )
754         lcl_enableRangeChoosing( false, m_pParentDialog );
755 }
756 
757 void ErrorBarResources::disposingRangeSelection()
758 {
759     OSL_ASSERT( m_apRangeSelectionHelper.get());
760     if( m_apRangeSelectionHelper.get())
761         m_apRangeSelectionHelper->stopRangeListening( false );
762 }
763 
764 bool ErrorBarResources::isRangeFieldContentValid( Edit & rEdit )
765 {
766     ::rtl::OUString aRange( rEdit.GetText());
767     bool bIsValid = ( aRange.getLength() == 0 ) ||
768         ( m_apRangeSelectionHelper.get() &&
769           m_apRangeSelectionHelper->verifyCellRange( aRange ));
770 
771     if( bIsValid || !rEdit.IsEnabled())
772     {
773         rEdit.SetControlForeground();
774         rEdit.SetControlBackground();
775     }
776     else
777     {
778         rEdit.SetControlBackground( RANGE_SELECTION_INVALID_RANGE_BACKGROUND_COLOR );
779         rEdit.SetControlForeground( RANGE_SELECTION_INVALID_RANGE_FOREGROUND_COLOR );
780     }
781 
782     return bIsValid;
783 }
784 
785 //.............................................................................
786 } //namespace chart
787 //.............................................................................
788