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