1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_chart2.hxx"
26
27 // header for class SvNumberformat
28 #ifndef _ZFORMAT_HXX
29 #ifndef _ZFORLIST_DECLARE_TABLE
30 #define _ZFORLIST_DECLARE_TABLE
31 #endif
32 #include <svl/zformat.hxx>
33 #endif
34 // header for SvNumberFormatter
35 #include <svl/zforlist.hxx>
36
37 #include "DataBrowser.hxx"
38 #include "DataBrowserModel.hxx"
39 #include "Strings.hrc"
40 #include "ContainerHelper.hxx"
41 #include "DataSeriesHelper.hxx"
42 #include "DiagramHelper.hxx"
43 #include "ChartModelHelper.hxx"
44 #include "CommonConverters.hxx"
45 #include "macros.hxx"
46 #include "NumberFormatterWrapper.hxx"
47 #include "servicenames_charttypes.hxx"
48 #include "ResId.hxx"
49 #include "Bitmaps.hrc"
50 #include "Bitmaps_HC.hrc"
51 #include "HelpIds.hrc"
52
53 #include <vcl/fixed.hxx>
54 #include <vcl/image.hxx>
55 #include <vcl/msgbox.hxx>
56 #include <rtl/math.hxx>
57
58 #include <com/sun/star/util/XCloneable.hpp>
59 #include <com/sun/star/chart2/XChartDocument.hpp>
60 #include <com/sun/star/chart2/XChartType.hpp>
61
62 #include <com/sun/star/container/XIndexReplace.hpp>
63 #include <com/sun/star/util/XNumberFormats.hpp>
64
65 #include <algorithm>
66 #include <functional>
67
68 #define SELECT_IMAGE(name,hc) Image( SchResId( hc ? name ## _HC : name ))
69
70 /* BROWSER_COLUMNSELECTION : single cells may be selected rather than only
71 entire rows
72 BROWSER_(H|V)LINES : show horizontal or vertical grid-lines
73
74 BROWSER_AUTO_(H|V)SCROLL : scroll automated horizontally or vertically when
75 cursor is moved beyond the edge of the dialog
76 BROWSER_HIGHLIGHT_NONE : Do not mark the current row with selection color
77 (usually blue)
78
79 */
80 #define BROWSER_STANDARD_FLAGS \
81 BROWSER_COLUMNSELECTION | \
82 BROWSER_HLINES | BROWSER_VLINES | \
83 BROWSER_AUTO_HSCROLL | BROWSER_AUTO_VSCROLL | \
84 BROWSER_HIGHLIGHT_NONE
85
86 // BROWSER_HIDECURSOR would prevent flickering in edit fields, but navigating
87 // with shift up/down, and entering non-editable cells would be problematic,
88 // e.g. the first cell, or when being in read-only mode
89
90
91 using namespace ::com::sun::star;
92 using ::com::sun::star::uno::Sequence;
93 using ::com::sun::star::uno::Reference;
94 using ::rtl::OUString;
95
96 using namespace ::svt;
97
98 namespace
99 {
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 : public ::std::unary_function< ::boost::shared_ptr< SeriesHeader >, void >
439 {
operator ()chart::impl::applyChangesFunctor440 void operator() ( ::boost::shared_ptr< SeriesHeader > spHeader )
441 {
442 spHeader->applyChanges();
443 }
444 };
445
446 } // namespace impl
447 // ----------------------------------------
448
449 namespace
450 {
451
452 /** returns false, if no header as the focus.
453
454 If a header has the focus, true is returned and the index of the header
455 with focus is set at pIndex if pOutIndex is not 0.
456 */
lcl_SeriesHeaderHasFocus(const::std::vector<::boost::shared_ptr<::chart::impl::SeriesHeader>> & rSeriesHeader,sal_Int32 * pOutIndex=0)457 bool lcl_SeriesHeaderHasFocus(
458 const ::std::vector< ::boost::shared_ptr< ::chart::impl::SeriesHeader > > & rSeriesHeader,
459 sal_Int32 * pOutIndex = 0 )
460 {
461 sal_Int32 nIndex = 0;
462 for( ::std::vector< ::boost::shared_ptr< ::chart::impl::SeriesHeader > >::const_iterator aIt( rSeriesHeader.begin());
463 aIt != rSeriesHeader.end(); ++aIt, ++nIndex )
464 {
465 if( (*aIt)->HasFocus())
466 {
467 if( pOutIndex )
468 *pOutIndex = nIndex;
469 return true;
470 }
471 }
472 return false;
473 }
474
lcl_getColumnInDataOrHeader(sal_uInt16 nCol,const::std::vector<::boost::shared_ptr<::chart::impl::SeriesHeader>> & rSeriesHeader)475 sal_Int32 lcl_getColumnInDataOrHeader(
476 sal_uInt16 nCol, const ::std::vector< ::boost::shared_ptr< ::chart::impl::SeriesHeader > > & rSeriesHeader )
477 {
478 sal_Int32 nColIdx = 0;
479 bool bHeaderHasFocus( lcl_SeriesHeaderHasFocus( rSeriesHeader, &nColIdx ));
480
481 if( bHeaderHasFocus )
482 nColIdx = lcl_getColumnInData( static_cast< sal_uInt16 >( rSeriesHeader[nColIdx]->GetStartColumn()));
483 else
484 nColIdx = lcl_getColumnInData( nCol );
485
486 return nColIdx;
487 }
488
489 } // anonymous namespace
490
491
DataBrowser(Window * pParent,const ResId & rId,bool bLiveUpdate)492 DataBrowser::DataBrowser( Window* pParent, const ResId& rId, bool bLiveUpdate ) :
493 ::svt::EditBrowseBox( pParent, rId, EBBF_SMART_TAB_TRAVEL | EBBF_HANDLE_COLUMN_TEXT, BROWSER_STANDARD_FLAGS ),
494 m_nSeekRow( 0 ),
495 m_bIsReadOnly( false ),
496 m_bIsDirty( false ),
497 m_bLiveUpdate( bLiveUpdate ),
498 m_bDataValid( true ),
499 m_aNumberEditField( & EditBrowseBox::GetDataWindow(), WB_NOBORDER ),
500 m_aTextEditField( & EditBrowseBox::GetDataWindow(), WB_NOBORDER ),
501 m_rNumberEditController( new ::svt::FormattedFieldCellController( & m_aNumberEditField )),
502 m_rTextEditController( new ::svt::EditCellController( & m_aTextEditField ))
503 {
504 double fNan;
505 ::rtl::math::setNan( & fNan );
506 m_aNumberEditField.SetDefaultValue( fNan );
507 m_aNumberEditField.TreatAsNumber( sal_True );
508 RenewTable();
509 SetClean();
510 }
511
~DataBrowser()512 DataBrowser::~DataBrowser()
513 {
514 }
515
MayInsertRow() const516 bool DataBrowser::MayInsertRow() const
517 {
518 return ! IsReadOnly()
519 && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ));
520 }
521
MayInsertColumn() const522 bool DataBrowser::MayInsertColumn() const
523 {
524 return ! IsReadOnly();
525 }
526
MayDeleteRow() const527 bool DataBrowser::MayDeleteRow() const
528 {
529 return ! IsReadOnly()
530 && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
531 && ( GetCurRow() >= 0 )
532 && ( GetRowCount() > 1 );
533 }
534
MayDeleteColumn() const535 bool DataBrowser::MayDeleteColumn() const
536 {
537 // if a series header has the focus
538 if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
539 return true;
540
541 return ! IsReadOnly()
542 && ( GetCurColumnId() > 1 )
543 && ( ColCount() > 2 );
544 }
545
MaySwapRows() const546 bool DataBrowser::MaySwapRows() const
547 {
548 return ! IsReadOnly()
549 && ( !lcl_SeriesHeaderHasFocus( m_aSeriesHeaders ))
550 && ( GetCurRow() >= 0 )
551 && ( GetCurRow() < GetRowCount() - 1 );
552 }
553
MaySwapColumns() const554 bool DataBrowser::MaySwapColumns() const
555 {
556 // if a series header (except the last one) has the focus
557 {
558 sal_Int32 nColIndex(0);
559 if( lcl_SeriesHeaderHasFocus( m_aSeriesHeaders, &nColIndex ))
560 return (static_cast< sal_uInt32 >( nColIndex ) < (m_aSeriesHeaders.size() - 1));
561 }
562
563 sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
564 return ! IsReadOnly()
565 && ( nColIdx > 0 )
566 && ( nColIdx < ColCount()-2 )
567 && m_apDataBrowserModel.get()
568 && !m_apDataBrowserModel->isCategoriesColumn( nColIdx );
569 }
570
clearHeaders()571 void DataBrowser::clearHeaders()
572 {
573 ::std::for_each( m_aSeriesHeaders.begin(), m_aSeriesHeaders.end(), impl::applyChangesFunctor());
574 m_aSeriesHeaders.clear();
575 }
576
RenewTable()577 void DataBrowser::RenewTable()
578 {
579 if( ! m_apDataBrowserModel.get())
580 return;
581
582 long nOldRow = GetCurRow();
583 sal_uInt16 nOldColId = GetCurColumnId();
584
585 sal_Bool bLastUpdateMode = GetUpdateMode();
586 SetUpdateMode( sal_False );
587
588 if( IsModified() )
589 SaveModified();
590
591 DeactivateCell();
592
593 RemoveColumns();
594 RowRemoved( 1, GetRowCount() );
595
596 // for row numbers
597 InsertHandleColumn( static_cast< sal_uInt16 >(
598 GetDataWindow().LogicToPixel( Size( 42, 0 )).getWidth() ));
599
600 OUString aDefaultSeriesName( ::chart::SchResId::getResString( STR_COLUMN_LABEL ));
601 replaceParamterInString( aDefaultSeriesName, C2U("%COLUMNNUMBER"), OUString::valueOf( sal_Int32(24) ) );
602 sal_Int32 nColumnWidth = GetDataWindow().GetTextWidth( aDefaultSeriesName )
603 + GetDataWindow().LogicToPixel( Point( 4 + impl::SeriesHeader::GetRelativeAppFontXPosForNameField(), 0 ), MAP_APPFONT ).X();
604 sal_Int32 nColumnCount = m_apDataBrowserModel->getColumnCount();
605 // nRowCount is a member of a base class
606 sal_Int32 nRowCountLocal = m_apDataBrowserModel->getMaxRowCount();
607 for( sal_Int32 nColIdx=1; nColIdx<=nColumnCount; ++nColIdx )
608 {
609 InsertDataColumn( static_cast< sal_uInt16 >( nColIdx ), GetColString( nColIdx ), nColumnWidth );
610 }
611
612 RowInserted( 1, nRowCountLocal );
613 GoToRow( ::std::min( nOldRow, GetRowCount() - 1 ));
614 GoToColumnId( ::std::min( nOldColId, static_cast< sal_uInt16 >( ColCount() - 1 )));
615
616 Window * pWin = this->GetParent();
617 if( !pWin )
618 pWin = this;
619
620 // fill series headers
621 clearHeaders();
622 const DataBrowserModel::tDataHeaderVector& aHeaders( m_apDataBrowserModel->getDataHeaders());
623 Link aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus ));
624 Link aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged ));
625 bool bIsHighContrast = pWin ? (pWin->GetSettings().GetStyleSettings().GetHighContrastMode()) : false;
626
627 for( DataBrowserModel::tDataHeaderVector::const_iterator aIt( aHeaders.begin());
628 aIt != aHeaders.end(); ++aIt )
629 {
630 ::boost::shared_ptr< impl::SeriesHeader > spHeader( new impl::SeriesHeader( pWin ));
631 Reference< beans::XPropertySet > xSeriesProp( aIt->m_xDataSeries, uno::UNO_QUERY );
632 sal_Int32 nColor = 0;
633 // @todo: Set "DraftColor", i.e. interpolated colors for gradients, bitmaps, etc.
634 if( xSeriesProp.is() &&
635 ( xSeriesProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Color"))) >>= nColor ))
636 spHeader->SetColor( Color( nColor ));
637 spHeader->SetChartType( aIt->m_xChartType, aIt->m_bSwapXAndYAxis, bIsHighContrast );
638 spHeader->SetSeriesName(
639 String( DataSeriesHelper::getDataSeriesLabel(
640 aIt->m_xDataSeries,
641 (aIt->m_xChartType.is() ?
642 aIt->m_xChartType->getRoleOfSequenceForSeriesLabel() :
643 OUString( RTL_CONSTASCII_USTRINGPARAM("values-y"))))));
644 // index is 1-based, as 0 is for the column that contains the row-numbers
645 spHeader->SetRange( aIt->m_nStartColumn + 1, aIt->m_nEndColumn + 1 );
646 spHeader->SetGetFocusHdl( aFocusLink );
647 spHeader->SetEditChangedHdl( aSeriesHeaderChangedLink );
648 m_aSeriesHeaders.push_back( spHeader );
649 }
650
651 ImplAdjustHeaderControls();
652 SetDirty();
653 SetUpdateMode( bLastUpdateMode );
654 ActivateCell();
655 Invalidate();
656 }
657
GetColString(sal_Int32 nColumnId) const658 String DataBrowser::GetColString( sal_Int32 nColumnId ) const
659 {
660 OSL_ASSERT( m_apDataBrowserModel.get());
661 if( nColumnId > 0 )
662 return String( m_apDataBrowserModel->getRoleOfColumn( static_cast< sal_Int32 >( nColumnId ) - 1 ));
663 return String();
664 }
665
GetRowString(sal_Int32 nRow) const666 String DataBrowser::GetRowString( sal_Int32 nRow ) const
667 {
668 return String::CreateFromInt32( nRow + 1 );
669 }
670
GetCellText(long nRow,sal_uInt16 nColumnId) const671 String DataBrowser::GetCellText( long nRow, sal_uInt16 nColumnId ) const
672 {
673 String aResult;
674
675 if( nColumnId == 0 )
676 {
677 aResult = GetRowString( static_cast< sal_Int32 >( nRow ));
678 }
679 else if( nRow >= 0 &&
680 m_apDataBrowserModel.get())
681 {
682 sal_Int32 nColIndex = static_cast< sal_Int32 >( nColumnId ) - 1;
683
684 if( m_apDataBrowserModel->getCellType( nColIndex, nRow ) == DataBrowserModel::NUMBER )
685 {
686 double fData( m_apDataBrowserModel->getCellNumber( nColIndex, nRow ));
687 sal_Int32 nLabelColor;
688 bool bColorChanged = false;
689
690 if( ! ::rtl::math::isNan( fData ) &&
691 m_spNumberFormatterWrapper.get() )
692 aResult = String( m_spNumberFormatterWrapper->getFormattedString(
693 GetNumberFormatKey( nRow, nColumnId ),
694 fData, nLabelColor, bColorChanged ));
695 }
696 else if( m_apDataBrowserModel->getCellType( nColIndex, nRow ) == DataBrowserModel::TEXTORDATE )
697 {
698 uno::Any aAny = m_apDataBrowserModel->getCellAny( nColIndex, nRow );
699 OUString aText;
700 double fDouble=0.0;
701 if( aAny>>=aText )
702 aResult = aText;
703 else if( aAny>>=fDouble )
704 {
705 sal_Int32 nLabelColor;
706 bool bColorChanged = false;
707 sal_Int32 nDateNumberFormat = DiagramHelper::getDateNumberFormat( Reference< util::XNumberFormatsSupplier >( m_xChartDoc, uno::UNO_QUERY) );
708 if( ! ::rtl::math::isNan( fDouble ) && m_spNumberFormatterWrapper.get() )
709 aResult = String( m_spNumberFormatterWrapper->getFormattedString(
710 nDateNumberFormat, fDouble, nLabelColor, bColorChanged ));
711 }
712 }
713 else
714 {
715 OSL_ASSERT( m_apDataBrowserModel->getCellType( nColIndex, nRow ) == DataBrowserModel::TEXT );
716 aResult = m_apDataBrowserModel->getCellText( nColIndex, nRow );
717 }
718 }
719
720 return aResult;
721 }
722
GetCellNumber(long nRow,sal_uInt16 nColumnId) const723 double DataBrowser::GetCellNumber( long nRow, sal_uInt16 nColumnId ) const
724 {
725 double fResult;
726 ::rtl::math::setNan( & fResult );
727
728 if(( nColumnId >= 1 ) && ( nRow >= 0 ) &&
729 m_apDataBrowserModel.get())
730 {
731 fResult = m_apDataBrowserModel->getCellNumber(
732 static_cast< sal_Int32 >( nColumnId ) - 1, nRow );
733 }
734
735 return fResult;
736 }
737
Resize()738 void DataBrowser::Resize()
739 {
740 sal_Bool bLastUpdateMode = GetUpdateMode();
741 SetUpdateMode( sal_False );
742
743 ::svt::EditBrowseBox::Resize();
744 ImplAdjustHeaderControls();
745 SetUpdateMode( bLastUpdateMode );
746 }
747
SetReadOnly(bool bNewState)748 bool DataBrowser::SetReadOnly( bool bNewState )
749 {
750 bool bResult = m_bIsReadOnly;
751
752 if( m_bIsReadOnly != bNewState )
753 {
754 m_bIsReadOnly = bNewState;
755 Invalidate();
756 DeactivateCell();
757 }
758
759 return bResult;
760 }
761
IsReadOnly() const762 bool DataBrowser::IsReadOnly() const
763 {
764 return m_bIsReadOnly;
765 }
766
767
SetClean()768 void DataBrowser::SetClean()
769 {
770 m_bIsDirty = false;
771 }
772
SetDirty()773 void DataBrowser::SetDirty()
774 {
775 if( !m_bLiveUpdate )
776 m_bIsDirty = true;
777 }
778
CursorMoved()779 void DataBrowser::CursorMoved()
780 {
781 EditBrowseBox::CursorMoved();
782
783 if( GetUpdateMode() && m_aCursorMovedHdlLink.IsSet())
784 m_aCursorMovedHdlLink.Call( this );
785 }
786
SetCellModifiedHdl(const Link & rLink)787 void DataBrowser::SetCellModifiedHdl( const Link& rLink )
788 {
789 m_aCellModifiedLink = rLink;
790 }
791
MouseButtonDown(const BrowserMouseEvent & rEvt)792 void DataBrowser::MouseButtonDown( const BrowserMouseEvent& rEvt )
793 {
794 if( !m_bDataValid )
795 ShowWarningBox();
796 else
797 EditBrowseBox::MouseButtonDown( rEvt );
798 }
799
ShowWarningBox()800 void DataBrowser::ShowWarningBox()
801 {
802 WarningBox( this, WinBits( WB_OK ),
803 String( SchResId( STR_INVALID_NUMBER ))).Execute();
804 }
805
ShowQueryBox()806 bool DataBrowser::ShowQueryBox()
807 {
808 QueryBox* pQueryBox = new QueryBox( this, WB_YES_NO, String( SchResId( STR_DATA_EDITOR_INCORRECT_INPUT )));
809
810 return ( pQueryBox->Execute() == RET_YES );
811 }
812
IsDataValid()813 bool DataBrowser::IsDataValid()
814 {
815 bool bValid = true;
816 const sal_Int32 nRow = lcl_getRowInData( GetCurRow());
817 const sal_Int32 nCol = lcl_getColumnInData( GetCurColumnId());
818
819 if( m_apDataBrowserModel->getCellType( nCol, nRow ) == DataBrowserModel::NUMBER )
820 {
821 sal_uInt32 nDummy = 0;
822 double fDummy = 0.0;
823 String aText( m_aNumberEditField.GetText());
824
825 if( aText.Len() > 0 &&
826 m_spNumberFormatterWrapper.get() &&
827 m_spNumberFormatterWrapper->getSvNumberFormatter() &&
828 ! m_spNumberFormatterWrapper->getSvNumberFormatter()->IsNumberFormat(
829 aText, nDummy, fDummy ))
830 {
831 bValid = false;
832 }
833 }
834
835 return bValid;
836 }
837
IsEnableItem()838 bool DataBrowser::IsEnableItem()
839 {
840 return m_bDataValid;
841 }
842
CellModified()843 void DataBrowser::CellModified()
844 {
845 m_bDataValid = IsDataValid();
846 SetDirty();
847 if( m_aCellModifiedLink.IsSet())
848 m_aCursorMovedHdlLink.Call( this );
849 }
850
SetDataFromModel(const Reference<chart2::XChartDocument> & xChartDoc,const Reference<uno::XComponentContext> & xContext)851 void DataBrowser::SetDataFromModel(
852 const Reference< chart2::XChartDocument > & xChartDoc,
853 const Reference< uno::XComponentContext > & xContext )
854 {
855 if( m_bLiveUpdate )
856 {
857 m_xChartDoc.set( xChartDoc );
858 }
859 else
860 {
861 Reference< util::XCloneable > xCloneable( xChartDoc, uno::UNO_QUERY );
862 if( xCloneable.is())
863 m_xChartDoc.set( xCloneable->createClone(), uno::UNO_QUERY );
864 }
865
866 m_apDataBrowserModel.reset( new DataBrowserModel( m_xChartDoc, xContext ));
867 m_spNumberFormatterWrapper.reset(
868 new NumberFormatterWrapper(
869 Reference< util::XNumberFormatsSupplier >( m_xChartDoc, uno::UNO_QUERY )));
870
871 if( m_spNumberFormatterWrapper.get() )
872 m_aNumberEditField.SetFormatter( m_spNumberFormatterWrapper->getSvNumberFormatter() );
873
874 RenewTable();
875
876 const sal_Int32 nColCnt = m_apDataBrowserModel->getColumnCount();
877 const sal_Int32 nRowCnt = m_apDataBrowserModel->getMaxRowCount();
878 if( nRowCnt && nColCnt )
879 {
880 GoToRow( 0 );
881 GoToColumnId( 1 );
882 }
883 SetClean();
884 }
885
InsertColumn()886 void DataBrowser::InsertColumn()
887 {
888 sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
889
890 if( nColIdx >= 0 &&
891 m_apDataBrowserModel.get())
892 {
893 // save changes made to edit-field
894 if( IsModified() )
895 SaveModified();
896
897 m_apDataBrowserModel->insertDataSeries( nColIdx );
898 RenewTable();
899 }
900 }
901
InsertTextColumn()902 void DataBrowser::InsertTextColumn()
903 {
904 sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
905
906 if( nColIdx >= 0 &&
907 m_apDataBrowserModel.get())
908 {
909 // save changes made to edit-field
910 if( IsModified() )
911 SaveModified();
912
913 m_apDataBrowserModel->insertComplexCategoryLevel( nColIdx );
914 RenewTable();
915 }
916 }
917
RemoveColumn()918 void DataBrowser::RemoveColumn()
919 {
920 sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
921
922 if( nColIdx >= 0 &&
923 m_apDataBrowserModel.get())
924 {
925 // save changes made to edit-field
926 if( IsModified() )
927 SaveModified();
928
929 m_bDataValid = true;
930 m_apDataBrowserModel->removeDataSeriesOrComplexCategoryLevel( nColIdx );
931 RenewTable();
932 }
933 }
934
InsertRow()935 void DataBrowser::InsertRow()
936 {
937 sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow());
938
939 if( nRowIdx >= 0 &&
940 m_apDataBrowserModel.get())
941 {
942 // save changes made to edit-field
943 if( IsModified() )
944 SaveModified();
945
946 m_apDataBrowserModel->insertDataPointForAllSeries( nRowIdx );
947 RenewTable();
948 }
949 }
950
RemoveRow()951 void DataBrowser::RemoveRow()
952 {
953 sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow());
954
955 if( nRowIdx >= 0 &&
956 m_apDataBrowserModel.get())
957 {
958 // save changes made to edit-field
959 if( IsModified() )
960 SaveModified();
961
962 m_bDataValid = true;
963 m_apDataBrowserModel->removeDataPointForAllSeries( nRowIdx );
964 RenewTable();
965 }
966 }
967
SwapColumn()968 void DataBrowser::SwapColumn()
969 {
970 sal_Int32 nColIdx = lcl_getColumnInDataOrHeader( GetCurColumnId(), m_aSeriesHeaders );
971
972 if( nColIdx >= 0 &&
973 m_apDataBrowserModel.get())
974 {
975 // save changes made to edit-field
976 if( IsModified() )
977 SaveModified();
978
979 m_apDataBrowserModel->swapDataSeries( nColIdx );
980
981 // keep cursor in swapped column
982 if( GetCurColumnId() < ColCount() - 1 )
983 {
984 Dispatch( BROWSER_CURSORRIGHT );
985 }
986 RenewTable();
987 }
988 }
989
SwapRow()990 void DataBrowser::SwapRow()
991 {
992 sal_Int32 nRowIdx = lcl_getRowInData( GetCurRow());
993
994 if( nRowIdx >= 0 &&
995 m_apDataBrowserModel.get())
996 {
997 // save changes made to edit-field
998 if( IsModified() )
999 SaveModified();
1000
1001 m_apDataBrowserModel->swapDataPointForAllSeries( nRowIdx );
1002
1003 // keep cursor in swapped row
1004 if( GetCurRow() < GetRowCount() - 1 )
1005 {
1006 Dispatch( BROWSER_CURSORDOWN );
1007 }
1008 RenewTable();
1009 }
1010 }
1011
SetCursorMovedHdl(const Link & rLink)1012 void DataBrowser::SetCursorMovedHdl( const Link& rLink )
1013 {
1014 m_aCursorMovedHdlLink = rLink;
1015 }
1016
1017 // implementations for ::svt::EditBrowseBox (pure virtual methods)
PaintCell(OutputDevice & rDev,const Rectangle & rRect,sal_uInt16 nColumnId) const1018 void DataBrowser::PaintCell(
1019 OutputDevice& rDev, const Rectangle& rRect, sal_uInt16 nColumnId ) const
1020 {
1021 Point aPos( rRect.TopLeft());
1022 aPos.X() += 1;
1023
1024 String aText = GetCellText( m_nSeekRow, nColumnId );
1025 Size TxtSize( GetDataWindow().GetTextWidth( aText ), GetDataWindow().GetTextHeight());
1026
1027 // clipping
1028 if( aPos.X() < rRect.Right() || aPos.X() + TxtSize.Width() > rRect.Right() ||
1029 aPos.Y() < rRect.Top() || aPos.Y() + TxtSize.Height() > rRect.Bottom())
1030 rDev.SetClipRegion( rRect );
1031
1032 // allow for a disabled control ...
1033 sal_Bool bEnabled = IsEnabled();
1034 Color aOriginalColor = rDev.GetTextColor();
1035 if( ! bEnabled )
1036 rDev.SetTextColor( GetSettings().GetStyleSettings().GetDisableColor() );
1037
1038 // TEST
1039 // if( nColumnId == 1 )
1040 // // categories
1041 // rDev.SetFillColor( Color( 0xff, 0xff, 0xff ));
1042 // else if( nColumnId == 2 )
1043 // // x-values
1044 // rDev.SetFillColor( Color( 0xf0, 0xf0, 0xff ));
1045 // else
1046 // // y-values
1047 // rDev.SetFillColor( Color( 0xff, 0xff, 0xf0 ));
1048
1049 // rDev.DrawRect( rRect );
1050
1051 // draw the text
1052 rDev.DrawText( aPos, aText );
1053
1054 // reset the color (if necessary)
1055 if( ! bEnabled )
1056 rDev.SetTextColor( aOriginalColor );
1057
1058 if( rDev.IsClipRegion())
1059 rDev.SetClipRegion();
1060 }
1061
SeekRow(long nRow)1062 sal_Bool DataBrowser::SeekRow( long nRow )
1063 {
1064 if( ! EditBrowseBox::SeekRow( nRow ))
1065 return sal_False;
1066
1067 if( nRow < 0 )
1068 m_nSeekRow = - 1;
1069 else
1070 m_nSeekRow = nRow;
1071
1072 return sal_True;
1073 }
1074
IsTabAllowed(sal_Bool bForward) const1075 sal_Bool DataBrowser::IsTabAllowed( sal_Bool bForward ) const
1076 {
1077 long nRow = GetCurRow();
1078 long nCol = GetCurColumnId();
1079
1080 // column 0 is header-column
1081 long nBadCol = bForward
1082 ? GetColumnCount() - 1
1083 : 1;
1084 long nBadRow = bForward
1085 ? GetRowCount() - 1
1086 : 0;
1087
1088 if( !m_bDataValid )
1089 {
1090 const_cast< DataBrowser* >( this )->ShowWarningBox();
1091 return sal_False;
1092 }
1093
1094 return ( nRow != nBadRow ||
1095 nCol != nBadCol );
1096 }
1097
GetController(long nRow,sal_uInt16 nCol)1098 ::svt::CellController* DataBrowser::GetController( long nRow, sal_uInt16 nCol )
1099 {
1100 if( m_bIsReadOnly )
1101 return 0;
1102
1103 if( CellContainsNumbers( nRow, nCol ))
1104 {
1105 m_aNumberEditField.UseInputStringForFormatting();
1106 m_aNumberEditField.SetFormatKey( GetNumberFormatKey( nRow, nCol ));
1107 return m_rNumberEditController;
1108 }
1109
1110 return m_rTextEditController;
1111 }
1112
InitController(::svt::CellControllerRef & rController,long nRow,sal_uInt16 nCol)1113 void DataBrowser::InitController(
1114 ::svt::CellControllerRef& rController, long nRow, sal_uInt16 nCol )
1115 {
1116 if( rController == m_rTextEditController )
1117 {
1118 String aText( GetCellText( nRow, nCol ) );
1119 m_aTextEditField.SetText( aText );
1120 m_aTextEditField.SetSelection( Selection( 0, aText.Len() ));
1121 }
1122 else if( rController == m_rNumberEditController )
1123 {
1124 // treat invalid and empty text as Nan
1125 m_aNumberEditField.EnableNotANumber( true );
1126 if( ::rtl::math::isNan( GetCellNumber( nRow, nCol )))
1127 m_aNumberEditField.SetTextValue( String());
1128 else
1129 m_aNumberEditField.SetValue( GetCellNumber( nRow, nCol ) );
1130 String aText( m_aNumberEditField.GetText());
1131 m_aNumberEditField.SetSelection( Selection( 0, aText.Len()));
1132 }
1133 else
1134 {
1135 DBG_ERROR( "Invalid Controller" );
1136 }
1137 }
1138
CellContainsNumbers(sal_Int32 nRow,sal_uInt16 nCol) const1139 bool DataBrowser::CellContainsNumbers( sal_Int32 nRow, sal_uInt16 nCol ) const
1140 {
1141 if( ! m_apDataBrowserModel.get())
1142 return false;
1143 return (m_apDataBrowserModel->getCellType( lcl_getColumnInData( nCol ), lcl_getRowInData( nRow )) ==
1144 DataBrowserModel::NUMBER);
1145 }
1146
GetNumberFormatKey(sal_Int32 nRow,sal_uInt16 nCol) const1147 sal_uInt32 DataBrowser::GetNumberFormatKey( sal_Int32 nRow, sal_uInt16 nCol ) const
1148 {
1149 if( ! m_apDataBrowserModel.get())
1150 return 0;
1151 return m_apDataBrowserModel->getNumberFormatKey( lcl_getColumnInData( nCol ), lcl_getRowInData( nRow ));
1152 }
1153
isDateString(rtl::OUString aInputString,double & fOutDateValue)1154 bool DataBrowser::isDateString( rtl::OUString aInputString, double& fOutDateValue )
1155 {
1156 sal_uInt32 nNumberFormat=0;
1157 SvNumberFormatter* pSvNumberFormatter = m_spNumberFormatterWrapper.get() ? m_spNumberFormatterWrapper->getSvNumberFormatter() : 0;
1158 if( !aInputString.isEmpty() && pSvNumberFormatter && pSvNumberFormatter->IsNumberFormat( aInputString, nNumberFormat, fOutDateValue ) )
1159 {
1160 Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( m_xChartDoc, uno::UNO_QUERY );
1161 Reference< util::XNumberFormats > xNumberFormats;
1162 if( xNumberFormatsSupplier.is() )
1163 xNumberFormats = Reference< util::XNumberFormats >( xNumberFormatsSupplier->getNumberFormats() );
1164 if( DiagramHelper::isDateNumberFormat( nNumberFormat, xNumberFormats ) )
1165 return true;
1166 }
1167 return false;
1168 }
1169
SaveModified()1170 sal_Bool DataBrowser::SaveModified()
1171 {
1172 if( ! IsModified() )
1173 return sal_True;
1174
1175 sal_Bool bChangeValid = sal_True;
1176
1177 const sal_Int32 nRow = lcl_getRowInData( GetCurRow());
1178 const sal_Int32 nCol = lcl_getColumnInData( GetCurColumnId());
1179
1180 DBG_ASSERT( nRow >= 0 || nCol >= 0, "This cell should not be modified!" );
1181
1182 SvNumberFormatter* pSvNumberFormatter = m_spNumberFormatterWrapper.get() ? m_spNumberFormatterWrapper->getSvNumberFormatter() : 0;
1183 switch( m_apDataBrowserModel->getCellType( nCol, nRow ))
1184 {
1185 case DataBrowserModel::NUMBER:
1186 {
1187 sal_uInt32 nDummy = 0;
1188 double fDummy = 0.0;
1189 String aText( m_aNumberEditField.GetText());
1190 // an empty string is valid, if no numberformatter exists, all
1191 // values are treated as valid
1192 if( aText.Len() > 0 && pSvNumberFormatter &&
1193 ! pSvNumberFormatter->IsNumberFormat( aText, nDummy, fDummy ) )
1194 {
1195 bChangeValid = sal_False;
1196 }
1197 else
1198 {
1199 double fData = m_aNumberEditField.GetValue();
1200 bChangeValid = m_apDataBrowserModel->setCellNumber( nCol, nRow, fData );
1201 }
1202 }
1203 break;
1204 case DataBrowserModel::TEXTORDATE:
1205 {
1206 OUString aText( m_aTextEditField.GetText() );
1207 double fDateValue=0.0;
1208 bChangeValid = sal_False;
1209 if( isDateString( aText, fDateValue ) )
1210 bChangeValid = m_apDataBrowserModel->setCellAny( nCol, nRow, uno::makeAny( fDateValue ) );
1211 if(!bChangeValid)
1212 bChangeValid = m_apDataBrowserModel->setCellAny( nCol, nRow, uno::makeAny( aText ) );
1213 }
1214 break;
1215 case DataBrowserModel::TEXT:
1216 {
1217 OUString aText( m_aTextEditField.GetText());
1218 bChangeValid = m_apDataBrowserModel->setCellText( nCol, nRow, aText );
1219 }
1220 break;
1221 }
1222
1223 // the first valid change changes this to true
1224 if( bChangeValid )
1225 {
1226 RowModified( GetCurRow(), GetCurColumnId());
1227 ::svt::CellController* pCtrl = GetController( GetCurRow(), GetCurColumnId());
1228 if( pCtrl )
1229 pCtrl->ClearModified();
1230 SetDirty();
1231 }
1232
1233 return bChangeValid;
1234 }
1235
EndEditing()1236 bool DataBrowser::EndEditing()
1237 {
1238 if( IsModified())
1239 SaveModified();
1240
1241 // apply changes made to series headers
1242 ::std::for_each( m_aSeriesHeaders.begin(), m_aSeriesHeaders.end(), impl::applyChangesFunctor());
1243
1244 if( m_bDataValid )
1245 return true;
1246 else
1247 return ShowQueryBox();
1248 }
1249
GetFirstVisibleColumNumber() const1250 sal_Int16 DataBrowser::GetFirstVisibleColumNumber() const
1251 {
1252 return GetFirstVisibleColNumber();
1253 }
1254
ColumnResized(sal_uInt16 nColId)1255 void DataBrowser::ColumnResized( sal_uInt16 nColId )
1256 {
1257 sal_Bool bLastUpdateMode = GetUpdateMode();
1258 SetUpdateMode( sal_False );
1259
1260 EditBrowseBox::ColumnResized( nColId );
1261 ImplAdjustHeaderControls();
1262 SetUpdateMode( bLastUpdateMode );
1263 }
1264
1265 // virtual void MouseMove( const MouseEvent& rEvt );
1266
EndScroll()1267 void DataBrowser::EndScroll()
1268 {
1269 sal_Bool bLastUpdateMode = GetUpdateMode();
1270 SetUpdateMode( sal_False );
1271
1272 EditBrowseBox::EndScroll();
1273 RenewSeriesHeaders();
1274
1275 SetUpdateMode( bLastUpdateMode );
1276 }
1277
RenewSeriesHeaders()1278 void DataBrowser::RenewSeriesHeaders()
1279 {
1280 Window * pWin = this->GetParent();
1281 if( !pWin )
1282 pWin = this;
1283
1284 clearHeaders();
1285 DataBrowserModel::tDataHeaderVector aHeaders( m_apDataBrowserModel->getDataHeaders());
1286 Link aFocusLink( LINK( this, DataBrowser, SeriesHeaderGotFocus ));
1287 Link aSeriesHeaderChangedLink( LINK( this, DataBrowser, SeriesHeaderChanged ));
1288 bool bIsHighContrast = pWin ? (pWin->GetSettings().GetStyleSettings().GetHighContrastMode()) : false;
1289
1290 for( DataBrowserModel::tDataHeaderVector::const_iterator aIt( aHeaders.begin());
1291 aIt != aHeaders.end(); ++aIt )
1292 {
1293 ::boost::shared_ptr< impl::SeriesHeader > spHeader( new impl::SeriesHeader( pWin ));
1294 Reference< beans::XPropertySet > xSeriesProp( aIt->m_xDataSeries, uno::UNO_QUERY );
1295 sal_Int32 nColor = 0;
1296 if( xSeriesProp.is() &&
1297 ( xSeriesProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM("Color"))) >>= nColor ))
1298 spHeader->SetColor( Color( nColor ));
1299 spHeader->SetChartType( aIt->m_xChartType, aIt->m_bSwapXAndYAxis, bIsHighContrast );
1300 spHeader->SetSeriesName(
1301 String( DataSeriesHelper::getDataSeriesLabel(
1302 aIt->m_xDataSeries,
1303 (aIt->m_xChartType.is() ?
1304 aIt->m_xChartType->getRoleOfSequenceForSeriesLabel() :
1305 OUString( RTL_CONSTASCII_USTRINGPARAM("values-y"))))));
1306 spHeader->SetRange( aIt->m_nStartColumn + 1, aIt->m_nEndColumn + 1 );
1307 spHeader->SetGetFocusHdl( aFocusLink );
1308 spHeader->SetEditChangedHdl( aSeriesHeaderChangedLink );
1309 m_aSeriesHeaders.push_back( spHeader );
1310 }
1311
1312 ImplAdjustHeaderControls();
1313 }
1314
ImplAdjustHeaderControls()1315 void DataBrowser::ImplAdjustHeaderControls()
1316 {
1317 sal_uInt16 nColCount = this->GetColumnCount();
1318 sal_uInt32 nCurrentPos = this->GetPosPixel().getX();
1319 sal_uInt32 nMaxPos = nCurrentPos + this->GetOutputSizePixel().getWidth();
1320 sal_uInt32 nStartPos = nCurrentPos;
1321
1322 // width of header column
1323 nCurrentPos += this->GetColumnWidth( 0 );
1324 tSeriesHeaderContainer::iterator aIt( m_aSeriesHeaders.begin());
1325 sal_uInt16 i = this->GetFirstVisibleColumNumber();
1326 while( (aIt != m_aSeriesHeaders.end()) && ((*aIt)->GetStartColumn() < i) )
1327 ++aIt;
1328 for( ; i < nColCount && aIt != m_aSeriesHeaders.end(); ++i )
1329 {
1330 if( (*aIt)->GetStartColumn() == i )
1331 nStartPos = nCurrentPos;
1332
1333 nCurrentPos += (this->GetColumnWidth( i ));
1334
1335 if( (*aIt)->GetEndColumn() == i )
1336 {
1337 if( nStartPos < nMaxPos )
1338 {
1339 (*aIt)->SetPixelPosX( nStartPos + 2 );
1340 (*aIt)->SetPixelWidth( nCurrentPos - nStartPos - 3 );
1341 }
1342 else
1343 // do not hide, to get focus events. Move outside the dialog for "hiding"
1344 (*aIt)->SetPixelPosX( nMaxPos + 42 );
1345 ++aIt;
1346 }
1347 }
1348 }
1349
IMPL_LINK(DataBrowser,SeriesHeaderGotFocus,impl::SeriesHeaderEdit *,pEdit)1350 IMPL_LINK( DataBrowser, SeriesHeaderGotFocus, impl::SeriesHeaderEdit*, pEdit )
1351 {
1352 if( pEdit )
1353 {
1354 pEdit->SetShowWarningBox( !m_bDataValid );
1355
1356 if( !m_bDataValid )
1357 GoToCell( 0, 0 );
1358 else
1359 {
1360 //DeactivateCell();
1361 MakeFieldVisible( GetCurRow(), static_cast< sal_uInt16 >( pEdit->getStartColumn()), true /* bComplete */ );
1362 ActivateCell();
1363 m_aCursorMovedHdlLink.Call( this );
1364 }
1365 }
1366 return 0;
1367 }
1368
IMPL_LINK(DataBrowser,SeriesHeaderChanged,impl::SeriesHeaderEdit *,pEdit)1369 IMPL_LINK( DataBrowser, SeriesHeaderChanged, impl::SeriesHeaderEdit*, pEdit )
1370 {
1371 if( pEdit )
1372 {
1373 Reference< chart2::XDataSeries > xSeries(
1374 m_apDataBrowserModel->getDataSeriesByColumn( pEdit->getStartColumn() - 1 ));
1375 Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY );
1376 if( xSource.is())
1377 {
1378 Reference< chart2::XChartType > xChartType(
1379 m_apDataBrowserModel->getHeaderForSeries( xSeries ).m_xChartType );
1380 if( xChartType.is())
1381 {
1382 Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
1383 DataSeriesHelper::getDataSequenceByRole( xSource, xChartType->getRoleOfSequenceForSeriesLabel()));
1384 if( xLabeledSeq.is())
1385 {
1386 Reference< container::XIndexReplace > xIndexReplace( xLabeledSeq->getLabel(), uno::UNO_QUERY );
1387 if( xIndexReplace.is())
1388 xIndexReplace->replaceByIndex(
1389 0, uno::makeAny( OUString( pEdit->GetText())));
1390 }
1391 }
1392 }
1393 }
1394 return 0;
1395 }
1396
GetTotalWidth() const1397 sal_Int32 DataBrowser::GetTotalWidth() const
1398 {
1399 sal_uLong nWidth = 0;
1400 for ( sal_uInt16 nCol = 0; nCol < ColCount(); ++nCol )
1401 nWidth += GetColumnWidth( nCol );
1402 return static_cast< sal_Int32 >( nWidth );
1403 }
1404
1405 } // namespace chart
1406