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