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