1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_chart2.hxx" 26 27 #include "tp_DataSource.hxx" 28 #include "tp_DataSource.hrc" 29 #include "Strings.hrc" 30 #include "ResId.hxx" 31 #include "chartview/ChartSfxItemIds.hxx" 32 #include "macros.hxx" 33 #include "ChartTypeTemplateProvider.hxx" 34 #include "RangeSelectionHelper.hxx" 35 #include "DataSeriesHelper.hxx" 36 #include "tp_DataSourceControls.hxx" 37 #include "ControllerLockGuard.hxx" 38 #include "DataSourceHelper.hxx" 39 #include <com/sun/star/sheet/XRangeSelection.hpp> 40 #include <com/sun/star/table/XCellRange.hpp> 41 #include <com/sun/star/chart2/XChartType.hpp> 42 #include <com/sun/star/chart2/XChartTypeTemplate.hpp> 43 #include <com/sun/star/util/XModifiable.hpp> 44 #include <com/sun/star/chart2/data/XDataSink.hpp> 45 46 // for RET_OK 47 #include <vcl/msgbox.hxx> 48 #include <rtl/ustrbuf.hxx> 49 50 #include <functional> 51 #include <algorithm> 52 #include <map> 53 54 using namespace ::com::sun::star; 55 using namespace ::com::sun::star::chart2; 56 57 using ::com::sun::star::uno::Reference; 58 using ::com::sun::star::uno::Sequence; 59 using ::rtl::OUString; 60 using ::rtl::OUStringBuffer; 61 62 // -------------------------------------------------------------------------------- 63 64 namespace 65 { 66 67 const OUString lcl_aLabelRole( RTL_CONSTASCII_USTRINGPARAM( "label" )); 68 69 String lcl_GetRoleLBEntry( 70 const OUString & rRole, const OUString & rRange ) 71 { 72 //IAccessibility2 Implementation 2009----- 73 //String aEntry( rRole ); 74 //aEntry += '\t'; 75 //aEntry += String( 76 // ::chart::DialogModel::ConvertRoleFromInternalToUI( rRole )); 77 String aEntry(::chart::DialogModel::ConvertRoleFromInternalToUI( rRole )); 78 //-----IAccessibility2 Implementation 2009 79 aEntry += '\t'; 80 aEntry += String( rRange ); 81 82 return aEntry; 83 } 84 85 void lcl_UpdateCurrentRange( 86 SvTabListBox & rOutListBox, 87 const OUString & rRole, const OUString & rRange ) 88 { 89 SvLBoxEntry * pEntry = rOutListBox.FirstSelected(); 90 if( pEntry ) 91 rOutListBox.SetEntryText( lcl_GetRoleLBEntry( rRole, rRange ), pEntry ); 92 } 93 94 bool lcl_UpdateCurrentSeriesName( 95 SvTreeListBox & rOutListBox ) 96 { 97 bool bResult = false; 98 ::chart::SeriesEntry * pEntry = dynamic_cast< ::chart::SeriesEntry * >( rOutListBox.FirstSelected()); 99 if( pEntry && 100 pEntry->m_xDataSeries.is() && 101 pEntry->m_xChartType.is()) 102 { 103 String aLabel( ::chart::DataSeriesHelper::getDataSeriesLabel( 104 pEntry->m_xDataSeries, 105 pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel())); 106 if( aLabel.Len()) 107 { 108 rOutListBox.SetEntryText( pEntry, aLabel ); 109 bResult = true; 110 } 111 } 112 return bResult; 113 } 114 115 OUString lcl_GetSelectedRole( const SvTabListBox & rRoleListBox, bool bUITranslated = false ) 116 { 117 OUString aResult; 118 SvLBoxEntry * pEntry = rRoleListBox.FirstSelected(); 119 if( pEntry ) 120 aResult = OUString( rRoleListBox.GetEntryText( pEntry, 121 bUITranslated ? 1 : 0 )); 122 return aResult; 123 } 124 125 OUString lcl_GetSelectedRolesRange( const SvTabListBox & rRoleListBox ) 126 { 127 OUString aResult; 128 SvLBoxEntry * pEntry = rRoleListBox.FirstSelected(); 129 if( pEntry ) 130 aResult = OUString( rRoleListBox.GetEntryText( pEntry, 2 )); 131 return aResult; 132 } 133 134 OUString lcl_GetSequenceNameForLabel( ::chart::SeriesEntry * pEntry ) 135 { 136 OUString aResult( RTL_CONSTASCII_USTRINGPARAM("values-y")); 137 if( pEntry && 138 pEntry->m_xChartType.is()) 139 { 140 aResult = pEntry->m_xChartType->getRoleOfSequenceForSeriesLabel(); 141 } 142 return aResult; 143 } 144 145 //IAccessibility2 Implementation 2009----- 146 static long lcl_pRoleListBoxTabs[] = 147 { 2, // Number of Tabs 148 0, 75 149 }; 150 //-----IAccessibility2 Implementation 2009 151 152 void lcl_ShowChooserButton( 153 ::chart::RangeSelectionButton & rChooserButton, 154 Edit & rEditField, 155 sal_Bool bShow ) 156 { 157 if( rChooserButton.IsVisible() != bShow ) 158 { 159 rChooserButton.Show( bShow ); 160 sal_Int32 nWidhtDiff = 12 + 4; 161 if( bShow ) 162 nWidhtDiff = -nWidhtDiff; 163 Size aSize = rChooserButton.PixelToLogic( rEditField.GetSizePixel(), MAP_APPFONT ); 164 aSize.setWidth( aSize.getWidth() + nWidhtDiff ); 165 rEditField.SetSizePixel( rChooserButton.LogicToPixel( aSize, MAP_APPFONT )); 166 } 167 } 168 169 void lcl_enableRangeChoosing( bool bEnable, Dialog * pDialog ) 170 { 171 if( pDialog ) 172 { 173 pDialog->Show( bEnable ? sal_False : sal_True ); 174 pDialog->SetModalInputMode( bEnable ? sal_False : sal_True ); 175 } 176 } 177 178 void lcl_addLSequenceToDataSource( 179 const Reference< chart2::data::XLabeledDataSequence > & xLSequence, 180 const Reference< chart2::data::XDataSource > & xSource ) 181 { 182 Reference< data::XDataSink > xSink( xSource, uno::UNO_QUERY ); 183 if( xSink.is()) 184 { 185 Sequence< Reference< chart2::data::XLabeledDataSequence > > aData( xSource->getDataSequences()); 186 aData.realloc( aData.getLength() + 1 ); 187 aData[ aData.getLength() - 1 ] = xLSequence; 188 xSink->setData( aData ); 189 } 190 } 191 192 Reference< chart2::data::XLabeledDataSequence > lcl_findLSequenceWithOnlyLabel( 193 const Reference< chart2::data::XDataSource > & xDataSource ) 194 { 195 Reference< chart2::data::XLabeledDataSequence > xResult; 196 Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences()); 197 198 for( sal_Int32 i=0; i<aSequences.getLength(); ++i ) 199 { 200 // no values are set but a label exists 201 if( ! aSequences[i]->getValues().is() && 202 aSequences[i]->getLabel().is()) 203 { 204 xResult.set( aSequences[i] ); 205 break; 206 } 207 } 208 209 return xResult; 210 } 211 212 void lcl_shiftControlY( Control & rControl, long nYOffset ) 213 { 214 Point aPos( rControl.GetPosPixel()); 215 aPos.setY( aPos.getY() + nYOffset ); 216 rControl.SetPosPixel( aPos ); 217 } 218 219 void lcl_increaseHeightOfControl( Control & rControl, long nYOffset ) 220 { 221 Size aSize( rControl.GetSizePixel()); 222 aSize.setHeight( aSize.getHeight () + nYOffset ); 223 rControl.SetSizePixel( aSize ); 224 } 225 226 } // anonymous namespace 227 228 // -------------------------------------------------------------------------------- 229 230 namespace chart 231 { 232 233 DataSourceTabPage::DataSourceTabPage( 234 Window * pParent, 235 DialogModel & rDialogModel, 236 ChartTypeTemplateProvider* pTemplateProvider, 237 Dialog * pParentDialog, 238 bool bHideDescription /* = false */ ) : 239 ::svt::OWizardPage( pParent, SchResId( TP_DATA_SOURCE )), 240 241 m_aFT_CAPTION ( this, SchResId( FT_CAPTION_FOR_WIZARD )), 242 m_aFT_SERIES ( this, SchResId( FT_SERIES )), 243 m_apLB_SERIES( new SeriesListBox( this, SchResId( LB_SERIES ))), 244 m_aBTN_ADD ( this, SchResId( BTN_ADD )), 245 m_aBTN_REMOVE ( this, SchResId( BTN_REMOVE )), 246 m_aBTN_UP ( this, SchResId( BTN_UP )), 247 m_aBTN_DOWN ( this, SchResId( BTN_DOWN )), 248 m_aFT_ROLE ( this, SchResId( FT_ROLE )), 249 m_aLB_ROLE ( this, SchResId( LB_ROLE )), 250 m_aFT_RANGE ( this, SchResId( FT_RANGE )), 251 m_aEDT_RANGE ( this, SchResId( EDT_RANGE )), 252 m_aIMB_RANGE_MAIN ( this, SchResId( IMB_RANGE_MAIN )), 253 m_aFT_CATEGORIES ( this, SchResId( FT_CATEGORIES )), 254 m_aFT_DATALABELS ( this, SchResId( FT_DATALABELS )), 255 m_aEDT_CATEGORIES ( this, SchResId( EDT_CATEGORIES )), 256 m_aIMB_RANGE_CAT ( this, SchResId( IMB_RANGE_CAT )), 257 258 m_pTemplateProvider( pTemplateProvider ), 259 m_rDialogModel( rDialogModel ), 260 261 m_pCurrentRangeChoosingField( 0 ), 262 m_bIsDirty( false ), 263 m_pParentDialog( pParentDialog ), 264 m_pTabPageNotifiable( dynamic_cast< TabPageNotifiable * >( pParentDialog )) 265 { 266 FreeResource(); 267 268 if( bHideDescription ) 269 { 270 // note: the offset should be a negative value for shifting upwards, the 271 // 4 is for the offset difference between a wizard page and a tab-page 272 long nYOffset = - ( m_aFT_SERIES.GetPosPixel().getY() - m_aFT_CAPTION.GetPosPixel().getY() + 4 ); 273 long nUpShift = - 2; 274 long nYResize = - (nYOffset - nUpShift); 275 m_aFT_CAPTION.Hide(); 276 277 // shift list boxes and enlarge them by the space saved by hiding the caption 278 lcl_shiftControlY( m_aFT_SERIES, nYOffset ); 279 lcl_shiftControlY( *(m_apLB_SERIES.get()), nYOffset ); 280 lcl_increaseHeightOfControl( *(m_apLB_SERIES.get()), nYResize ); 281 282 lcl_shiftControlY( m_aFT_ROLE, nYOffset ); 283 lcl_shiftControlY( m_aLB_ROLE, nYOffset ); 284 lcl_increaseHeightOfControl( m_aLB_ROLE, nYResize ); 285 286 lcl_shiftControlY( m_aBTN_ADD, nUpShift ); 287 lcl_shiftControlY( m_aBTN_REMOVE, nUpShift ); 288 lcl_shiftControlY( m_aBTN_UP, nUpShift ); 289 lcl_shiftControlY( m_aBTN_DOWN, nUpShift ); 290 lcl_shiftControlY( m_aFT_RANGE, nUpShift ); 291 lcl_shiftControlY( m_aEDT_RANGE, nUpShift ); 292 lcl_shiftControlY( m_aIMB_RANGE_MAIN, nUpShift ); 293 lcl_shiftControlY( m_aFT_CATEGORIES, nUpShift ); 294 lcl_shiftControlY( m_aFT_DATALABELS, nUpShift ); 295 lcl_shiftControlY( m_aEDT_CATEGORIES, nUpShift ); 296 lcl_shiftControlY( m_aIMB_RANGE_CAT, nUpShift ); 297 } 298 else 299 { 300 // make font of caption bold 301 Font aFont( m_aFT_CAPTION.GetControlFont() ); 302 aFont.SetWeight( WEIGHT_BOLD ); 303 m_aFT_CAPTION.SetControlFont( aFont ); 304 305 // no mnemonic 306 m_aFT_CAPTION.SetStyle( m_aFT_CAPTION.GetStyle() | WB_NOLABEL ); 307 } 308 309 m_aFixedTextRange = OUString( m_aFT_RANGE.GetText() ); 310 this->SetText( String( SchResId( STR_OBJECT_DATASERIES_PLURAL ) ) ); 311 312 // set handlers 313 m_apLB_SERIES->SetSelectHdl( LINK( this, DataSourceTabPage, SeriesSelectionChangedHdl )); 314 315 m_aLB_ROLE.SetStyle( m_aLB_ROLE.GetStyle() | WB_HSCROLL | WB_CLIPCHILDREN ); 316 m_aLB_ROLE.SetSelectionMode( SINGLE_SELECTION ); 317 m_aLB_ROLE.SetSelectHdl( LINK( this, DataSourceTabPage, RoleSelectionChangedHdl )); 318 319 m_aEDT_RANGE.SetKeyInputHdl( LINK( this, DataSourceTabPage, MainRangeButtonClickedHdl )); 320 m_aEDT_CATEGORIES.SetKeyInputHdl( LINK( this, DataSourceTabPage, CategoriesRangeButtonClickedHdl )); 321 322 m_aIMB_RANGE_MAIN.SetClickHdl( LINK( this, DataSourceTabPage, MainRangeButtonClickedHdl )); 323 m_aIMB_RANGE_CAT.SetClickHdl( LINK( this, DataSourceTabPage, CategoriesRangeButtonClickedHdl )); 324 325 m_aBTN_ADD.SetClickHdl( LINK( this, DataSourceTabPage, AddButtonClickedHdl )); 326 m_aBTN_REMOVE.SetClickHdl( LINK( this, DataSourceTabPage, RemoveButtonClickedHdl )); 327 328 m_aBTN_UP.SetClickHdl( LINK( this, DataSourceTabPage, UpButtonClickedHdl )); 329 m_aBTN_DOWN.SetClickHdl( LINK( this, DataSourceTabPage, DownButtonClickedHdl )); 330 331 m_aEDT_RANGE.SetModifyHdl( LINK( this, DataSourceTabPage, RangeModifiedHdl )); 332 m_aEDT_CATEGORIES.SetModifyHdl( LINK( this, DataSourceTabPage, RangeModifiedHdl )); 333 m_aEDT_RANGE.SetUpdateDataHdl( LINK( this, DataSourceTabPage, RangeUpdateDataHdl )); 334 m_aEDT_CATEGORIES.SetUpdateDataHdl( LINK( this, DataSourceTabPage, RangeUpdateDataHdl )); 335 336 // #i75179# enable setting the background to a different color 337 m_aEDT_RANGE.SetStyle( m_aEDT_RANGE.GetStyle() | WB_FORCECTRLBACKGROUND ); 338 m_aEDT_CATEGORIES.SetStyle( m_aEDT_CATEGORIES.GetStyle() | WB_FORCECTRLBACKGROUND ); 339 340 // set symbol font for arrows 341 // note: StarSymbol is substituted to OpenSymbol for OOo 342 Font aSymbolFont( m_aBTN_UP.GetFont()); 343 aSymbolFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "StarSymbol" ))); 344 m_aBTN_UP.SetControlFont( aSymbolFont ); 345 m_aBTN_DOWN.SetControlFont( aSymbolFont ); 346 347 // set button text 348 sal_Unicode cBlackUpPointingTriangle( 0x25b2 ); 349 sal_Unicode cBlackDownPointingTriangle( 0x25bc ); 350 m_aBTN_UP.SetText( String( cBlackUpPointingTriangle )); 351 m_aBTN_DOWN.SetText( String( cBlackDownPointingTriangle )); 352 353 // init controls 354 m_aLB_ROLE.SetTabs( lcl_pRoleListBoxTabs, MAP_APPFONT ); 355 m_aLB_ROLE.Show(); 356 357 updateControlsFromDialogModel(); 358 359 // select first series 360 if( m_apLB_SERIES->First()) 361 m_apLB_SERIES->Select( m_apLB_SERIES->First()); 362 m_apLB_SERIES->GrabFocus(); 363 m_aBTN_UP.SetAccessibleName(String(SchResId(STR_BUTTON_UP))); 364 m_aBTN_DOWN.SetAccessibleName(String(SchResId(STR_BUTTON_DOWN))); 365 } 366 367 DataSourceTabPage::~DataSourceTabPage() 368 {} 369 370 void DataSourceTabPage::ActivatePage() 371 { 372 OWizardPage::ActivatePage(); 373 updateControlsFromDialogModel(); 374 } 375 376 void DataSourceTabPage::initializePage() 377 { 378 } 379 380 void DataSourceTabPage::DeactivatePage() 381 { 382 commitPage(); 383 svt::OWizardPage::DeactivatePage(); 384 } 385 386 void DataSourceTabPage::commitPage() 387 { 388 commitPage(::svt::WizardTypes::eFinish); 389 } 390 391 sal_Bool DataSourceTabPage::commitPage( ::svt::WizardTypes::CommitPageReason /*eReason*/ ) 392 { 393 //ranges may have been edited in the meanwhile (dirty is true in that case here) 394 if( isValid() ) 395 { 396 updateModelFromControl( 0 /*update all*/ ); 397 return sal_True;//return false if this page should not be left 398 } 399 else 400 return sal_False; 401 } 402 403 bool DataSourceTabPage::isRangeFieldContentValid( Edit & rEdit ) 404 { 405 OUString aRange( rEdit.GetText()); 406 bool bIsValid = ( aRange.getLength() == 0 ) || 407 m_rDialogModel.getRangeSelectionHelper()->verifyCellRange( aRange ); 408 409 if( bIsValid ) 410 { 411 rEdit.SetControlForeground(); 412 rEdit.SetControlBackground(); 413 } 414 else 415 { 416 rEdit.SetControlBackground( RANGE_SELECTION_INVALID_RANGE_BACKGROUND_COLOR ); 417 rEdit.SetControlForeground( RANGE_SELECTION_INVALID_RANGE_FOREGROUND_COLOR ); 418 } 419 420 return bIsValid; 421 } 422 423 bool DataSourceTabPage::isValid() 424 { 425 bool bRoleRangeValid = true; 426 bool bCategoriesRangeValid = true; 427 bool bHasSelectedEntry = (m_apLB_SERIES->FirstSelected() != 0); 428 429 if( bHasSelectedEntry ) 430 bRoleRangeValid = isRangeFieldContentValid( m_aEDT_RANGE ); 431 if( m_aEDT_CATEGORIES.IsEnabled() ) 432 bCategoriesRangeValid = isRangeFieldContentValid( m_aEDT_CATEGORIES ); 433 bool bValid = ( bRoleRangeValid && bCategoriesRangeValid ); 434 435 if( m_pTabPageNotifiable ) 436 { 437 if( bValid ) 438 m_pTabPageNotifiable->setValidPage( this ); 439 else 440 m_pTabPageNotifiable->setInvalidPage( this ); 441 } 442 443 return bValid; 444 } 445 446 void DataSourceTabPage::setDirty() 447 { 448 m_bIsDirty = true; 449 } 450 451 void DataSourceTabPage::updateControlsFromDialogModel() 452 { 453 // series 454 fillSeriesListBox(); 455 SeriesSelectionChangedHdl( 0 ); 456 457 // categories 458 m_aEDT_CATEGORIES.SetText( String( m_rDialogModel.getCategoriesRange() )); 459 460 updateControlState(); 461 } 462 463 void DataSourceTabPage::fillSeriesListBox() 464 { 465 m_apLB_SERIES->SetUpdateMode( sal_False ); 466 467 Reference< XDataSeries > xSelected; 468 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_apLB_SERIES->FirstSelected()); 469 if( pEntry ) 470 xSelected.set( pEntry->m_xDataSeries ); 471 472 bool bHasSelectedEntry = (pEntry != 0); 473 SvLBoxEntry * pSelectedEntry = 0; 474 m_apLB_SERIES->Clear(); 475 476 ::std::vector< DialogModel::tSeriesWithChartTypeByName > aSeries( 477 m_rDialogModel.getAllDataSeriesWithLabel() ); 478 479 sal_Int32 nUnnamedSeriesIndex = 1; 480 for( ::std::vector< DialogModel::tSeriesWithChartTypeByName >::const_iterator aIt = aSeries.begin(); 481 aIt != aSeries.end(); ++aIt ) 482 { 483 String aLabel( (*aIt).first ); 484 if( !aLabel.Len()) 485 { 486 if( nUnnamedSeriesIndex > 1 ) 487 { 488 OUString aResString( String( ::chart::SchResId( STR_DATA_UNNAMED_SERIES_WITH_INDEX ))); 489 490 // replace index of unnamed series 491 const OUString aReplacementStr( RTL_CONSTASCII_USTRINGPARAM( "%NUMBER" )); 492 sal_Int32 nIndex = aResString.indexOf( aReplacementStr ); 493 if( nIndex != -1 ) 494 aLabel = String( aResString.replaceAt( 495 nIndex, aReplacementStr.getLength(), 496 String::CreateFromInt32( nUnnamedSeriesIndex ))); 497 } 498 if( aLabel.Len() == 0 ) 499 aLabel = String( ::chart::SchResId( STR_DATA_UNNAMED_SERIES )); 500 501 ++nUnnamedSeriesIndex; 502 } 503 pEntry = dynamic_cast< SeriesEntry * >( 504 m_apLB_SERIES->InsertEntry( aLabel )); 505 if( pEntry ) 506 { 507 pEntry->m_xDataSeries.set( (*aIt).second.first ); 508 pEntry->m_xChartType.set( (*aIt).second.second ); 509 if( bHasSelectedEntry && ((*aIt).second.first == xSelected)) 510 pSelectedEntry = pEntry; 511 } 512 } 513 514 if( bHasSelectedEntry && pSelectedEntry ) 515 m_apLB_SERIES->Select( pSelectedEntry ); 516 517 m_apLB_SERIES->SetUpdateMode( sal_True ); 518 } 519 520 void DataSourceTabPage::fillRoleListBox() 521 { 522 SeriesEntry * pSeriesEntry = dynamic_cast< SeriesEntry * >( m_apLB_SERIES->FirstSelected()); 523 bool bHasSelectedEntry = (pSeriesEntry != 0); 524 525 SvLBoxEntry * pRoleEntry = m_aLB_ROLE.FirstSelected(); 526 sal_uLong nRoleIndex = SAL_MAX_UINT32; 527 if( pRoleEntry ) 528 nRoleIndex = m_aLB_ROLE.GetModel()->GetAbsPos( pRoleEntry ); 529 530 if( bHasSelectedEntry ) 531 { 532 DialogModel::tRolesWithRanges aRoles( 533 m_rDialogModel.getRolesWithRanges( 534 pSeriesEntry->m_xDataSeries, 535 lcl_GetSequenceNameForLabel( pSeriesEntry ), 536 pSeriesEntry->m_xChartType )); 537 538 // fill role list 539 m_aLB_ROLE.SetUpdateMode( sal_False ); 540 m_aLB_ROLE.Clear(); 541 m_aLB_ROLE.RemoveSelection(); 542 543 for( DialogModel::tRolesWithRanges::const_iterator aIt( aRoles.begin()); 544 aIt != aRoles.end(); ++ aIt ) 545 { 546 m_aLB_ROLE.InsertEntry( lcl_GetRoleLBEntry( aIt->first, aIt->second )); 547 } 548 549 // series may contain no roles, check listbox size before selecting entries 550 if( m_aLB_ROLE.GetEntryCount() > 0 ) 551 { 552 if( nRoleIndex >= m_aLB_ROLE.GetEntryCount()) 553 nRoleIndex = 0; 554 m_aLB_ROLE.Select( m_aLB_ROLE.GetEntry( nRoleIndex )); 555 } 556 557 m_aLB_ROLE.SetUpdateMode( sal_True ); 558 } 559 } 560 561 void DataSourceTabPage::updateControlState() 562 { 563 SvLBoxEntry * pSeriesEntry = m_apLB_SERIES->FirstSelected(); 564 bool bHasSelectedSeries = (pSeriesEntry != 0); 565 bool bHasValidRole = false; 566 bool bHasRangeChooser = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection(); 567 568 if( bHasSelectedSeries ) 569 { 570 SvLBoxEntry * pRoleEntry = m_aLB_ROLE.FirstSelected(); 571 bHasValidRole = (pRoleEntry != 0); 572 } 573 574 m_aBTN_ADD.Enable( true ); 575 m_aBTN_REMOVE.Enable( bHasSelectedSeries ); 576 577 m_aBTN_UP.Enable( bHasSelectedSeries && (pSeriesEntry != m_apLB_SERIES->First())); 578 m_aBTN_DOWN.Enable( bHasSelectedSeries && (pSeriesEntry != m_apLB_SERIES->Last())); 579 580 bool bHasCategories = m_rDialogModel.isCategoryDiagram(); 581 582 m_aFT_DATALABELS.Show(!bHasCategories); 583 m_aFT_CATEGORIES.Show( bHasCategories); 584 sal_Bool bShowIB = bHasRangeChooser; 585 lcl_ShowChooserButton( m_aIMB_RANGE_CAT, m_aEDT_CATEGORIES, bShowIB ); 586 587 m_aFT_SERIES.Enable(); 588 m_apLB_SERIES->Enable(); 589 590 m_aFT_ROLE.Enable( bHasSelectedSeries ); 591 m_aLB_ROLE.Enable( bHasSelectedSeries ); 592 593 m_aFT_RANGE.Enable( bHasValidRole ); 594 m_aEDT_RANGE.Enable( bHasValidRole ); 595 lcl_ShowChooserButton( m_aIMB_RANGE_MAIN, m_aEDT_RANGE, bShowIB ); 596 isValid(); 597 } 598 599 IMPL_LINK( DataSourceTabPage, SeriesSelectionChangedHdl, void *, EMPTYARG ) 600 { 601 m_rDialogModel.startControllerLockTimer(); 602 if( m_apLB_SERIES->FirstSelected()) 603 { 604 fillRoleListBox(); 605 RoleSelectionChangedHdl( 0 ); 606 } 607 updateControlState(); 608 609 return 0; 610 } 611 612 IMPL_LINK( DataSourceTabPage, RoleSelectionChangedHdl, void *, EMPTYARG ) 613 { 614 m_rDialogModel.startControllerLockTimer(); 615 SvLBoxEntry * pEntry = m_aLB_ROLE.FirstSelected(); 616 if( pEntry ) 617 { 618 OUString aRange( m_aEDT_RANGE.GetText()); 619 OUString aSelectedRoleUI = lcl_GetSelectedRole( m_aLB_ROLE, true ); 620 OUString aSelectedRange = lcl_GetSelectedRolesRange( m_aLB_ROLE ); 621 622 // replace role in fixed text label 623 const OUString aReplacementStr( RTL_CONSTASCII_USTRINGPARAM( "%VALUETYPE" )); 624 sal_Int32 nIndex = m_aFixedTextRange.indexOf( aReplacementStr ); 625 if( nIndex != -1 ) 626 { 627 m_aFT_RANGE.SetText( 628 String( m_aFixedTextRange.replaceAt( 629 nIndex, aReplacementStr.getLength(), aSelectedRoleUI ))); 630 } 631 632 m_aEDT_RANGE.SetText( String( aSelectedRange )); 633 isValid(); 634 } 635 636 return 0; 637 } 638 639 IMPL_LINK( DataSourceTabPage, MainRangeButtonClickedHdl, void *, EMPTYARG ) 640 { 641 OSL_ASSERT( m_pCurrentRangeChoosingField == 0 ); 642 m_pCurrentRangeChoosingField = & m_aEDT_RANGE; 643 if( m_aEDT_RANGE.GetText().Len() > 0 && 644 ! updateModelFromControl( m_pCurrentRangeChoosingField )) 645 return 0; 646 647 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_apLB_SERIES->FirstSelected()); 648 bool bHasSelectedEntry = (pEntry != 0); 649 650 OUString aSelectedRolesRange = lcl_GetSelectedRolesRange( m_aLB_ROLE ); 651 652 if( bHasSelectedEntry && (m_aLB_ROLE.FirstSelected() != 0)) 653 { 654 String aStr( SchResId( STR_DATA_SELECT_RANGE_FOR_SERIES )); 655 OUString aUIStr( aStr ); 656 657 // replace role 658 OUString aReplacement( RTL_CONSTASCII_USTRINGPARAM( "%VALUETYPE" )); 659 sal_Int32 nIndex = aUIStr.indexOf( aReplacement ); 660 if( nIndex != -1 ) 661 { 662 aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(), 663 lcl_GetSelectedRole( m_aLB_ROLE, true )); 664 } 665 // replace series name 666 aReplacement = C2U( "%SERIESNAME" ); 667 nIndex = aUIStr.indexOf( aReplacement ); 668 if( nIndex != -1 ) 669 { 670 aUIStr = aUIStr.replaceAt( nIndex, aReplacement.getLength(), 671 OUString( m_apLB_SERIES->GetEntryText( pEntry ))); 672 } 673 674 lcl_enableRangeChoosing( true, m_pParentDialog ); 675 m_rDialogModel.getRangeSelectionHelper()->chooseRange( aSelectedRolesRange, aUIStr, *this ); 676 } 677 else 678 m_pCurrentRangeChoosingField = 0; 679 680 return 0; 681 } 682 683 IMPL_LINK( DataSourceTabPage, CategoriesRangeButtonClickedHdl, void *, EMPTYARG ) 684 { 685 OSL_ASSERT( m_pCurrentRangeChoosingField == 0 ); 686 m_pCurrentRangeChoosingField = & m_aEDT_CATEGORIES; 687 if( m_aEDT_CATEGORIES.GetText().Len() > 0 && 688 ! updateModelFromControl( m_pCurrentRangeChoosingField )) 689 return 0; 690 691 String aStr( SchResId( m_aFT_CATEGORIES.IsVisible() ? STR_DATA_SELECT_RANGE_FOR_CATEGORIES : STR_DATA_SELECT_RANGE_FOR_DATALABELS )); 692 lcl_enableRangeChoosing( true, m_pParentDialog ); 693 m_rDialogModel.getRangeSelectionHelper()->chooseRange( 694 m_rDialogModel.getCategoriesRange(), OUString( aStr ), *this ); 695 return 0; 696 } 697 698 IMPL_LINK( DataSourceTabPage, AddButtonClickedHdl, void *, EMPTYARG ) 699 { 700 m_rDialogModel.startControllerLockTimer(); 701 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_apLB_SERIES->FirstSelected()); 702 Reference< XDataSeries > xSeriesToInsertAfter; 703 Reference< XChartType > xChartTypeForNewSeries; 704 if( m_pTemplateProvider ) 705 m_rDialogModel.setTemplate( m_pTemplateProvider->getCurrentTemplate()); 706 707 if( pEntry ) 708 { 709 xSeriesToInsertAfter.set( pEntry->m_xDataSeries ); 710 xChartTypeForNewSeries.set( pEntry->m_xChartType ); 711 } 712 else 713 { 714 ::std::vector< Reference< XDataSeriesContainer > > aCntVec( 715 m_rDialogModel.getAllDataSeriesContainers()); 716 if( ! aCntVec.empty()) 717 xChartTypeForNewSeries.set( aCntVec.front(), uno::UNO_QUERY ); 718 } 719 OSL_ENSURE( xChartTypeForNewSeries.is(), "Cannot insert new series" ); 720 721 m_rDialogModel.insertSeriesAfter( xSeriesToInsertAfter, xChartTypeForNewSeries ); 722 setDirty(); 723 724 fillSeriesListBox(); 725 // note the box was cleared and refilled, so pEntry is invalid now 726 SvLBoxEntry * pSelEntry = m_apLB_SERIES->FirstSelected(); 727 if( pSelEntry ) 728 { 729 SvLBoxEntry * pNextEntry = m_apLB_SERIES->Next( pSelEntry ); 730 if( pNextEntry ) 731 m_apLB_SERIES->Select( pNextEntry ); 732 } 733 SeriesSelectionChangedHdl( 0 ); 734 735 return 0; 736 } 737 738 IMPL_LINK( DataSourceTabPage, RemoveButtonClickedHdl, void *, EMPTYARG ) 739 { 740 m_rDialogModel.startControllerLockTimer(); 741 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_apLB_SERIES->FirstSelected()); 742 if( pEntry ) 743 { 744 Reference< XDataSeries > xNewSelSeries; 745 SeriesEntry * pNewSelEntry = dynamic_cast< SeriesEntry * >( 746 m_apLB_SERIES->Next( pEntry )); 747 if( pNewSelEntry ) 748 xNewSelSeries.set( pNewSelEntry->m_xDataSeries ); 749 else 750 { 751 pNewSelEntry = dynamic_cast< SeriesEntry * >( m_apLB_SERIES->Prev( pEntry )); 752 if( pNewSelEntry ) 753 xNewSelSeries.set( pNewSelEntry->m_xDataSeries ); 754 } 755 756 m_rDialogModel.deleteSeries( pEntry->m_xDataSeries, pEntry->m_xChartType ); 757 setDirty(); 758 759 m_apLB_SERIES->RemoveSelection(); 760 fillSeriesListBox(); 761 762 // select previous or next series 763 //@improve: see methods GetModel()->GetAbsPos()/GetEntry() for absoulte list positions 764 if( xNewSelSeries.is()) 765 { 766 pEntry = dynamic_cast< SeriesEntry * >( m_apLB_SERIES->First()); 767 while( pEntry ) 768 { 769 if( pEntry->m_xDataSeries == xNewSelSeries ) 770 { 771 m_apLB_SERIES->Select( pEntry ); 772 break; 773 } 774 pEntry = dynamic_cast< SeriesEntry * >( m_apLB_SERIES->Next( pEntry )); 775 } 776 } 777 SeriesSelectionChangedHdl( 0 ); 778 } 779 780 return 0; 781 } 782 783 IMPL_LINK( DataSourceTabPage, UpButtonClickedHdl, void *, EMPTYARG ) 784 { 785 m_rDialogModel.startControllerLockTimer(); 786 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_apLB_SERIES->FirstSelected()); 787 bool bHasSelectedEntry = (pEntry != 0); 788 789 if( bHasSelectedEntry ) 790 { 791 m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MOVE_UP ); 792 setDirty(); 793 fillSeriesListBox(); 794 SeriesSelectionChangedHdl(0); 795 } 796 797 return 0; 798 } 799 800 IMPL_LINK( DataSourceTabPage, DownButtonClickedHdl, void *, EMPTYARG ) 801 { 802 m_rDialogModel.startControllerLockTimer(); 803 SeriesEntry * pEntry = dynamic_cast< SeriesEntry * >( m_apLB_SERIES->FirstSelected()); 804 bool bHasSelectedEntry = (pEntry != 0); 805 806 if( bHasSelectedEntry ) 807 { 808 m_rDialogModel.moveSeries( pEntry->m_xDataSeries, DialogModel::MOVE_DOWN ); 809 setDirty(); 810 fillSeriesListBox(); 811 SeriesSelectionChangedHdl(0); 812 } 813 814 return 0; 815 } 816 817 IMPL_LINK( DataSourceTabPage, RangeModifiedHdl, Edit*, pEdit ) 818 { 819 if( isRangeFieldContentValid( *pEdit )) 820 setDirty(); 821 822 // enable/disable OK button 823 isValid(); 824 825 return 0; 826 } 827 828 IMPL_LINK( DataSourceTabPage, RangeUpdateDataHdl, Edit*, pEdit ) 829 { 830 // note: isValid sets the color of the edit field 831 if( isRangeFieldContentValid( *pEdit )) 832 { 833 setDirty(); 834 updateModelFromControl( pEdit ); 835 if( pEdit== &m_aEDT_RANGE ) 836 { 837 if( ! lcl_UpdateCurrentSeriesName( *m_apLB_SERIES )) 838 fillSeriesListBox(); 839 } 840 } 841 // enable/disable OK button 842 isValid(); 843 844 return 0; 845 } 846 847 void DataSourceTabPage::listeningFinished( 848 const ::rtl::OUString & rNewRange ) 849 { 850 // rNewRange becomes invalid after removing the listener 851 OUString aRange( rNewRange ); 852 853 m_rDialogModel.startControllerLockTimer(); 854 855 // stop listening 856 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening(); 857 858 // change edit field 859 ToTop(); 860 GrabFocus(); 861 if( m_pCurrentRangeChoosingField ) 862 { 863 m_pCurrentRangeChoosingField->SetText( String( aRange )); 864 m_pCurrentRangeChoosingField->GrabFocus(); 865 } 866 867 if( m_pCurrentRangeChoosingField == & m_aEDT_RANGE ) 868 { 869 m_aEDT_RANGE.SetText( String( aRange )); 870 setDirty(); 871 } 872 else if( m_pCurrentRangeChoosingField == & m_aEDT_CATEGORIES ) 873 { 874 m_aEDT_CATEGORIES.SetText( String( aRange )); 875 setDirty(); 876 } 877 878 updateModelFromControl( m_pCurrentRangeChoosingField ); 879 if( ! lcl_UpdateCurrentSeriesName( *m_apLB_SERIES )) 880 fillSeriesListBox(); 881 882 m_pCurrentRangeChoosingField = 0; 883 884 updateControlState(); 885 lcl_enableRangeChoosing( false, m_pParentDialog ); 886 } 887 888 void DataSourceTabPage::disposingRangeSelection() 889 { 890 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false ); 891 } 892 893 bool DataSourceTabPage::updateModelFromControl( Edit * pField ) 894 { 895 if( !m_bIsDirty ) 896 return true; 897 898 ControllerLockGuard aLockedControllers( m_rDialogModel.getChartModel() ); 899 900 // @todo: validity check of field content 901 bool bResult = true; 902 bool bAll = (pField == 0); 903 Reference< data::XDataProvider > xDataProvider( m_rDialogModel.getDataProvider()); 904 905 if( bAll || (pField == & m_aEDT_CATEGORIES) ) 906 { 907 Reference< data::XLabeledDataSequence > xLabeledSeq( m_rDialogModel.getCategories() ); 908 if( xDataProvider.is()) 909 { 910 OUString aRange( m_aEDT_CATEGORIES.GetText()); 911 if( aRange.getLength()) 912 { 913 // create or change categories 914 if( !xLabeledSeq.is()) 915 { 916 xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0))); 917 m_rDialogModel.setCategories( xLabeledSeq ); 918 } 919 try 920 { 921 xLabeledSeq->setValues( xDataProvider->createDataSequenceByRangeRepresentation( aRange )); 922 } 923 catch( const uno::Exception & ex ) 924 { 925 // should work as validation should have happened before 926 ASSERT_EXCEPTION( ex ); 927 } 928 } 929 else if( xLabeledSeq.is()) 930 { 931 // clear existing categories 932 xLabeledSeq.set(0); 933 m_rDialogModel.setCategories( xLabeledSeq ); 934 } 935 } 936 } 937 938 SeriesEntry * pSeriesEntry = dynamic_cast< SeriesEntry * >( m_apLB_SERIES->FirstSelected()); 939 bool bHasSelectedEntry = (pSeriesEntry != 0); 940 941 if( bHasSelectedEntry ) 942 { 943 if( bAll || (pField == & m_aEDT_RANGE) ) 944 { 945 try 946 { 947 OUString aSelectedRole = lcl_GetSelectedRole( m_aLB_ROLE ); 948 OUString aRange( m_aEDT_RANGE.GetText()); 949 OUString aSequenceRole( aSelectedRole ); 950 bool bIsLabel = aSequenceRole.equals( lcl_aLabelRole ); 951 OUString aSequenceNameForLabel( lcl_GetSequenceNameForLabel( pSeriesEntry )); 952 953 if( bIsLabel ) 954 aSequenceRole = aSequenceNameForLabel; 955 956 Reference< data::XDataSource > xSource( pSeriesEntry->m_xDataSeries, uno::UNO_QUERY_THROW ); 957 Reference< data::XLabeledDataSequence > xLabeledSeq( 958 DataSeriesHelper::getDataSequenceByRole( xSource, aSequenceRole )); 959 960 if( xDataProvider.is()) 961 { 962 if( bIsLabel ) 963 { 964 if( ! xLabeledSeq.is()) 965 { 966 // check if there is already an "orphan" label sequence 967 xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource )); 968 if( ! xLabeledSeq.is()) 969 { 970 // no corresponding labeled data sequence for label found 971 xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0))); 972 lcl_addLSequenceToDataSource( xLabeledSeq, xSource ); 973 } 974 } 975 if( xLabeledSeq.is()) 976 { 977 if( aRange.getLength()) 978 { 979 Reference< data::XDataSequence > xNewSeq; 980 try 981 { 982 xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange )); 983 } 984 catch( const uno::Exception & ex ) 985 { 986 // should work as validation should have happened before 987 ASSERT_EXCEPTION( ex ); 988 } 989 if( xNewSeq.is()) 990 { 991 // update range name by the full string provided 992 // by the data provider. E.g. "a1" might become 993 // "$Sheet1.$A$1" 994 aRange = xNewSeq->getSourceRangeRepresentation(); 995 Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW ); 996 xProp->setPropertyValue( C2U("Role"), uno::makeAny( lcl_aLabelRole )); 997 xLabeledSeq->setLabel( xNewSeq ); 998 } 999 } 1000 else 1001 { 1002 xLabeledSeq->setLabel( Reference< data::XDataSequence >()); 1003 } 1004 } 1005 } 1006 else 1007 { 1008 if( aRange.getLength()) 1009 { 1010 Reference< data::XDataSequence > xNewSeq; 1011 try 1012 { 1013 xNewSeq.set( xDataProvider->createDataSequenceByRangeRepresentation( aRange )); 1014 } 1015 catch( const uno::Exception & ex ) 1016 { 1017 // should work as validation should have happened before 1018 ASSERT_EXCEPTION( ex ); 1019 } 1020 if( xNewSeq.is()) 1021 { 1022 // update range name by the full string provided 1023 // by the data provider. E.g. "a1:e1" might become 1024 // "$Sheet1.$A$1:$E$1" 1025 aRange = xNewSeq->getSourceRangeRepresentation(); 1026 1027 Reference< beans::XPropertySet > xProp( xNewSeq, uno::UNO_QUERY_THROW ); 1028 xProp->setPropertyValue( C2U("Role"), uno::makeAny( aSelectedRole )); 1029 if( !xLabeledSeq.is()) 1030 { 1031 if( aSelectedRole.equals( aSequenceNameForLabel )) 1032 xLabeledSeq.set( lcl_findLSequenceWithOnlyLabel( xSource )); 1033 if( ! xLabeledSeq.is()) 1034 { 1035 xLabeledSeq.set( DataSourceHelper::createLabeledDataSequence( Reference< uno::XComponentContext >(0))); 1036 lcl_addLSequenceToDataSource( xLabeledSeq, xSource ); 1037 } 1038 } 1039 xLabeledSeq->setValues( xNewSeq ); 1040 } 1041 } 1042 else if( xLabeledSeq.is()) 1043 { 1044 // values cannot be deleted. This would also delete the Role (for labels) 1045 // xLabeledSeq->setValues( Reference< data::XDataSequence >()); 1046 } 1047 } 1048 } 1049 1050 lcl_UpdateCurrentRange( m_aLB_ROLE, aSelectedRole, aRange ); 1051 } 1052 catch( uno::Exception & ex ) 1053 { 1054 bResult = false; 1055 ASSERT_EXCEPTION( ex ); 1056 } 1057 } 1058 } 1059 1060 // update View 1061 // @todo remove this when automatic view updates from calc, writer and own data sequences are available 1062 if( bResult ) 1063 { 1064 try 1065 { 1066 Reference< util::XModifiable > xModifiable( m_rDialogModel.getChartModel(), uno::UNO_QUERY ); 1067 if( xModifiable.is() ) 1068 xModifiable->setModified( sal_True ); 1069 } 1070 catch( uno::Exception & ex ) 1071 { 1072 ASSERT_EXCEPTION( ex ); 1073 } 1074 } 1075 1076 return bResult; 1077 } 1078 1079 } // namespace chart 1080