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