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