xref: /trunk/main/chart2/source/controller/dialogs/DataBrowser.cxx (revision e8df90a080f9dc7518c4b937d7dcd461d7b4d178)
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_chartcontroller.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 {
lcl_getRowInData(long nRow)100 sal_Int32 lcl_getRowInData( long nRow )
101 {
102     return static_cast< sal_Int32 >( nRow );
103 }
104 
lcl_getColumnInData(sal_uInt16 nCol)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 
SeriesHeaderEdit(Window * pParent)137 SeriesHeaderEdit::SeriesHeaderEdit( Window * pParent ) :
138         Edit( pParent ),
139         m_nStartColumn( 0 ),
140         m_bShowWarningBox( false )
141 {}
~SeriesHeaderEdit()142 SeriesHeaderEdit::~SeriesHeaderEdit()
143 {}
144 
setStartColumn(sal_Int32 nStartColumn)145 void SeriesHeaderEdit::setStartColumn( sal_Int32 nStartColumn )
146 {
147     m_nStartColumn = nStartColumn;
148 }
149 
getStartColumn() const150 sal_Int32 SeriesHeaderEdit::getStartColumn() const
151 {
152     return m_nStartColumn;
153 }
154 
SetShowWarningBox(bool bShowWarning)155 void SeriesHeaderEdit::SetShowWarningBox( bool bShowWarning )
156 {
157     m_bShowWarningBox = bShowWarning;
158 }
159 
MouseButtonDown(const MouseEvent & rMEvt)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 
SeriesHeader(Window * pParent)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 
notifyChanges()245 void SeriesHeader::notifyChanges()
246 {
247     if( m_aChangeLink.IsSet())
248         m_aChangeLink.Call( m_spSeriesName.get());
249 
250     m_bSeriesNameChangePending = false;
251 }
252 
applyChanges()253 void SeriesHeader::applyChanges()
254 {
255     if( m_bSeriesNameChangePending )
256     {
257         notifyChanges();
258     }
259 }
260 
SetColor(const Color & rCol)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 
GetRelativeAppFontXPosForNameField()269 sal_Int32 SeriesHeader::GetRelativeAppFontXPosForNameField()
270 {
271     return nSymbolHeight + nSymbolDistance;
272 }
273 
SetPos(const Point & rPos)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 
SetWidth(sal_Int32 nWidth)304 void SeriesHeader::SetWidth( sal_Int32 nWidth )
305 {
306     m_nWidth = nWidth;
307     SetPos( m_aPos );
308 }
309 
310 
SetPixelPosX(sal_Int32 nPos)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 
SetPixelWidth(sal_Int32 nWidth)318 void SeriesHeader::SetPixelWidth( sal_Int32 nWidth )
319 {
320     SetWidth( m_pDevice->PixelToLogic( Size( nWidth, 0 ), MAP_APPFONT ).getWidth());
321 }
322 
SetChartType(const Reference<chart2::XChartType> & xChartType,bool bSwapXAndYAxis,bool bIsHighContrast)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 
SetSeriesName(const String & rName)331 void SeriesHeader::SetSeriesName( const String & rName )
332 {
333     m_spSeriesName->SetText( rName );
334 }
335 
SetRange(sal_Int32 nStartCol,sal_Int32 nEndCol)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 
GetStartColumn() const343 sal_Int32 SeriesHeader::GetStartColumn() const
344 {
345     return m_nStartCol;
346 }
347 
GetEndColumn() const348 sal_Int32 SeriesHeader::GetEndColumn() const
349 {
350     return m_nEndCol;
351 }
352 
Show()353 void SeriesHeader::Show()
354 {
355     m_spSymbol->Show();
356     m_spSeriesName->Show();
357     m_spColorBar->Show();
358 }
359 
SetEditChangedHdl(const Link & rLink)360 void SeriesHeader::SetEditChangedHdl( const Link & rLink )
361 {
362     m_aChangeLink = rLink;
363 }
364 
IMPL_LINK(SeriesHeader,SeriesNameChanged,void *,EMPTYARG)365 IMPL_LINK( SeriesHeader, SeriesNameChanged, void * , EMPTYARG )
366 {
367     notifyChanges();
368     return 0;
369 }
370 
IMPL_LINK(SeriesHeader,SeriesNameEdited,void *,EMPTYARG)371 IMPL_LINK( SeriesHeader, SeriesNameEdited, void * , EMPTYARG )
372 {
373     m_bSeriesNameChangePending = true;
374     return 0;
375 }
376 
SetGetFocusHdl(const Link & rLink)377 void SeriesHeader::SetGetFocusHdl( const Link& rLink )
378 {
379     m_spSeriesName->SetGetFocusHdl( rLink );
380 }
381 
HasFocus() const382 bool SeriesHeader::HasFocus() const
383 {
384     return m_spSeriesName->HasFocus();
385 }
386 
GetChartTypeImage(const Reference<chart2::XChartType> & xChartType,bool bSwapXAndYAxis,bool bHC)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
439 {
440     typedef ::boost::shared_ptr< SeriesHeader > argument_type;
441     typedef void result_type;
operator ()chart::impl::applyChangesFunctor442     void operator() ( ::boost::shared_ptr< SeriesHeader > spHeader )
443     {
444         spHeader->applyChanges();
445     }
446 };
447 
448 } // namespace impl
449 // ----------------------------------------
450 
451 namespace
452 {
453 
454 /** returns false, if no header as the focus.
455 
456     If a header has the focus, true is returned and the index of the header
457     with focus is set at pIndex if pOutIndex is not 0.
458 */
lcl_SeriesHeaderHasFocus(const::std::vector<::boost::shared_ptr<::chart::impl::SeriesHeader>> & rSeriesHeader,sal_Int32 * pOutIndex=0)459 bool lcl_SeriesHeaderHasFocus(
460     const ::std::vector< ::boost::shared_ptr< ::chart::impl::SeriesHeader > > & rSeriesHeader,
461     sal_Int32 * pOutIndex = 0 )
462 {
463     sal_Int32 nIndex = 0;
464     for( ::std::vector< ::boost::shared_ptr< ::chart::impl::SeriesHeader > >::const_iterator aIt( rSeriesHeader.begin());
465          aIt != rSeriesHeader.end(); ++aIt, ++nIndex )
466     {
467         if( (*aIt)->HasFocus())
468         {
469             if( pOutIndex )
470                 *pOutIndex = nIndex;
471             return true;
472         }
473     }
474     return false;
475 }
476 
lcl_getColumnInDataOrHeader(sal_uInt16 nCol,const::std::vector<::boost::shared_ptr<::chart::impl::SeriesHeader>> & rSeriesHeader)477 sal_Int32 lcl_getColumnInDataOrHeader(
478     sal_uInt16 nCol, const ::std::vector< ::boost::shared_ptr< ::chart::impl::SeriesHeader > > & rSeriesHeader )
479 {
480     sal_Int32 nColIdx = 0;
481     bool bHeaderHasFocus( lcl_SeriesHeaderHasFocus( rSeriesHeader, &nColIdx ));
482 
483     if( bHeaderHasFocus )
484         nColIdx = lcl_getColumnInData( static_cast< sal_uInt16 >( rSeriesHeader[nColIdx]->GetStartColumn()));
485     else
486         nColIdx = lcl_getColumnInData( nCol );
487 
488     return nColIdx;
489 }
490 
491 } // anonymous namespace
492 
493 
DataBrowser(Window * pParent,const ResId & rId,bool bLiveUpdate)494 DataBrowser::DataBrowser( Window* pParent, const ResId& rId, bool bLiveUpdate ) :
495     ::svt::EditBrowseBox( pParent, rId, EBBF_SMART_TAB_TRAVEL | EBBF_HANDLE_COLUMN_TEXT, BROWSER_STANDARD_FLAGS ),
496     m_nSeekRow( 0 ),
497     m_bIsReadOnly( false ),
498     m_bIsDirty( false ),
499     m_bLiveUpdate( bLiveUpdate ),
500     m_bDataValid( true ),
501     m_aNumberEditField( & EditBrowseBox::GetDataWindow(), WB_NOBORDER ),
502     m_aTextEditField( & EditBrowseBox::GetDataWindow(), WB_NOBORDER ),
503     m_rNumberEditController( new ::svt::FormattedFieldCellController( & m_aNumberEditField )),
504     m_rTextEditController( new ::svt::EditCellController( & m_aTextEditField ))
505 {
506     double fNan;
507     ::rtl::math::setNan( & fNan );
508     m_aNumberEditField.SetDefaultValue( fNan );
509     m_aNumberEditField.TreatAsNumber( sal_True );
510     RenewTable();
511     SetClean();
512 }
513 
~DataBrowser()514 DataBrowser::~DataBrowser()
515 {
516 }
517 
MayInsertRow() const518 bool DataBrowser::MayInsertRow() const
519 {
520     return ! IsReadOnly()
521         && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ));
522 }
523 
MayInsertColumn() const524 bool DataBrowser::MayInsertColumn() const
525 {
526     return ! IsReadOnly();
527 }
528 
MayDeleteRow() const529 bool DataBrowser::MayDeleteRow() const
530 {
531     return ! IsReadOnly()
532         && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
533         && ( GetCurRow() >= 0 )
534         && ( GetRowCount() > 1 );
535 }
536 
MayDeleteColumn() const537 bool DataBrowser::MayDeleteColumn() const
538 {
539     // if a series header has the focus
540     if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
541         return true;
542 
543     return ! IsReadOnly()
544         && ( GetCurColumnId() > 1 )
545         && ( ColCount() > 2 );
546 }
547 
MaySwapRows() const548 bool DataBrowser::MaySwapRows() const
549 {
550     return ! IsReadOnly()
551         && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
552         && ( GetCurRow() >= 0 )
553         && ( GetCurRow() < GetRowCount() - 1 );
554 }
555 
MaySwapColumns() const556 bool DataBrowser::MaySwapColumns() const
557 {
558     // if a series header (except the last one) has the focus
559     {
560         sal_Int32 nColIndex(0);
561         if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders, &nColIndex ))
562             return (static_cast< sal_uInt32 >( nColIndex ) < (m_aSeriesHeaders.size() - 1));
563     }
564 
565     sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
566     return ! IsReadOnly()
567         && ( nColIdx > 0 )
568         && ( nColIdx < ColCount()-2 )
569         && m_apDataBrowserModel.get()
570         && !m_apDataBrowserModel->isCategoriesColumn( nColIdx );
571 }
572 
clearHeaders()573 void DataBrowser::clearHeaders()
574 {
575     ::std::for_each( m_aSeriesHeaders.begin(), m_aSeriesHeaders.end(), impl::applyChangesFunctor());
576     m_aSeriesHeaders.clear();
577 }
578 
RenewTable()579 void DataBrowser::RenewTable()
580 {
581     if( ! m_apDataBrowserModel.get())
582         return;
583 
584     long   nOldRow     = GetCurRow();
585     sal_uInt16 nOldColId   = GetCurColumnId();
586 
587     sal_Bool bLastUpdateMode = GetUpdateMode();
588     SetUpdateMode( sal_False );
589 
590     if( IsModified() )
591         SaveModified();
592 
593     DeactivateCell();
594 
595     RemoveColumns();
596     RowRemoved( 1, GetRowCount() );
597 
598     // for row numbers
599     InsertHandleColumn( static_cast< sal_uInt16 >(
600                             GetDataWindow().LogicToPixel( Size( 42, 0 )).getWidth() ));
601 
602     OUString aDefaultSeriesName( ::chart::SchResId::getResString( STR_COLUMN_LABEL ));
603     replaceParamterInString( aDefaultSeriesName, C2U("%COLUMNNUMBER"), OUString::valueOf( sal_Int32(24) ) );
604     sal_Int32 nColumnWidth = GetDataWindow().GetTextWidth( aDefaultSeriesName )
605         + GetDataWindow().LogicToPixel( Point( 4 + impl::SeriesHeader::GetRelativeAppFontXPosForNameField(), 0 ), MAP_APPFONT ).X();
606     sal_Int32 nColumnCount = m_apDataBrowserModel->getColumnCount();
607     // nRowCount is a member of a base class
608     sal_Int32 nRowCountLocal = m_apDataBrowserModel->getMaxRowCount();
609     for( sal_Int32 nColIdx=1; nColIdx<=nColumnCount; ++nColIdx )
610     {
611         InsertDataColumn( static_cast< sal_uInt16 >( nColIdx ), GetColString( nColIdx ), nColumnWidth );
612     }
613 
614     RowInserted( 1, nRowCountLocal );
615     GoToRow( ::std::min( nOldRow, GetRowCount() - 1 ));
616     GoToColumnId( ::std::min( nOldColId, static_cast< sal_uInt16 >( ColCount() - 1 )));
617 
618     Window * pWin = this->GetParent();
619     if( !pWin )
620         pWin = this;
621 
622     // fill series headers
623     clearHeaders();
624     const DataBrowserModel::tDataHeaderVector& aHeaders( m_apDataBrowserModel->getDataHeaders());
625     Link aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus ));
626     Link aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged ));
627     bool bIsHighContrast = pWin ? (pWin->GetSettings().GetStyleSettings().GetHighContrastMode()) : false;
628 
629     for( DataBrowserModel::tDataHeaderVector::const_iterator aIt( aHeaders.begin());
630          aIt != aHeaders.end(); ++aIt )
631     {
632         ::boost::shared_ptr< impl::SeriesHeader > spHeader( new impl::SeriesHeader( pWin ));
633         Reference< beans::XPropertySet > xSeriesProp( aIt->m_xDataSeries, uno::UNO_QUERY );
634         sal_Int32 nColor = 0;
635         // @todo: Set "DraftColor", i.e. interpolated colors for gradients, bitmaps, etc.
636         if( xSeriesProp.is() &&
637             ( xSeriesProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Color"))) >>= nColor ))
638             spHeader->SetColor( Color( nColor ));
639         spHeader->SetChartType( aIt->m_xChartType, aIt->m_bSwapXAndYAxis, bIsHighContrast );
640         spHeader->SetSeriesName(
641             String( DataSeriesHelper::getDataSeriesLabel(
642                         aIt->m_xDataSeries,
643                         (aIt->m_xChartType.is() ?
644                          aIt->m_xChartType->getRoleOfSequenceForSeriesLabel() :
645                          OUString( RTL_CONSTASCII_USTRINGPARAM("values-y"))))));
646         // index is 1-based, as 0 is for the column that contains the row-numbers
647         spHeader->SetRange( aIt->m_nStartColumn + 1, aIt->m_nEndColumn + 1 );
648         spHeader->SetGetFocusHdl( aFocusLink );
649         spHeader->SetEditChangedHdl( aSeriesHeaderChangedLink );
650         m_aSeriesHeaders.push_back( spHeader );
651     }
652 
653     ImplAdjustHeaderControls();
654     SetDirty();
655     SetUpdateMode( bLastUpdateMode );
656     ActivateCell();
657     Invalidate();
658 }
659 
GetColString(sal_Int32 nColumnId) const660 String DataBrowser::GetColString( sal_Int32 nColumnId ) const
661 {
662     OSL_ASSERT( m_apDataBrowserModel.get());
663     if( nColumnId > 0 )
664         return String( m_apDataBrowserModel->getRoleOfColumn( static_cast< sal_Int32 >( nColumnId ) - 1 ));
665     return String();
666 }
667 
GetRowString(sal_Int32 nRow) const668 String DataBrowser::GetRowString( sal_Int32 nRow ) const
669 {
670     return String::CreateFromInt32( nRow + 1 );
671 }
672 
GetCellText(long nRow,sal_uInt16 nColumnId) const673 String DataBrowser::GetCellText( long nRow, sal_uInt16 nColumnId ) const
674 {
675     String aResult;
676 
677     if( nColumnId == 0 )
678     {
679         aResult = GetRowString( static_cast< sal_Int32 >( nRow ));
680     }
681     else if( nRow >= 0 &&
682              m_apDataBrowserModel.get())
683     {
684         sal_Int32 nColIndex = static_cast< sal_Int32 >( nColumnId ) - 1;
685 
686         if( m_apDataBrowserModel->getCellType( nColIndex, nRow ) == DataBrowserModel::NUMBER )
687         {
688             double fData( m_apDataBrowserModel->getCellNumber( nColIndex, nRow ));
689             sal_Int32 nLabelColor;
690             bool bColorChanged = false;
691 
692             if( ! ::rtl::math::isNan( fData ) &&
693                 m_spNumberFormatterWrapper.get() )
694                 aResult = String( m_spNumberFormatterWrapper->getFormattedString(
695                                       GetNumberFormatKey( nRow, nColumnId ),
696                                       fData, nLabelColor, bColorChanged ));
697         }
698         else if( m_apDataBrowserModel->getCellType( nColIndex, nRow ) == DataBrowserModel::TEXTORDATE )
699         {
700             uno::Any aAny = m_apDataBrowserModel->getCellAny( nColIndex, nRow );
701             OUString aText;
702             double fDouble=0.0;
703             if( aAny>>=aText )
704                 aResult = aText;
705             else if( aAny>>=fDouble )
706             {
707                 sal_Int32 nLabelColor;
708                 bool bColorChanged = false;
709                 sal_Int32 nDateNumberFormat = DiagramHelper::getDateNumberFormat( Reference< util::XNumberFormatsSupplier >( m_xChartDoc, uno::UNO_QUERY) );
710                 if( ! ::rtl::math::isNan( fDouble ) && m_spNumberFormatterWrapper.get() )
711                     aResult = String( m_spNumberFormatterWrapper->getFormattedString(
712                         nDateNumberFormat, fDouble, nLabelColor, bColorChanged ));
713             }
714         }
715         else
716         {
717             OSL_ASSERT( m_apDataBrowserModel->getCellType( nColIndex, nRow ) == DataBrowserModel::TEXT );
718             aResult = m_apDataBrowserModel->getCellText( nColIndex, nRow );
719         }
720     }
721 
722     return aResult;
723 }
724 
GetCellNumber(long nRow,sal_uInt16 nColumnId) const725 double DataBrowser::GetCellNumber( long nRow, sal_uInt16 nColumnId ) const
726 {
727     double fResult;
728     ::rtl::math::setNan( & fResult );
729 
730     if(( nColumnId >= 1 ) && ( nRow >= 0 ) &&
731         m_apDataBrowserModel.get())
732     {
733         fResult = m_apDataBrowserModel->getCellNumber(
734             static_cast< sal_Int32 >( nColumnId ) - 1, nRow );
735     }
736 
737     return fResult;
738 }
739 
Resize()740 void DataBrowser::Resize()
741 {
742     sal_Bool bLastUpdateMode = GetUpdateMode();
743     SetUpdateMode( sal_False );
744 
745     ::svt::EditBrowseBox::Resize();
746     ImplAdjustHeaderControls();
747     SetUpdateMode( bLastUpdateMode );
748 }
749 
SetReadOnly(bool bNewState)750 bool DataBrowser::SetReadOnly( bool bNewState )
751 {
752     bool bResult = m_bIsReadOnly;
753 
754     if( m_bIsReadOnly != bNewState )
755     {
756         m_bIsReadOnly = bNewState;
757         Invalidate();
758         DeactivateCell();
759     }
760 
761     return bResult;
762 }
763 
IsReadOnly() const764 bool DataBrowser::IsReadOnly() const
765 {
766     return m_bIsReadOnly;
767 }
768 
769 
SetClean()770 void DataBrowser::SetClean()
771 {
772     m_bIsDirty = false;
773 }
774 
SetDirty()775 void DataBrowser::SetDirty()
776 {
777     if( !m_bLiveUpdate )
778         m_bIsDirty = true;
779 }
780 
CursorMoved()781 void DataBrowser::CursorMoved()
782 {
783     EditBrowseBox::CursorMoved();
784 
785     if( GetUpdateMode() && m_aCursorMovedHdlLink.IsSet())
786         m_aCursorMovedHdlLink.Call( this );
787 }
788 
SetCellModifiedHdl(const Link & rLink)789 void DataBrowser::SetCellModifiedHdl( const Link& rLink )
790 {
791     m_aCellModifiedLink = rLink;
792 }
793 
MouseButtonDown(const BrowserMouseEvent & rEvt)794 void DataBrowser::MouseButtonDown( const BrowserMouseEvent& rEvt )
795 {
796     if( !m_bDataValid )
797         ShowWarningBox();
798     else
799         EditBrowseBox::MouseButtonDown( rEvt );
800 }
801 
ShowWarningBox()802 void DataBrowser::ShowWarningBox()
803 {
804     WarningBox( this, WinBits( WB_OK ),
805                 String( SchResId( STR_INVALID_NUMBER ))).Execute();
806 }
807 
ShowQueryBox()808 bool DataBrowser::ShowQueryBox()
809 {
810     QueryBox* pQueryBox = new QueryBox( this, WB_YES_NO, String( SchResId( STR_DATA_EDITOR_INCORRECT_INPUT )));
811 
812     return ( pQueryBox->Execute() == RET_YES );
813 }
814 
IsDataValid()815 bool DataBrowser::IsDataValid()
816 {
817     bool bValid = true;
818     const sal_Int32 nRow = lcl_getRowInData( GetCurRow());
819     const sal_Int32 nCol = lcl_getColumnInData( GetCurColumnId());
820 
821     if( m_apDataBrowserModel->getCellType( nCol, nRow ) == DataBrowserModel::NUMBER )
822     {
823         sal_uInt32 nDummy = 0;
824         double fDummy = 0.0;
825         String aText( m_aNumberEditField.GetText());
826 
827         if( aText.Len() > 0 &&
828             m_spNumberFormatterWrapper.get() &&
829             m_spNumberFormatterWrapper->getSvNumberFormatter() &&
830             ! m_spNumberFormatterWrapper->getSvNumberFormatter()->IsNumberFormat(
831               aText, nDummy, fDummy ))
832         {
833             bValid = false;
834         }
835     }
836 
837     return bValid;
838 }
839 
IsEnableItem()840 bool DataBrowser::IsEnableItem()
841 {
842     return m_bDataValid;
843 }
844 
CellModified()845 void DataBrowser::CellModified()
846 {
847     m_bDataValid = IsDataValid();
848     SetDirty();
849     if( m_aCellModifiedLink.IsSet())
850         m_aCursorMovedHdlLink.Call( this );
851 }
852 
SetDataFromModel(const Reference<chart2::XChartDocument> & xChartDoc,const Reference<uno::XComponentContext> & xContext)853 void DataBrowser::SetDataFromModel(
854     const Reference< chart2::XChartDocument > & xChartDoc,
855     const Reference< uno::XComponentContext > & xContext )
856 {
857     if( m_bLiveUpdate )
858     {
859         m_xChartDoc.set( xChartDoc );
860     }
861     else
862     {
863         Reference< util::XCloneable > xCloneable( xChartDoc, uno::UNO_QUERY );
864         if( xCloneable.is())
865             m_xChartDoc.set( xCloneable->createClone(), uno::UNO_QUERY );
866     }
867 
868     m_apDataBrowserModel.reset( new DataBrowserModel( m_xChartDoc, xContext ));
869     m_spNumberFormatterWrapper.reset(
870         new NumberFormatterWrapper(
871             Reference< util::XNumberFormatsSupplier >( m_xChartDoc, uno::UNO_QUERY )));
872 
873     if( m_spNumberFormatterWrapper.get() )
874         m_aNumberEditField.SetFormatter( m_spNumberFormatterWrapper->getSvNumberFormatter() );
875 
876     RenewTable();
877 
878     const sal_Int32 nColCnt  = m_apDataBrowserModel->getColumnCount();
879     const sal_Int32 nRowCnt =  m_apDataBrowserModel->getMaxRowCount();
880     if( nRowCnt && nColCnt )
881     {
882         GoToRow( 0 );
883         GoToColumnId( 1 );
884     }
885     SetClean();
886 }
887 
InsertColumn()888 void DataBrowser::InsertColumn()
889 {
890     sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
891 
892     if( nColIdx >= 0 &&
893         m_apDataBrowserModel.get())
894     {
895         // save changes made to edit-field
896         if( IsModified() )
897             SaveModified();
898 
899         m_apDataBrowserModel->insertDataSeries( nColIdx );
900         RenewTable();
901     }
902 }
903 
InsertTextColumn()904 void DataBrowser::InsertTextColumn()
905 {
906     sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
907 
908     if( nColIdx >= 0 &&
909         m_apDataBrowserModel.get())
910     {
911         // save changes made to edit-field
912         if( IsModified() )
913             SaveModified();
914 
915         m_apDataBrowserModel->insertComplexCategoryLevel( nColIdx );
916         RenewTable();
917     }
918 }
919 
RemoveColumn()920 void DataBrowser::RemoveColumn()
921 {
922     sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
923 
924     if( nColIdx >= 0 &&
925         m_apDataBrowserModel.get())
926     {
927         // save changes made to edit-field
928         if( IsModified() )
929             SaveModified();
930 
931         m_bDataValid = true;
932         m_apDataBrowserModel->removeDataSeriesOrComplexCategoryLevel( nColIdx );
933         RenewTable();
934     }
935 }
936 
InsertRow()937 void DataBrowser::InsertRow()
938 {
939     sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow());
940 
941     if( nRowIdx >= 0 &&
942         m_apDataBrowserModel.get())
943     {
944         // save changes made to edit-field
945         if( IsModified() )
946             SaveModified();
947 
948         m_apDataBrowserModel->insertDataPointForAllSeries( nRowIdx );
949         RenewTable();
950     }
951 }
952 
RemoveRow()953 void DataBrowser::RemoveRow()
954 {
955     sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow());
956 
957     if( nRowIdx >= 0 &&
958         m_apDataBrowserModel.get())
959     {
960         // save changes made to edit-field
961         if( IsModified() )
962             SaveModified();
963 
964         m_bDataValid = true;
965         m_apDataBrowserModel->removeDataPointForAllSeries( nRowIdx );
966         RenewTable();
967     }
968 }
969 
SwapColumn()970 void DataBrowser::SwapColumn()
971 {
972     sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
973 
974     if( nColIdx >= 0 &&
975         m_apDataBrowserModel.get())
976     {
977         // save changes made to edit-field
978         if( IsModified() )
979             SaveModified();
980 
981         m_apDataBrowserModel->swapDataSeries( nColIdx );
982 
983         // keep cursor in swapped column
984         if( GetCurColumnId() < ColCount() - 1 )
985         {
986             Dispatch( BROWSER_CURSORRIGHT );
987         }
988         RenewTable();
989     }
990 }
991 
SwapRow()992 void DataBrowser::SwapRow()
993 {
994     sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow());
995 
996     if( nRowIdx >= 0 &&
997         m_apDataBrowserModel.get())
998     {
999         // save changes made to edit-field
1000         if( IsModified() )
1001             SaveModified();
1002 
1003         m_apDataBrowserModel->swapDataPointForAllSeries( nRowIdx );
1004 
1005         // keep cursor in swapped row
1006         if( GetCurRow() < GetRowCount() - 1 )
1007         {
1008             Dispatch( BROWSER_CURSORDOWN );
1009         }
1010         RenewTable();
1011     }
1012 }
1013 
SetCursorMovedHdl(const Link & rLink)1014 void DataBrowser::SetCursorMovedHdl( const Link& rLink )
1015 {
1016     m_aCursorMovedHdlLink = rLink;
1017 }
1018 
1019 // implementations for ::svt::EditBrowseBox (pure virtual methods)
PaintCell(OutputDevice & rDev,const Rectangle & rRect,sal_uInt16 nColumnId) const1020 void DataBrowser::PaintCell(
1021     OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId ) const
1022 {
1023     Point aPos( rRect.TopLeft());
1024     aPos.X() += 1;
1025 
1026     String aText = GetCellText( m_nSeekRow, nColumnId );
1027     Size TxtSize( GetDataWindow().GetTextWidth( aText ), GetDataWindow().GetTextHeight());
1028 
1029     // clipping
1030     if( aPos.X() < rRect.Right() || aPos.X() + TxtSize.Width() > rRect.Right() ||
1031         aPos.Y() < rRect.Top() || aPos.Y() + TxtSize.Height() > rRect.Bottom())
1032         rDev.SetClipRegion( rRect );
1033 
1034     // allow for a disabled control ...
1035     sal_Bool bEnabled = IsEnabled();
1036     Color aOriginalColor = rDev.GetTextColor();
1037     if( ! bEnabled )
1038         rDev.SetTextColor( GetSettings().GetStyleSettings().GetDisableColor() );
1039 
1040     // TEST
1041 //     if( nColumnId == 1 )
1042 //         // categories
1043 //         rDev.SetFillColor( Color( 0xff, 0xff, 0xff ));
1044 //     else if( nColumnId == 2 )
1045 //         // x-values
1046 //         rDev.SetFillColor( Color( 0xf0, 0xf0, 0xff ));
1047 //     else
1048 //         // y-values
1049 //         rDev.SetFillColor( Color( 0xff, 0xff, 0xf0 ));
1050 
1051 //     rDev.DrawRect( rRect );
1052 
1053     // draw the text
1054     rDev.DrawText( aPos, aText );
1055 
1056     // reset the color (if necessary)
1057     if( ! bEnabled )
1058         rDev.SetTextColor( aOriginalColor );
1059 
1060     if( rDev.IsClipRegion())
1061         rDev.SetClipRegion();
1062 }
1063 
SeekRow(long nRow)1064 sal_Bool DataBrowser::SeekRow( long nRow )
1065 {
1066     if( ! EditBrowseBox::SeekRow( nRow ))
1067         return sal_False;
1068 
1069     if( nRow < 0 )
1070         m_nSeekRow = - 1;
1071     else
1072         m_nSeekRow = nRow;
1073 
1074     return sal_True;
1075 }
1076 
IsTabAllowed(sal_Bool bForward) const1077 sal_Bool DataBrowser::IsTabAllowed( sal_Bool bForward ) const
1078 {
1079     long nRow = GetCurRow();
1080     long nCol = GetCurColumnId();
1081 
1082     // column 0 is header-column
1083     long nBadCol = bForward
1084         ? GetColumnCount() - 1
1085         : 1;
1086     long nBadRow = bForward
1087         ? GetRowCount() - 1
1088         : 0;
1089 
1090     if( !m_bDataValid )
1091     {
1092         const_cast< DataBrowser* >( this )->ShowWarningBox();
1093         return sal_False;
1094     }
1095 
1096     return ( nRow != nBadRow ||
1097              nCol != nBadCol );
1098 }
1099 
GetController(long nRow,sal_uInt16 nCol)1100 ::svt::CellController* DataBrowser::GetController( long nRow, sal_uInt16 nCol )
1101 {
1102     if( m_bIsReadOnly )
1103         return 0;
1104 
1105     if( CellContainsNumbers( nRow, nCol ))
1106     {
1107         m_aNumberEditField.UseInputStringForFormatting();
1108         m_aNumberEditField.SetFormatKey( GetNumberFormatKey( nRow, nCol ));
1109         return m_rNumberEditController;
1110     }
1111 
1112     return m_rTextEditController;
1113 }
1114 
InitController(::svt::CellControllerRef & rController,long nRow,sal_uInt16 nCol)1115 void DataBrowser::InitController(
1116     ::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol )
1117 {
1118     if( rController == m_rTextEditController )
1119     {
1120         String aText( GetCellText( nRow, nCol ) );
1121         m_aTextEditField.SetText( aText );
1122         m_aTextEditField.SetSelection( Selection( 0, aText.Len() ));
1123     }
1124     else if( rController == m_rNumberEditController )
1125     {
1126         // treat invalid and empty text as Nan
1127         m_aNumberEditField.EnableNotANumber( true );
1128         if( ::rtl::math::isNan( GetCellNumber( nRow, nCol )))
1129             m_aNumberEditField.SetTextValue( String());
1130         else
1131             m_aNumberEditField.SetValue( GetCellNumber( nRow, nCol ) );
1132         String aText( m_aNumberEditField.GetText());
1133         m_aNumberEditField.SetSelection( Selection( 0, aText.Len()));
1134     }
1135     else
1136     {
1137         DBG_ERROR( "Invalid Controller" );
1138     }
1139 }
1140 
CellContainsNumbers(sal_Int32 nRow,sal_uInt16 nCol) const1141 bool DataBrowser::CellContainsNumbers( sal_Int32 nRow, sal_uInt16 nCol ) const
1142 {
1143     if( ! m_apDataBrowserModel.get())
1144         return false;
1145     return (m_apDataBrowserModel->getCellType( lcl_getColumnInData( nCol ), lcl_getRowInData( nRow )) ==
1146             DataBrowserModel::NUMBER);
1147 }
1148 
GetNumberFormatKey(sal_Int32 nRow,sal_uInt16 nCol) const1149 sal_uInt32 DataBrowser::GetNumberFormatKey( sal_Int32 nRow, sal_uInt16 nCol ) const
1150 {
1151     if( ! m_apDataBrowserModel.get())
1152         return 0;
1153     return m_apDataBrowserModel->getNumberFormatKey( lcl_getColumnInData( nCol ), lcl_getRowInData( nRow ));
1154 }
1155 
isDateString(rtl::OUString aInputString,double & fOutDateValue)1156 bool DataBrowser::isDateString( rtl::OUString aInputString, double& fOutDateValue )
1157 {
1158     sal_uInt32 nNumberFormat=0;
1159     SvNumberFormatter* pSvNumberFormatter = m_spNumberFormatterWrapper.get() ? m_spNumberFormatterWrapper->getSvNumberFormatter() : 0;
1160     if( !aInputString.isEmpty() &&  pSvNumberFormatter && pSvNumberFormatter->IsNumberFormat( aInputString, nNumberFormat, fOutDateValue ) )
1161     {
1162         Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( m_xChartDoc, uno::UNO_QUERY );
1163         Reference< util::XNumberFormats > xNumberFormats;
1164         if( xNumberFormatsSupplier.is() )
1165              xNumberFormats = Reference< util::XNumberFormats >( xNumberFormatsSupplier->getNumberFormats() );
1166         if( DiagramHelper::isDateNumberFormat( nNumberFormat, xNumberFormats ) )
1167             return true;
1168     }
1169     return false;
1170 }
1171 
SaveModified()1172 sal_Bool DataBrowser::SaveModified()
1173 {
1174     if( ! IsModified() )
1175         return sal_True;
1176 
1177     sal_Bool bChangeValid = sal_True;
1178 
1179     const sal_Int32 nRow = lcl_getRowInData( GetCurRow());
1180     const sal_Int32 nCol = lcl_getColumnInData( GetCurColumnId());
1181 
1182     DBG_ASSERT( nRow >= 0 || nCol >= 0, "This cell should not be modified!" );
1183 
1184     SvNumberFormatter* pSvNumberFormatter = m_spNumberFormatterWrapper.get() ? m_spNumberFormatterWrapper->getSvNumberFormatter() : 0;
1185     switch( m_apDataBrowserModel->getCellType( nCol, nRow ))
1186     {
1187         case DataBrowserModel::NUMBER:
1188         {
1189             sal_uInt32 nDummy = 0;
1190             double fDummy = 0.0;
1191             String aText( m_aNumberEditField.GetText());
1192             // an empty string is valid, if no numberformatter exists, all
1193             // values are treated as valid
1194             if( aText.Len() > 0 && pSvNumberFormatter &&
1195                 ! pSvNumberFormatter->IsNumberFormat( aText, nDummy, fDummy ) )
1196             {
1197                 bChangeValid = sal_False;
1198             }
1199             else
1200             {
1201                 double fData = m_aNumberEditField.GetValue();
1202                 bChangeValid = m_apDataBrowserModel->setCellNumber( nCol, nRow, fData );
1203             }
1204         }
1205         break;
1206         case DataBrowserModel::TEXTORDATE:
1207         {
1208             OUString aText( m_aTextEditField.GetText() );
1209             double fDateValue=0.0;
1210             bChangeValid = sal_False;
1211             if( isDateString( aText, fDateValue ) )
1212                 bChangeValid = m_apDataBrowserModel->setCellAny( nCol, nRow, uno::makeAny( fDateValue ) );
1213             if(!bChangeValid)
1214                 bChangeValid = m_apDataBrowserModel->setCellAny( nCol, nRow, uno::makeAny( aText ) );
1215         }
1216         break;
1217         case DataBrowserModel::TEXT:
1218         {
1219             OUString aText( m_aTextEditField.GetText());
1220             bChangeValid = m_apDataBrowserModel->setCellText( nCol, nRow, aText );
1221         }
1222         break;
1223     }
1224 
1225     // the first valid change changes this to true
1226     if( bChangeValid )
1227     {
1228         RowModified( GetCurRow(), GetCurColumnId());
1229         ::svt::CellController* pCtrl = GetController( GetCurRow(), GetCurColumnId());
1230         if( pCtrl )
1231             pCtrl->ClearModified();
1232         SetDirty();
1233     }
1234 
1235     return bChangeValid;
1236 }
1237 
EndEditing()1238 bool DataBrowser::EndEditing()
1239 {
1240     if( IsModified())
1241         SaveModified();
1242 
1243     // apply changes made to series headers
1244     ::std::for_each( m_aSeriesHeaders.begin(), m_aSeriesHeaders.end(), impl::applyChangesFunctor());
1245 
1246     if( m_bDataValid )
1247         return true;
1248     else
1249         return ShowQueryBox();
1250 }
1251 
GetFirstVisibleColumNumber() const1252 sal_Int16 DataBrowser::GetFirstVisibleColumNumber() const
1253 {
1254     return GetFirstVisibleColNumber();
1255 }
1256 
ColumnResized(sal_uInt16 nColId)1257 void DataBrowser::ColumnResized( sal_uInt16 nColId )
1258 {
1259     sal_Bool bLastUpdateMode = GetUpdateMode();
1260     SetUpdateMode( sal_False );
1261 
1262     EditBrowseBox::ColumnResized( nColId );
1263     ImplAdjustHeaderControls();
1264     SetUpdateMode( bLastUpdateMode );
1265 }
1266 
1267 //  virtual void    MouseMove( const MouseEvent& rEvt );
1268 
EndScroll()1269 void DataBrowser::EndScroll()
1270 {
1271     sal_Bool bLastUpdateMode = GetUpdateMode();
1272     SetUpdateMode( sal_False );
1273 
1274     EditBrowseBox::EndScroll();
1275     RenewSeriesHeaders();
1276 
1277     SetUpdateMode( bLastUpdateMode );
1278 }
1279 
RenewSeriesHeaders()1280 void DataBrowser::RenewSeriesHeaders()
1281 {
1282     Window * pWin = this->GetParent();
1283     if( !pWin )
1284         pWin = this;
1285 
1286     clearHeaders();
1287     DataBrowserModel::tDataHeaderVector aHeaders( m_apDataBrowserModel->getDataHeaders());
1288     Link aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus ));
1289     Link aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged ));
1290     bool bIsHighContrast = pWin ? (pWin->GetSettings().GetStyleSettings().GetHighContrastMode()) : false;
1291 
1292     for( DataBrowserModel::tDataHeaderVector::const_iterator aIt( aHeaders.begin());
1293          aIt != aHeaders.end(); ++aIt )
1294     {
1295         ::boost::shared_ptr< impl::SeriesHeader > spHeader( new impl::SeriesHeader( pWin ));
1296         Reference< beans::XPropertySet > xSeriesProp( aIt->m_xDataSeries, uno::UNO_QUERY );
1297         sal_Int32 nColor = 0;
1298         if( xSeriesProp.is() &&
1299             ( xSeriesProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Color"))) >>= nColor ))
1300             spHeader->SetColor( Color( nColor ));
1301         spHeader->SetChartType( aIt->m_xChartType, aIt->m_bSwapXAndYAxis, bIsHighContrast );
1302         spHeader->SetSeriesName(
1303             String( DataSeriesHelper::getDataSeriesLabel(
1304                         aIt->m_xDataSeries,
1305                         (aIt->m_xChartType.is() ?
1306                          aIt->m_xChartType->getRoleOfSequenceForSeriesLabel() :
1307                          OUString( RTL_CONSTASCII_USTRINGPARAM("values-y"))))));
1308         spHeader->SetRange( aIt->m_nStartColumn + 1, aIt->m_nEndColumn + 1 );
1309         spHeader->SetGetFocusHdl( aFocusLink );
1310         spHeader->SetEditChangedHdl( aSeriesHeaderChangedLink );
1311         m_aSeriesHeaders.push_back( spHeader );
1312     }
1313 
1314     ImplAdjustHeaderControls();
1315 }
1316 
ImplAdjustHeaderControls()1317 void DataBrowser::ImplAdjustHeaderControls()
1318 {
1319     sal_uInt16 nColCount = this->GetColumnCount();
1320     sal_uInt32 nCurrentPos = this->GetPosPixel().getX();
1321     sal_uInt32 nMaxPos = nCurrentPos + this->GetOutputSizePixel().getWidth();
1322     sal_uInt32 nStartPos = nCurrentPos;
1323 
1324     // width of header column
1325     nCurrentPos +=  this->GetColumnWidth( 0 );
1326     tSeriesHeaderContainer::iterator aIt( m_aSeriesHeaders.begin());
1327     sal_uInt16 i = this->GetFirstVisibleColumNumber();
1328     while( (aIt != m_aSeriesHeaders.end()) && ((*aIt)->GetStartColumn() < i) )
1329         ++aIt;
1330     for( ; i < nColCount && aIt != m_aSeriesHeaders.end(); ++i )
1331     {
1332         if( (*aIt)->GetStartColumn() == i )
1333             nStartPos = nCurrentPos;
1334 
1335         nCurrentPos += (this->GetColumnWidth( i ));
1336 
1337         if( (*aIt)->GetEndColumn() == i )
1338         {
1339             if( nStartPos < nMaxPos )
1340             {
1341                 (*aIt)->SetPixelPosX( nStartPos + 2 );
1342                 (*aIt)->SetPixelWidth( nCurrentPos - nStartPos - 3 );
1343             }
1344             else
1345                 // do not hide, to get focus events. Move outside the dialog for "hiding"
1346                 (*aIt)->SetPixelPosX( nMaxPos + 42 );
1347             ++aIt;
1348         }
1349     }
1350 }
1351 
IMPL_LINK(DataBrowser,SeriesHeaderGotFocus,impl::SeriesHeaderEdit *,pEdit)1352 IMPL_LINK( DataBrowser, SeriesHeaderGotFocus, impl::SeriesHeaderEdit*, pEdit )
1353 {
1354     if( pEdit )
1355     {
1356         pEdit->SetShowWarningBox( !m_bDataValid );
1357 
1358         if( !m_bDataValid )
1359             GoToCell( 0, 0 );
1360         else
1361         {
1362             //DeactivateCell();
1363             MakeFieldVisible( GetCurRow(), static_cast< sal_uInt16 >( pEdit->getStartColumn()), true /* bComplete */ );
1364             ActivateCell();
1365             m_aCursorMovedHdlLink.Call( this );
1366         }
1367     }
1368     return 0;
1369 }
1370 
IMPL_LINK(DataBrowser,SeriesHeaderChanged,impl::SeriesHeaderEdit *,pEdit)1371 IMPL_LINK( DataBrowser, SeriesHeaderChanged, impl::SeriesHeaderEdit*, pEdit )
1372 {
1373     if( pEdit )
1374     {
1375         Reference< chart2::XDataSeries > xSeries(
1376             m_apDataBrowserModel->getDataSeriesByColumn( pEdit->getStartColumn() - 1 ));
1377         Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
1378         if( xSource.is())
1379         {
1380             Reference< chart2::XChartType > xChartType(
1381                 m_apDataBrowserModel->getHeaderForSeries( xSeries ).m_xChartType );
1382             if( xChartType.is())
1383             {
1384                 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
1385                     DataSeriesHelper::getDataSequenceByRole( xSource, xChartType->getRoleOfSequenceForSeriesLabel()));
1386                 if( xLabeledSeq.is())
1387                 {
1388                     Reference< container::XIndexReplace > xIndexReplace( xLabeledSeq->getLabel(), uno::UNO_QUERY );
1389                     if( xIndexReplace.is())
1390                         xIndexReplace->replaceByIndex(
1391                             0, uno::makeAny( OUString( pEdit->GetText())));
1392                 }
1393             }
1394         }
1395     }
1396     return 0;
1397 }
1398 
GetTotalWidth() const1399 sal_Int32 DataBrowser::GetTotalWidth() const
1400 {
1401     sal_uLong nWidth = 0;
1402     for ( sal_uInt16 nCol = 0; nCol < ColCount(); ++nCol )
1403         nWidth += GetColumnWidth( nCol );
1404     return static_cast< sal_Int32 >( nWidth );
1405 }
1406 
1407 } // namespace chart
1408