1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26 
27 // header for class SvNumberformat
28 #ifndef _ZFORMAT_HXX
29 #ifndef _ZFORLIST_DECLARE_TABLE
30 #define _ZFORLIST_DECLARE_TABLE
31 #endif
32 #include <svl/zformat.hxx>
33 #endif
34 // header for SvNumberFormatter
35 #include <svl/zforlist.hxx>
36 
37 #include "DataBrowser.hxx"
38 #include "DataBrowserModel.hxx"
39 #include "Strings.hrc"
40 #include "ContainerHelper.hxx"
41 #include "DataSeriesHelper.hxx"
42 #include "DiagramHelper.hxx"
43 #include "ChartModelHelper.hxx"
44 #include "CommonConverters.hxx"
45 #include "macros.hxx"
46 #include "NumberFormatterWrapper.hxx"
47 #include "servicenames_charttypes.hxx"
48 #include "ResId.hxx"
49 #include "Bitmaps.hrc"
50 #include "Bitmaps_HC.hrc"
51 #include "HelpIds.hrc"
52 
53 #include <vcl/fixed.hxx>
54 #include <vcl/image.hxx>
55 #include <vcl/msgbox.hxx>
56 #include <rtl/math.hxx>
57 
58 #include <com/sun/star/util/XCloneable.hpp>
59 #include <com/sun/star/chart2/XChartDocument.hpp>
60 #include <com/sun/star/chart2/XChartType.hpp>
61 
62 #include <com/sun/star/container/XIndexReplace.hpp>
63 #include <com/sun/star/util/XNumberFormats.hpp>
64 
65 #include <algorithm>
66 #include <functional>
67 
68 #define SELECT_IMAGE(name,hc) Image( SchResId( hc ? name ## _HC : name ))
69 
70 /*  BROWSER_COLUMNSELECTION :  single cells may be selected rather than only
71                                entire rows
72     BROWSER_(H|V)LINES :       show horizontal or vertical grid-lines
73 
74     BROWSER_AUTO_(H|V)SCROLL : scroll automated horizontally or vertically when
75                                cursor is moved beyond the edge of the dialog
76     BROWSER_HIGHLIGHT_NONE :   Do not mark the current row with selection color
77                                (usually blue)
78 
79  */
80 #define BROWSER_STANDARD_FLAGS  \
81     BROWSER_COLUMNSELECTION | \
82     BROWSER_HLINES | BROWSER_VLINES | \
83     BROWSER_AUTO_HSCROLL | BROWSER_AUTO_VSCROLL | \
84     BROWSER_HIGHLIGHT_NONE
85 
86 // BROWSER_HIDECURSOR would prevent flickering in edit fields, but navigating
87 // with shift up/down, and entering non-editable cells would be problematic,
88 // e.g.  the first cell, or when being in read-only mode
89 
90 
91 using namespace ::com::sun::star;
92 using ::com::sun::star::uno::Sequence;
93 using ::com::sun::star::uno::Reference;
94 using ::rtl::OUString;
95 
96 using namespace ::svt;
97 
98 namespace
99 {
100 sal_Int32 lcl_getRowInData( long nRow )
101 {
102     return static_cast< sal_Int32 >( nRow );
103 }
104 
105 sal_Int32 lcl_getColumnInData( sal_uInt16 nCol )
106 {
107     return static_cast< sal_Int32 >( nCol ) - 1;
108 }
109 
110 } // anonymous namespace
111 
112 // --------------------------------------------------------------------------------
113 
114 namespace chart
115 {
116 
117 // ----------------------------------------
118 namespace impl
119 {
120 
121 class SeriesHeaderEdit : public Edit
122 {
123 public:
124     SeriesHeaderEdit( Window * pParent );
125     virtual ~SeriesHeaderEdit();
126     virtual void MouseButtonDown( const MouseEvent& rMEvt );
127 
128     void setStartColumn( sal_Int32 nStartColumn );
129     sal_Int32 getStartColumn() const;
130     void SetShowWarningBox( bool bShowWarning = true );
131 
132 private:
133     sal_Int32 m_nStartColumn;
134     bool m_bShowWarningBox;
135 };
136 
137 SeriesHeaderEdit::SeriesHeaderEdit( Window * pParent ) :
138         Edit( pParent ),
139         m_nStartColumn( 0 ),
140         m_bShowWarningBox( false )
141 {}
142 SeriesHeaderEdit::~SeriesHeaderEdit()
143 {}
144 
145 void SeriesHeaderEdit::setStartColumn( sal_Int32 nStartColumn )
146 {
147     m_nStartColumn = nStartColumn;
148 }
149 
150 sal_Int32 SeriesHeaderEdit::getStartColumn() const
151 {
152     return m_nStartColumn;
153 }
154 
155 void SeriesHeaderEdit::SetShowWarningBox( bool bShowWarning )
156 {
157     m_bShowWarningBox = bShowWarning;
158 }
159 
160 void SeriesHeaderEdit::MouseButtonDown( const MouseEvent& rMEvt )
161 {
162     Edit::MouseButtonDown( rMEvt );
163 
164     if( m_bShowWarningBox )
165         WarningBox( this, WinBits( WB_OK ),
166                     String( SchResId( STR_INVALID_NUMBER ))).Execute();
167 }
168 
169 class SeriesHeader
170 {
171 public:
172     explicit SeriesHeader( Window * pParent );
173 
174     void SetColor( const Color & rCol );
175     void SetPos( const Point & rPos );
176     void SetWidth( sal_Int32 nWidth );
177     void SetChartType( const Reference< chart2::XChartType > & xChartType,
178                        bool bSwapXAndYAxis,
179                        bool bIsHighContrast );
180     void SetSeriesName( const String & rName );
181     void SetRange( sal_Int32 nStartCol, sal_Int32 nEndCol );
182 
183     void SetPixelPosX( sal_Int32 nPos );
184     void SetPixelWidth( sal_Int32 nWidth );
185 
186     sal_Int32 GetStartColumn() const;
187     sal_Int32 GetEndColumn() const;
188 
189     static sal_Int32 GetRelativeAppFontXPosForNameField();
190 
191     void Show();
192 
193     /** call this before destroying the class.  This notifies the listeners to
194         changes of the edit field for the series name.
195      */
196     void applyChanges();
197 
198 	void SetGetFocusHdl( const Link& rLink );
199 
200 	void SetEditChangedHdl( const Link & rLink );
201 
202     bool HasFocus() const;
203 
204 private:
205     ::boost::shared_ptr< FixedImage >        m_spSymbol;
206     ::boost::shared_ptr< SeriesHeaderEdit >  m_spSeriesName;
207     ::boost::shared_ptr< FixedText >         m_spColorBar;
208     OutputDevice *                           m_pDevice;
209     Link                                     m_aChangeLink;
210 
211     void notifyChanges();
212     DECL_LINK( SeriesNameChanged, void * );
213     DECL_LINK( SeriesNameEdited, void * );
214 
215     /// @param bHC </sal_True> for hight-contrast image
216     static Image GetChartTypeImage(
217         const Reference< chart2::XChartType > & xChartType,
218         bool bSwapXAndYAxis,
219         bool bHC );
220 
221     sal_Int32 m_nStartCol, m_nEndCol;
222     sal_Int32 m_nWidth;
223     Point     m_aPos;
224     bool      m_bSeriesNameChangePending;
225 };
226 
227 SeriesHeader::SeriesHeader( Window * pParent ) :
228         m_spSymbol( new FixedImage( pParent, WB_NOBORDER )),
229         m_spSeriesName( new SeriesHeaderEdit( pParent )),
230         m_spColorBar( new FixedText( pParent, WB_NOBORDER )),
231         m_pDevice( pParent ),
232         m_nStartCol( 0 ),
233         m_nEndCol( 0 ),
234         m_nWidth( 42 ),
235         m_aPos( 0, 22 ),
236         m_bSeriesNameChangePending( false )
237 {
238     m_spSeriesName->EnableUpdateData( 4 * EDIT_UPDATEDATA_TIMEOUT ); // define is in vcl/edit.hxx
239     m_spSeriesName->SetUpdateDataHdl( LINK( this, SeriesHeader, SeriesNameChanged ));
240     m_spSeriesName->SetModifyHdl( LINK( this, SeriesHeader, SeriesNameEdited ));
241     m_spSeriesName->SetHelpId( HID_SCH_DATA_SERIES_LABEL );
242     Show();
243 }
244 
245 void SeriesHeader::notifyChanges()
246 {
247     if( m_aChangeLink.IsSet())
248 		m_aChangeLink.Call( m_spSeriesName.get());
249 
250     m_bSeriesNameChangePending = false;
251 }
252 
253 void SeriesHeader::applyChanges()
254 {
255     if( m_bSeriesNameChangePending )
256     {
257         notifyChanges();
258     }
259 }
260 
261 void SeriesHeader::SetColor( const Color & rCol )
262 {
263     m_spColorBar->SetControlBackground( rCol );
264 }
265 
266 const sal_Int32 nSymbolHeight = 10;
267 const sal_Int32 nSymbolDistance = 2;
268 
269 sal_Int32 SeriesHeader::GetRelativeAppFontXPosForNameField()
270 {
271     return nSymbolHeight + nSymbolDistance;
272 }
273 
274 void SeriesHeader::SetPos( const Point & rPos )
275 {
276     m_aPos = rPos;
277 
278     // chart type symbol
279     Point aPos( rPos );
280     aPos.setY( aPos.getY() + nSymbolDistance );
281     Size aSize( nSymbolHeight, nSymbolHeight );
282     m_spSymbol->SetPosPixel( m_pDevice->LogicToPixel( aPos, MAP_APPFONT ));
283     m_spSymbol->SetSizePixel( m_pDevice->LogicToPixel( aSize, MAP_APPFONT ));
284     aPos.setY( aPos.getY() - nSymbolDistance );
285 
286     // series name edit field
287     aPos.setX( aPos.getX() + nSymbolHeight + nSymbolDistance );
288     aSize.setWidth( m_nWidth - nSymbolHeight - nSymbolDistance );
289     sal_Int32 nHeight = 12;
290     aSize.setHeight( nHeight );
291     m_spSeriesName->SetPosPixel( m_pDevice->LogicToPixel( aPos, MAP_APPFONT ));
292     m_spSeriesName->SetSizePixel( m_pDevice->LogicToPixel( aSize, MAP_APPFONT ));
293 
294     // color bar
295     aPos.setX( rPos.getX() + 1 );
296     aPos.setY( aPos.getY() + nHeight + 2 );
297     nHeight = 3;
298     aSize.setWidth( m_nWidth - 1 );
299     aSize.setHeight( nHeight );
300     m_spColorBar->SetPosPixel( m_pDevice->LogicToPixel( aPos, MAP_APPFONT ));
301     m_spColorBar->SetSizePixel( m_pDevice->LogicToPixel( aSize, MAP_APPFONT ));
302 }
303 
304 void SeriesHeader::SetWidth( sal_Int32 nWidth )
305 {
306     m_nWidth = nWidth;
307     SetPos( m_aPos );
308 }
309 
310 
311 void SeriesHeader::SetPixelPosX( sal_Int32 nPos )
312 {
313     Point aPos( m_pDevice->LogicToPixel( m_aPos, MAP_APPFONT ));
314     aPos.setX( nPos );
315     SetPos( m_pDevice->PixelToLogic( aPos, MAP_APPFONT ));
316 }
317 
318 void SeriesHeader::SetPixelWidth( sal_Int32 nWidth )
319 {
320     SetWidth( m_pDevice->PixelToLogic( Size( nWidth, 0 ), MAP_APPFONT ).getWidth());
321 }
322 
323 void SeriesHeader::SetChartType(
324     const Reference< chart2::XChartType > & xChartType,
325     bool bSwapXAndYAxis,
326     bool bIsHighContrast )
327 {
328     m_spSymbol->SetImage( GetChartTypeImage( xChartType, bSwapXAndYAxis, bIsHighContrast ));
329 }
330 
331 void SeriesHeader::SetSeriesName( const String & rName )
332 {
333     m_spSeriesName->SetText( rName );
334 }
335 
336 void SeriesHeader::SetRange( sal_Int32 nStartCol, sal_Int32 nEndCol )
337 {
338     m_nStartCol = nStartCol;
339     m_nEndCol = (nEndCol > nStartCol) ? nEndCol : nStartCol;
340     m_spSeriesName->setStartColumn( nStartCol );
341 }
342 
343 sal_Int32 SeriesHeader::GetStartColumn() const
344 {
345     return m_nStartCol;
346 }
347 
348 sal_Int32 SeriesHeader::GetEndColumn() const
349 {
350     return m_nEndCol;
351 }
352 
353 void SeriesHeader::Show()
354 {
355     m_spSymbol->Show();
356     m_spSeriesName->Show();
357     m_spColorBar->Show();
358 }
359 
360 void SeriesHeader::SetEditChangedHdl( const Link & rLink )
361 {
362     m_aChangeLink = rLink;
363 }
364 
365 IMPL_LINK( SeriesHeader, SeriesNameChanged, void * , EMPTYARG )
366 {
367     notifyChanges();
368     return 0;
369 }
370 
371 IMPL_LINK( SeriesHeader, SeriesNameEdited, void * , EMPTYARG )
372 {
373     m_bSeriesNameChangePending = true;
374     return 0;
375 }
376 
377 void SeriesHeader::SetGetFocusHdl( const Link& rLink )
378 {
379     m_spSeriesName->SetGetFocusHdl( rLink );
380 }
381 
382 bool SeriesHeader::HasFocus() const
383 {
384     return m_spSeriesName->HasFocus();
385 }
386 
387 Image SeriesHeader::GetChartTypeImage(
388     const Reference< chart2::XChartType > & xChartType,
389     bool bSwapXAndYAxis,
390     bool bHC )
391 {
392     Image aResult;
393     if( !xChartType.is())
394         return aResult;
395     OUString aChartTypeName( xChartType->getChartType());
396 
397     if( aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_AREA ))
398     {
399         aResult = SELECT_IMAGE( IMG_TYPE_AREA, bHC );
400     }
401     else if( aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_COLUMN ))
402     {
403         if( bSwapXAndYAxis )
404             aResult = SELECT_IMAGE( IMG_TYPE_BAR, bHC );
405         else
406             aResult = SELECT_IMAGE( IMG_TYPE_COLUMN, bHC );
407     }
408     else if( aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_LINE ))
409     {
410         aResult = SELECT_IMAGE( IMG_TYPE_LINE, bHC );
411     }
412     else if( aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_SCATTER ))
413     {
414         aResult = SELECT_IMAGE( IMG_TYPE_XY, bHC );
415     }
416     else if( aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_PIE ))
417     {
418         aResult = SELECT_IMAGE( IMG_TYPE_PIE, bHC );
419     }
420     else if( aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_NET )
421           || aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_FILLED_NET ) )
422     {
423         aResult = SELECT_IMAGE( IMG_TYPE_NET, bHC );
424     }
425     else if( aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ))
426     {
427         // @todo: correct image for candle-stick type
428         aResult = SELECT_IMAGE( IMG_TYPE_STOCK, bHC );
429     }
430     else if( aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE ))
431     {
432         aResult = SELECT_IMAGE( IMG_TYPE_BUBBLE, bHC );
433     }
434 
435     return aResult;
436 }
437 
438 struct applyChangesFunctor : public ::std::unary_function< ::boost::shared_ptr< SeriesHeader >, void >
439 {
440     void operator() ( ::boost::shared_ptr< SeriesHeader > spHeader )
441     {
442         spHeader->applyChanges();
443     }
444 };
445 
446 } // namespace impl
447 // ----------------------------------------
448 
449 namespace
450 {
451 
452 /** returns false, if no header as the focus.
453 
454     If a header has the focus, true is returned and the index of the header
455     with focus is set at pIndex if pOutIndex is not 0.
456 */
457 bool lcl_SeriesHeaderHasFocus(
458     const ::std::vector< ::boost::shared_ptr< ::chart::impl::SeriesHeader > > & rSeriesHeader,
459     sal_Int32 * pOutIndex = 0 )
460 {
461     sal_Int32 nIndex = 0;
462     for( ::std::vector< ::boost::shared_ptr< ::chart::impl::SeriesHeader > >::const_iterator aIt( rSeriesHeader.begin());
463          aIt != rSeriesHeader.end(); ++aIt, ++nIndex )
464     {
465         if( (*aIt)->HasFocus())
466         {
467             if( pOutIndex )
468                 *pOutIndex = nIndex;
469             return true;
470         }
471     }
472     return false;
473 }
474 
475 sal_Int32 lcl_getColumnInDataOrHeader(
476     sal_uInt16 nCol, const ::std::vector< ::boost::shared_ptr< ::chart::impl::SeriesHeader > > & rSeriesHeader )
477 {
478     sal_Int32 nColIdx = 0;
479     bool bHeaderHasFocus( lcl_SeriesHeaderHasFocus( rSeriesHeader, &nColIdx ));
480 
481     if( bHeaderHasFocus )
482         nColIdx = lcl_getColumnInData( static_cast< sal_uInt16 >( rSeriesHeader[nColIdx]->GetStartColumn()));
483     else
484         nColIdx = lcl_getColumnInData( nCol );
485 
486     return nColIdx;
487 }
488 
489 } // anonymous namespace
490 
491 
492 DataBrowser::DataBrowser( Window* pParent, const ResId& rId, bool bLiveUpdate ) :
493 	::svt::EditBrowseBox( pParent, rId, EBBF_SMART_TAB_TRAVEL | EBBF_HANDLE_COLUMN_TEXT, BROWSER_STANDARD_FLAGS ),
494 	m_nSeekRow( 0 ),
495     m_bIsReadOnly( false ),
496     m_bIsDirty( false ),
497     m_bLiveUpdate( bLiveUpdate ),
498     m_bDataValid( true ),
499     m_aNumberEditField( & EditBrowseBox::GetDataWindow(), WB_NOBORDER ),
500     m_aTextEditField( & EditBrowseBox::GetDataWindow(), WB_NOBORDER ),
501     m_rNumberEditController( new ::svt::FormattedFieldCellController( & m_aNumberEditField )),
502     m_rTextEditController( new ::svt::EditCellController( & m_aTextEditField ))
503 {
504     double fNan;
505     ::rtl::math::setNan( & fNan );
506     m_aNumberEditField.SetDefaultValue( fNan );
507     m_aNumberEditField.TreatAsNumber( sal_True );
508     RenewTable();
509     SetClean();
510 }
511 
512 DataBrowser::~DataBrowser()
513 {
514 }
515 
516 bool DataBrowser::MayInsertRow() const
517 {
518     return ! IsReadOnly()
519         && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ));
520 }
521 
522 bool DataBrowser::MayInsertColumn() const
523 {
524     return ! IsReadOnly();
525 }
526 
527 bool DataBrowser::MayDeleteRow() const
528 {
529     return ! IsReadOnly()
530         && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
531         && ( GetCurRow() >= 0 )
532         && ( GetRowCount() > 1 );
533 }
534 
535 bool DataBrowser::MayDeleteColumn() const
536 {
537     // if a series header has the focus
538     if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
539         return true;
540 
541     return ! IsReadOnly()
542         && ( GetCurColumnId() > 1 )
543         && ( ColCount() > 2 );
544 }
545 
546 bool DataBrowser::MaySwapRows() const
547 {
548     return ! IsReadOnly()
549         && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
550         && ( GetCurRow() >= 0 )
551         && ( GetCurRow() < GetRowCount() - 1 );
552 }
553 
554 bool DataBrowser::MaySwapColumns() const
555 {
556     // if a series header (except the last one) has the focus
557     {
558         sal_Int32 nColIndex(0);
559         if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders, &nColIndex ))
560             return (static_cast< sal_uInt32 >( nColIndex ) < (m_aSeriesHeaders.size() - 1));
561     }
562 
563     sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
564     return ! IsReadOnly()
565         && ( nColIdx > 0 )
566         && ( nColIdx < ColCount()-2 )
567         && m_apDataBrowserModel.get()
568         && !m_apDataBrowserModel->isCategoriesColumn( nColIdx );
569 }
570 
571 void DataBrowser::clearHeaders()
572 {
573     ::std::for_each( m_aSeriesHeaders.begin(), m_aSeriesHeaders.end(), impl::applyChangesFunctor());
574     m_aSeriesHeaders.clear();
575 }
576 
577 void DataBrowser::RenewTable()
578 {
579     if( ! m_apDataBrowserModel.get())
580         return;
581 
582     long   nOldRow     = GetCurRow();
583     sal_uInt16 nOldColId   = GetCurColumnId();
584 
585 	sal_Bool bLastUpdateMode = GetUpdateMode();
586 	SetUpdateMode( sal_False );
587 
588     if( IsModified() )
589         SaveModified();
590 
591     DeactivateCell();
592 
593     RemoveColumns();
594     RowRemoved( 1, GetRowCount() );
595 
596     // for row numbers
597 	InsertHandleColumn( static_cast< sal_uInt16 >(
598                             GetDataWindow().LogicToPixel( Size( 42, 0 )).getWidth() ));
599 
600     OUString aDefaultSeriesName( ::chart::SchResId::getResString( STR_COLUMN_LABEL ));
601     replaceParamterInString( aDefaultSeriesName, C2U("%COLUMNNUMBER"), OUString::valueOf( sal_Int32(24) ) );
602     sal_Int32 nColumnWidth = GetDataWindow().GetTextWidth( aDefaultSeriesName )
603         + GetDataWindow().LogicToPixel( Point( 4 + impl::SeriesHeader::GetRelativeAppFontXPosForNameField(), 0 ), MAP_APPFONT ).X();
604     sal_Int32 nColumnCount = m_apDataBrowserModel->getColumnCount();
605     // nRowCount is a member of a base class
606     sal_Int32 nRowCountLocal = m_apDataBrowserModel->getMaxRowCount();
607     for( sal_Int32 nColIdx=1; nColIdx<=nColumnCount; ++nColIdx )
608     {
609         InsertDataColumn( static_cast< sal_uInt16 >( nColIdx ), GetColString( nColIdx ), nColumnWidth );
610     }
611 
612     RowInserted( 1, nRowCountLocal );
613     GoToRow( ::std::min( nOldRow, GetRowCount() - 1 ));
614     GoToColumnId( ::std::min( nOldColId, static_cast< sal_uInt16 >( ColCount() - 1 )));
615 
616     Window * pWin = this->GetParent();
617     if( !pWin )
618         pWin = this;
619 
620     // fill series headers
621     clearHeaders();
622     const DataBrowserModel::tDataHeaderVector& aHeaders( m_apDataBrowserModel->getDataHeaders());
623     Link aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus ));
624     Link aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged ));
625     bool bIsHighContrast = pWin ? (pWin->GetSettings().GetStyleSettings().GetHighContrastMode()) : false;
626 
627     for( DataBrowserModel::tDataHeaderVector::const_iterator aIt( aHeaders.begin());
628          aIt != aHeaders.end(); ++aIt )
629     {
630         ::boost::shared_ptr< impl::SeriesHeader > spHeader( new impl::SeriesHeader( pWin ));
631         Reference< beans::XPropertySet > xSeriesProp( aIt->m_xDataSeries, uno::UNO_QUERY );
632         sal_Int32 nColor = 0;
633         // @todo: Set "DraftColor", i.e. interpolated colors for gradients, bitmaps, etc.
634         if( xSeriesProp.is() &&
635             ( xSeriesProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Color"))) >>= nColor ))
636             spHeader->SetColor( Color( nColor ));
637         spHeader->SetChartType( aIt->m_xChartType, aIt->m_bSwapXAndYAxis, bIsHighContrast );
638         spHeader->SetSeriesName(
639             String( DataSeriesHelper::getDataSeriesLabel(
640                         aIt->m_xDataSeries,
641                         (aIt->m_xChartType.is() ?
642                          aIt->m_xChartType->getRoleOfSequenceForSeriesLabel() :
643                          OUString( RTL_CONSTASCII_USTRINGPARAM("values-y"))))));
644         // index is 1-based, as 0 is for the column that contains the row-numbers
645         spHeader->SetRange( aIt->m_nStartColumn + 1, aIt->m_nEndColumn + 1 );
646         spHeader->SetGetFocusHdl( aFocusLink );
647         spHeader->SetEditChangedHdl( aSeriesHeaderChangedLink );
648         m_aSeriesHeaders.push_back( spHeader );
649     }
650 
651     ImplAdjustHeaderControls();
652     SetDirty();
653 	SetUpdateMode( bLastUpdateMode );
654     ActivateCell();
655     Invalidate();
656 }
657 
658 String DataBrowser::GetColString( sal_Int32 nColumnId ) const
659 {
660     OSL_ASSERT( m_apDataBrowserModel.get());
661     if( nColumnId > 0 )
662         return String( m_apDataBrowserModel->getRoleOfColumn( static_cast< sal_Int32 >( nColumnId ) - 1 ));
663     return String();
664 }
665 
666 String DataBrowser::GetRowString( sal_Int32 nRow ) const
667 {
668 	return String::CreateFromInt32( nRow + 1 );
669 }
670 
671 String DataBrowser::GetCellText( long nRow, sal_uInt16 nColumnId ) const
672 {
673 	String aResult;
674 
675 	if( nColumnId == 0 )
676 	{
677 		aResult = GetRowString( static_cast< sal_Int32 >( nRow ));
678 	}
679 	else if( nRow >= 0 &&
680              m_apDataBrowserModel.get())
681 	{
682         sal_Int32 nColIndex = static_cast< sal_Int32 >( nColumnId ) - 1;
683 
684         if( m_apDataBrowserModel->getCellType( nColIndex, nRow ) == DataBrowserModel::NUMBER )
685         {
686             double fData( m_apDataBrowserModel->getCellNumber( nColIndex, nRow ));
687             sal_Int32 nLabelColor;
688             bool bColorChanged = false;
689 
690             if( ! ::rtl::math::isNan( fData ) &&
691                 m_spNumberFormatterWrapper.get() )
692                 aResult = String( m_spNumberFormatterWrapper->getFormattedString(
693                                       GetNumberFormatKey( nRow, nColumnId ),
694                                       fData, nLabelColor, bColorChanged ));
695         }
696         else if( m_apDataBrowserModel->getCellType( nColIndex, nRow ) == DataBrowserModel::TEXTORDATE )
697         {
698             uno::Any aAny = m_apDataBrowserModel->getCellAny( nColIndex, nRow );
699             OUString aText;
700             double fDouble=0.0;
701             if( aAny>>=aText )
702                 aResult = aText;
703             else if( aAny>>=fDouble )
704             {
705                 sal_Int32 nLabelColor;
706                 bool bColorChanged = false;
707                 sal_Int32 nDateNumberFormat = DiagramHelper::getDateNumberFormat( Reference< util::XNumberFormatsSupplier >( m_xChartDoc, uno::UNO_QUERY) );
708                 if( ! ::rtl::math::isNan( fDouble ) && m_spNumberFormatterWrapper.get() )
709                     aResult = String( m_spNumberFormatterWrapper->getFormattedString(
710                         nDateNumberFormat, fDouble, nLabelColor, bColorChanged ));
711             }
712         }
713         else
714         {
715             OSL_ASSERT( m_apDataBrowserModel->getCellType( nColIndex, nRow ) == DataBrowserModel::TEXT );
716             aResult = m_apDataBrowserModel->getCellText( nColIndex, nRow );
717         }
718     }
719 
720 	return aResult;
721 }
722 
723 double DataBrowser::GetCellNumber( long nRow, sal_uInt16 nColumnId ) const
724 {
725     double fResult;
726     ::rtl::math::setNan( & fResult );
727 
728     if(( nColumnId >= 1 ) && ( nRow >= 0 ) &&
729         m_apDataBrowserModel.get())
730 	{
731         fResult = m_apDataBrowserModel->getCellNumber(
732             static_cast< sal_Int32 >( nColumnId ) - 1, nRow );
733     }
734 
735 	return fResult;
736 }
737 
738 void DataBrowser::Resize()
739 {
740     sal_Bool bLastUpdateMode = GetUpdateMode();
741 	SetUpdateMode( sal_False );
742 
743     ::svt::EditBrowseBox::Resize();
744     ImplAdjustHeaderControls();
745     SetUpdateMode( bLastUpdateMode );
746 }
747 
748 bool DataBrowser::SetReadOnly( bool bNewState )
749 {
750     bool bResult = m_bIsReadOnly;
751 
752     if( m_bIsReadOnly != bNewState )
753     {
754         m_bIsReadOnly = bNewState;
755         Invalidate();
756         DeactivateCell();
757     }
758 
759     return bResult;
760 }
761 
762 bool DataBrowser::IsReadOnly() const
763 {
764     return m_bIsReadOnly;
765 }
766 
767 
768 void DataBrowser::SetClean()
769 {
770     m_bIsDirty = false;
771 }
772 
773 void DataBrowser::SetDirty()
774 {
775     if( !m_bLiveUpdate )
776         m_bIsDirty = true;
777 }
778 
779 void DataBrowser::CursorMoved()
780 {
781 	EditBrowseBox::CursorMoved();
782 
783 	if( GetUpdateMode() && m_aCursorMovedHdlLink.IsSet())
784 		m_aCursorMovedHdlLink.Call( this );
785 }
786 
787 void DataBrowser::SetCellModifiedHdl( const Link& rLink )
788 {
789     m_aCellModifiedLink = rLink;
790 }
791 
792 void DataBrowser::MouseButtonDown( const BrowserMouseEvent& rEvt )
793 {
794     if( !m_bDataValid )
795         ShowWarningBox();
796     else
797         EditBrowseBox::MouseButtonDown( rEvt );
798 }
799 
800 void DataBrowser::ShowWarningBox()
801 {
802     WarningBox( this, WinBits( WB_OK ),
803                 String( SchResId( STR_INVALID_NUMBER ))).Execute();
804 }
805 
806 bool DataBrowser::ShowQueryBox()
807 {
808     QueryBox* pQueryBox = new QueryBox( this, WB_YES_NO, String( SchResId( STR_DATA_EDITOR_INCORRECT_INPUT )));
809 
810     return ( pQueryBox->Execute() == RET_YES );
811 }
812 
813 bool DataBrowser::IsDataValid()
814 {
815     bool bValid = true;
816     const sal_Int32 nRow = lcl_getRowInData( GetCurRow());
817     const sal_Int32 nCol = lcl_getColumnInData( GetCurColumnId());
818 
819     if( m_apDataBrowserModel->getCellType( nCol, nRow ) == DataBrowserModel::NUMBER )
820     {
821         sal_uInt32 nDummy = 0;
822         double fDummy = 0.0;
823         String aText( m_aNumberEditField.GetText());
824 
825         if( aText.Len() > 0 &&
826             m_spNumberFormatterWrapper.get() &&
827             m_spNumberFormatterWrapper->getSvNumberFormatter() &&
828             ! m_spNumberFormatterWrapper->getSvNumberFormatter()->IsNumberFormat(
829               aText, nDummy, fDummy ))
830         {
831             bValid = false;
832         }
833     }
834 
835     return bValid;
836 }
837 
838 bool DataBrowser::IsEnableItem()
839 {
840     return m_bDataValid;
841 }
842 
843 void DataBrowser::CellModified()
844 {
845     m_bDataValid = IsDataValid();
846     SetDirty();
847     if( m_aCellModifiedLink.IsSet())
848         m_aCursorMovedHdlLink.Call( this );
849 }
850 
851 void DataBrowser::SetDataFromModel(
852     const Reference< chart2::XChartDocument > & xChartDoc,
853     const Reference< uno::XComponentContext > & xContext )
854 {
855     if( m_bLiveUpdate )
856     {
857         m_xChartDoc.set( xChartDoc );
858     }
859     else
860     {
861         Reference< util::XCloneable > xCloneable( xChartDoc, uno::UNO_QUERY );
862         if( xCloneable.is())
863             m_xChartDoc.set( xCloneable->createClone(), uno::UNO_QUERY );
864     }
865 
866     m_apDataBrowserModel.reset( new DataBrowserModel( m_xChartDoc, xContext ));
867     m_spNumberFormatterWrapper.reset(
868         new NumberFormatterWrapper(
869             Reference< util::XNumberFormatsSupplier >( m_xChartDoc, uno::UNO_QUERY )));
870 
871     if( m_spNumberFormatterWrapper.get() )
872         m_aNumberEditField.SetFormatter( m_spNumberFormatterWrapper->getSvNumberFormatter() );
873 
874     RenewTable();
875 
876     const sal_Int32 nColCnt  = m_apDataBrowserModel->getColumnCount();
877     const sal_Int32 nRowCnt =  m_apDataBrowserModel->getMaxRowCount();
878     if( nRowCnt && nColCnt )
879     {
880         GoToRow( 0 );
881         GoToColumnId( 1 );
882     }
883     SetClean();
884 }
885 
886 void DataBrowser::InsertColumn()
887 {
888     sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
889 
890 	if( nColIdx >= 0 &&
891         m_apDataBrowserModel.get())
892 	{
893         // save changes made to edit-field
894         if( IsModified() )
895             SaveModified();
896 
897         m_apDataBrowserModel->insertDataSeries( nColIdx );
898 		RenewTable();
899 	}
900 }
901 
902 void DataBrowser::InsertTextColumn()
903 {
904     sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
905 
906 	if( nColIdx >= 0 &&
907         m_apDataBrowserModel.get())
908 	{
909         // save changes made to edit-field
910         if( IsModified() )
911             SaveModified();
912 
913         m_apDataBrowserModel->insertComplexCategoryLevel( nColIdx );
914 		RenewTable();
915 	}
916 }
917 
918 void DataBrowser::RemoveColumn()
919 {
920     sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
921 
922 	if( nColIdx >= 0 &&
923         m_apDataBrowserModel.get())
924 	{
925         // save changes made to edit-field
926         if( IsModified() )
927             SaveModified();
928 
929         m_bDataValid = true;
930         m_apDataBrowserModel->removeDataSeriesOrComplexCategoryLevel( nColIdx );
931         RenewTable();
932 	}
933 }
934 
935 void DataBrowser::InsertRow()
936 {
937  	sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow());
938 
939  	if( nRowIdx >= 0 &&
940         m_apDataBrowserModel.get())
941     {
942         // save changes made to edit-field
943         if( IsModified() )
944             SaveModified();
945 
946         m_apDataBrowserModel->insertDataPointForAllSeries( nRowIdx );
947 		RenewTable();
948 	}
949 }
950 
951 void DataBrowser::RemoveRow()
952 {
953  	sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow());
954 
955  	if( nRowIdx >= 0 &&
956         m_apDataBrowserModel.get())
957     {
958         // save changes made to edit-field
959         if( IsModified() )
960             SaveModified();
961 
962         m_bDataValid = true;
963         m_apDataBrowserModel->removeDataPointForAllSeries( nRowIdx );
964 		RenewTable();
965 	}
966 }
967 
968 void DataBrowser::SwapColumn()
969 {
970     sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
971 
972 	if( nColIdx >= 0 &&
973         m_apDataBrowserModel.get())
974 	{
975         // save changes made to edit-field
976         if( IsModified() )
977             SaveModified();
978 
979         m_apDataBrowserModel->swapDataSeries( nColIdx );
980 
981         // keep cursor in swapped column
982         if( GetCurColumnId() < ColCount() - 1 )
983 		{
984             Dispatch( BROWSER_CURSORRIGHT );
985 		}
986         RenewTable();
987 	}
988 }
989 
990 void DataBrowser::SwapRow()
991 {
992  	sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow());
993 
994  	if( nRowIdx >= 0 &&
995         m_apDataBrowserModel.get())
996     {
997         // save changes made to edit-field
998         if( IsModified() )
999             SaveModified();
1000 
1001         m_apDataBrowserModel->swapDataPointForAllSeries( nRowIdx );
1002 
1003         // keep cursor in swapped row
1004         if( GetCurRow() < GetRowCount() - 1 )
1005 		{
1006             Dispatch( BROWSER_CURSORDOWN );
1007 		}
1008         RenewTable();
1009 	}
1010 }
1011 
1012 void DataBrowser::SetCursorMovedHdl( const Link& rLink )
1013 {
1014     m_aCursorMovedHdlLink = rLink;
1015 }
1016 
1017 // implementations for ::svt::EditBrowseBox (pure virtual methods)
1018 void DataBrowser::PaintCell(
1019     OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId ) const
1020 {
1021     Point aPos( rRect.TopLeft());
1022     aPos.X() += 1;
1023 
1024     String aText = GetCellText( m_nSeekRow, nColumnId );
1025     Size TxtSize( GetDataWindow().GetTextWidth( aText ), GetDataWindow().GetTextHeight());
1026 
1027     // clipping
1028     if( aPos.X() < rRect.Right() || aPos.X() + TxtSize.Width() > rRect.Right() ||
1029         aPos.Y() < rRect.Top() || aPos.Y() + TxtSize.Height() > rRect.Bottom())
1030         rDev.SetClipRegion( rRect );
1031 
1032     // allow for a disabled control ...
1033     sal_Bool bEnabled = IsEnabled();
1034     Color aOriginalColor = rDev.GetTextColor();
1035     if( ! bEnabled )
1036         rDev.SetTextColor( GetSettings().GetStyleSettings().GetDisableColor() );
1037 
1038     // TEST
1039 //     if( nColumnId == 1 )
1040 //         // categories
1041 //         rDev.SetFillColor( Color( 0xff, 0xff, 0xff ));
1042 //     else if( nColumnId == 2 )
1043 //         // x-values
1044 //         rDev.SetFillColor( Color( 0xf0, 0xf0, 0xff ));
1045 //     else
1046 //         // y-values
1047 //         rDev.SetFillColor( Color( 0xff, 0xff, 0xf0 ));
1048 
1049 //     rDev.DrawRect( rRect );
1050 
1051     // draw the text
1052     rDev.DrawText( aPos, aText );
1053 
1054     // reset the color (if necessary)
1055     if( ! bEnabled )
1056         rDev.SetTextColor( aOriginalColor );
1057 
1058     if( rDev.IsClipRegion())
1059         rDev.SetClipRegion();
1060 }
1061 
1062 sal_Bool DataBrowser::SeekRow( long nRow )
1063 {
1064     if( ! EditBrowseBox::SeekRow( nRow ))
1065         return sal_False;
1066 
1067     if( nRow < 0 )
1068         m_nSeekRow = - 1;
1069     else
1070         m_nSeekRow = nRow;
1071 
1072     return sal_True;
1073 }
1074 
1075 sal_Bool DataBrowser::IsTabAllowed( sal_Bool bForward ) const
1076 {
1077     long nRow = GetCurRow();
1078     long nCol = GetCurColumnId();
1079 
1080     // column 0 is header-column
1081     long nBadCol = bForward
1082         ? GetColumnCount() - 1
1083         : 1;
1084     long nBadRow = bForward
1085         ? GetRowCount() - 1
1086         : 0;
1087 
1088     if( !m_bDataValid )
1089     {
1090         const_cast< DataBrowser* >( this )->ShowWarningBox();
1091         return sal_False;
1092     }
1093 
1094     return ( nRow != nBadRow ||
1095              nCol != nBadCol );
1096 }
1097 
1098 ::svt::CellController* DataBrowser::GetController( long nRow, sal_uInt16 nCol )
1099 {
1100     if( m_bIsReadOnly )
1101         return 0;
1102 
1103     if( CellContainsNumbers( nRow, nCol ))
1104     {
1105         m_aNumberEditField.UseInputStringForFormatting();
1106         m_aNumberEditField.SetFormatKey( GetNumberFormatKey( nRow, nCol ));
1107         return m_rNumberEditController;
1108     }
1109 
1110     return m_rTextEditController;
1111 }
1112 
1113 void DataBrowser::InitController(
1114     ::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol )
1115 {
1116     if( rController == m_rTextEditController )
1117     {
1118         String aText( GetCellText( nRow, nCol ) );
1119         m_aTextEditField.SetText( aText );
1120         m_aTextEditField.SetSelection( Selection( 0, aText.Len() ));
1121     }
1122     else if( rController == m_rNumberEditController )
1123     {
1124         // treat invalid and empty text as Nan
1125         m_aNumberEditField.EnableNotANumber( true );
1126         if( ::rtl::math::isNan( GetCellNumber( nRow, nCol )))
1127             m_aNumberEditField.SetTextValue( String());
1128         else
1129             m_aNumberEditField.SetValue( GetCellNumber( nRow, nCol ) );
1130         String aText( m_aNumberEditField.GetText());
1131         m_aNumberEditField.SetSelection( Selection( 0, aText.Len()));
1132     }
1133     else
1134     {
1135         DBG_ERROR( "Invalid Controller" );
1136     }
1137 }
1138 
1139 bool DataBrowser::CellContainsNumbers( sal_Int32 nRow, sal_uInt16 nCol ) const
1140 {
1141     if( ! m_apDataBrowserModel.get())
1142         return false;
1143     return (m_apDataBrowserModel->getCellType( lcl_getColumnInData( nCol ), lcl_getRowInData( nRow )) ==
1144             DataBrowserModel::NUMBER);
1145 }
1146 
1147 sal_uInt32 DataBrowser::GetNumberFormatKey( sal_Int32 nRow, sal_uInt16 nCol ) const
1148 {
1149     if( ! m_apDataBrowserModel.get())
1150         return 0;
1151     return m_apDataBrowserModel->getNumberFormatKey( lcl_getColumnInData( nCol ), lcl_getRowInData( nRow ));
1152 }
1153 
1154 bool DataBrowser::isDateString( rtl::OUString aInputString, double& fOutDateValue )
1155 {
1156     sal_uInt32 nNumberFormat=0;
1157     SvNumberFormatter* pSvNumberFormatter = m_spNumberFormatterWrapper.get() ? m_spNumberFormatterWrapper->getSvNumberFormatter() : 0;
1158     if( aInputString.getLength() > 0 &&  pSvNumberFormatter && pSvNumberFormatter->IsNumberFormat( aInputString, nNumberFormat, fOutDateValue ) )
1159     {
1160         Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( m_xChartDoc, uno::UNO_QUERY );
1161         Reference< util::XNumberFormats > xNumberFormats;
1162         if( xNumberFormatsSupplier.is() )
1163              xNumberFormats = Reference< util::XNumberFormats >( xNumberFormatsSupplier->getNumberFormats() );
1164         if( DiagramHelper::isDateNumberFormat( nNumberFormat, xNumberFormats ) )
1165             return true;
1166     }
1167     return false;
1168 }
1169 
1170 sal_Bool DataBrowser::SaveModified()
1171 {
1172     if( ! IsModified() )
1173         return sal_True;
1174 
1175     sal_Bool bChangeValid = sal_True;
1176 
1177     const sal_Int32 nRow = lcl_getRowInData( GetCurRow());
1178     const sal_Int32 nCol = lcl_getColumnInData( GetCurColumnId());
1179 
1180     DBG_ASSERT( nRow >= 0 || nCol >= 0, "This cell should not be modified!" );
1181 
1182     SvNumberFormatter* pSvNumberFormatter = m_spNumberFormatterWrapper.get() ? m_spNumberFormatterWrapper->getSvNumberFormatter() : 0;
1183     switch( m_apDataBrowserModel->getCellType( nCol, nRow ))
1184     {
1185         case DataBrowserModel::NUMBER:
1186         {
1187             sal_uInt32 nDummy = 0;
1188             double fDummy = 0.0;
1189             String aText( m_aNumberEditField.GetText());
1190             // an empty string is valid, if no numberformatter exists, all
1191             // values are treated as valid
1192             if( aText.Len() > 0 && pSvNumberFormatter &&
1193                 ! pSvNumberFormatter->IsNumberFormat( aText, nDummy, fDummy ) )
1194             {
1195                 bChangeValid = sal_False;
1196             }
1197             else
1198             {
1199                 double fData = m_aNumberEditField.GetValue();
1200                 bChangeValid = m_apDataBrowserModel->setCellNumber( nCol, nRow, fData );
1201             }
1202         }
1203         break;
1204         case DataBrowserModel::TEXTORDATE:
1205         {
1206             OUString aText( m_aTextEditField.GetText() );
1207             double fDateValue=0.0;
1208             bChangeValid = sal_False;
1209             if( isDateString( aText, fDateValue ) )
1210                 bChangeValid = m_apDataBrowserModel->setCellAny( nCol, nRow, uno::makeAny( fDateValue ) );
1211             if(!bChangeValid)
1212                 bChangeValid = m_apDataBrowserModel->setCellAny( nCol, nRow, uno::makeAny( aText ) );
1213         }
1214         break;
1215         case DataBrowserModel::TEXT:
1216         {
1217             OUString aText( m_aTextEditField.GetText());
1218             bChangeValid = m_apDataBrowserModel->setCellText( nCol, nRow, aText );
1219         }
1220         break;
1221     }
1222 
1223     // the first valid change changes this to true
1224     if( bChangeValid )
1225     {
1226         RowModified( GetCurRow(), GetCurColumnId());
1227         ::svt::CellController* pCtrl = GetController( GetCurRow(), GetCurColumnId());
1228         if( pCtrl )
1229             pCtrl->ClearModified();
1230         SetDirty();
1231     }
1232 
1233     return bChangeValid;
1234 }
1235 
1236 bool DataBrowser::EndEditing()
1237 {
1238     if( IsModified())
1239         SaveModified();
1240 
1241     // apply changes made to series headers
1242     ::std::for_each( m_aSeriesHeaders.begin(), m_aSeriesHeaders.end(), impl::applyChangesFunctor());
1243 
1244     if( m_bDataValid )
1245         return true;
1246     else
1247         return ShowQueryBox();
1248 }
1249 
1250 sal_Int16 DataBrowser::GetFirstVisibleColumNumber() const
1251 {
1252     return GetFirstVisibleColNumber();
1253 }
1254 
1255 void DataBrowser::ColumnResized( sal_uInt16 nColId )
1256 {
1257     sal_Bool bLastUpdateMode = GetUpdateMode();
1258 	SetUpdateMode( sal_False );
1259 
1260     EditBrowseBox::ColumnResized( nColId );
1261     ImplAdjustHeaderControls();
1262     SetUpdateMode( bLastUpdateMode );
1263 }
1264 
1265 // 	virtual void    MouseMove( const MouseEvent& rEvt );
1266 
1267 void DataBrowser::EndScroll()
1268 {
1269     sal_Bool bLastUpdateMode = GetUpdateMode();
1270 	SetUpdateMode( sal_False );
1271 
1272     EditBrowseBox::EndScroll();
1273     RenewSeriesHeaders();
1274 
1275     SetUpdateMode( bLastUpdateMode );
1276 }
1277 
1278 void DataBrowser::RenewSeriesHeaders()
1279 {
1280     Window * pWin = this->GetParent();
1281     if( !pWin )
1282         pWin = this;
1283 
1284     clearHeaders();
1285     DataBrowserModel::tDataHeaderVector aHeaders( m_apDataBrowserModel->getDataHeaders());
1286     Link aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus ));
1287     Link aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged ));
1288     bool bIsHighContrast = pWin ? (pWin->GetSettings().GetStyleSettings().GetHighContrastMode()) : false;
1289 
1290     for( DataBrowserModel::tDataHeaderVector::const_iterator aIt( aHeaders.begin());
1291          aIt != aHeaders.end(); ++aIt )
1292     {
1293         ::boost::shared_ptr< impl::SeriesHeader > spHeader( new impl::SeriesHeader( pWin ));
1294         Reference< beans::XPropertySet > xSeriesProp( aIt->m_xDataSeries, uno::UNO_QUERY );
1295         sal_Int32 nColor = 0;
1296         if( xSeriesProp.is() &&
1297             ( xSeriesProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Color"))) >>= nColor ))
1298             spHeader->SetColor( Color( nColor ));
1299         spHeader->SetChartType( aIt->m_xChartType, aIt->m_bSwapXAndYAxis, bIsHighContrast );
1300         spHeader->SetSeriesName(
1301             String( DataSeriesHelper::getDataSeriesLabel(
1302                         aIt->m_xDataSeries,
1303                         (aIt->m_xChartType.is() ?
1304                          aIt->m_xChartType->getRoleOfSequenceForSeriesLabel() :
1305                          OUString( RTL_CONSTASCII_USTRINGPARAM("values-y"))))));
1306         spHeader->SetRange( aIt->m_nStartColumn + 1, aIt->m_nEndColumn + 1 );
1307         spHeader->SetGetFocusHdl( aFocusLink );
1308         spHeader->SetEditChangedHdl( aSeriesHeaderChangedLink );
1309         m_aSeriesHeaders.push_back( spHeader );
1310     }
1311 
1312     ImplAdjustHeaderControls();
1313 }
1314 
1315 void DataBrowser::ImplAdjustHeaderControls()
1316 {
1317     sal_uInt16 nColCount = this->GetColumnCount();
1318     sal_uInt32 nCurrentPos = this->GetPosPixel().getX();
1319     sal_uInt32 nMaxPos = nCurrentPos + this->GetOutputSizePixel().getWidth();
1320     sal_uInt32 nStartPos = nCurrentPos;
1321 
1322     // width of header column
1323     nCurrentPos +=  this->GetColumnWidth( 0 );
1324     tSeriesHeaderContainer::iterator aIt( m_aSeriesHeaders.begin());
1325     sal_uInt16 i = this->GetFirstVisibleColumNumber();
1326     while( (aIt != m_aSeriesHeaders.end()) && ((*aIt)->GetStartColumn() < i) )
1327         ++aIt;
1328     for( ; i < nColCount && aIt != m_aSeriesHeaders.end(); ++i )
1329     {
1330         if( (*aIt)->GetStartColumn() == i )
1331             nStartPos = nCurrentPos;
1332 
1333         nCurrentPos += (this->GetColumnWidth( i ));
1334 
1335         if( (*aIt)->GetEndColumn() == i )
1336         {
1337             if( nStartPos < nMaxPos )
1338             {
1339                 (*aIt)->SetPixelPosX( nStartPos + 2 );
1340                 (*aIt)->SetPixelWidth( nCurrentPos - nStartPos - 3 );
1341             }
1342             else
1343                 // do not hide, to get focus events. Move outside the dialog for "hiding"
1344                 (*aIt)->SetPixelPosX( nMaxPos + 42 );
1345             ++aIt;
1346         }
1347     }
1348 }
1349 
1350 IMPL_LINK( DataBrowser, SeriesHeaderGotFocus, impl::SeriesHeaderEdit*, pEdit )
1351 {
1352     if( pEdit )
1353     {
1354         pEdit->SetShowWarningBox( !m_bDataValid );
1355 
1356         if( !m_bDataValid )
1357             GoToCell( 0, 0 );
1358         else
1359         {
1360             //DeactivateCell();
1361             MakeFieldVisible( GetCurRow(), static_cast< sal_uInt16 >( pEdit->getStartColumn()), true /* bComplete */ );
1362             ActivateCell();
1363             m_aCursorMovedHdlLink.Call( this );
1364         }
1365     }
1366     return 0;
1367 }
1368 
1369 IMPL_LINK( DataBrowser, SeriesHeaderChanged, impl::SeriesHeaderEdit*, pEdit )
1370 {
1371     if( pEdit )
1372     {
1373         Reference< chart2::XDataSeries > xSeries(
1374             m_apDataBrowserModel->getDataSeriesByColumn( pEdit->getStartColumn() - 1 ));
1375         Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
1376         if( xSource.is())
1377         {
1378             Reference< chart2::XChartType > xChartType(
1379                 m_apDataBrowserModel->getHeaderForSeries( xSeries ).m_xChartType );
1380             if( xChartType.is())
1381             {
1382                 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
1383                     DataSeriesHelper::getDataSequenceByRole( xSource, xChartType->getRoleOfSequenceForSeriesLabel()));
1384                 if( xLabeledSeq.is())
1385                 {
1386                     Reference< container::XIndexReplace > xIndexReplace( xLabeledSeq->getLabel(), uno::UNO_QUERY );
1387                     if( xIndexReplace.is())
1388                         xIndexReplace->replaceByIndex(
1389                             0, uno::makeAny( OUString( pEdit->GetText())));
1390                 }
1391             }
1392         }
1393     }
1394     return 0;
1395 }
1396 
1397 sal_Int32 DataBrowser::GetTotalWidth() const
1398 {
1399     sal_uLong nWidth = 0;
1400 	for ( sal_uInt16 nCol = 0; nCol < ColCount(); ++nCol )
1401 		nWidth += GetColumnWidth( nCol );
1402 	return static_cast< sal_Int32 >( nWidth );
1403 }
1404 
1405 } // namespace chart
1406