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 #include "tp_RangeChooser.hxx" 32 #include "tp_RangeChooser.hrc" 33 #include "Strings.hrc" 34 #include "ResId.hxx" 35 #include "macros.hxx" 36 #include "NoWarningThisInCTOR.hxx" 37 #include "DataSourceHelper.hxx" 38 #include "DiagramHelper.hxx" 39 #include "ChartTypeTemplateProvider.hxx" 40 #include "DialogModel.hxx" 41 #include "RangeSelectionHelper.hxx" 42 #include <com/sun/star/awt/XTopWindow.hpp> 43 #include <com/sun/star/embed/EmbedStates.hpp> 44 #include <com/sun/star/embed/XComponentSupplier.hpp> 45 46 namespace 47 { 48 void lcl_ShowChooserButton( 49 ::chart::RangeSelectionButton & rChooserButton, 50 Edit & rEditField, 51 sal_Bool bShow ) 52 { 53 if( rChooserButton.IsVisible() != bShow ) 54 { 55 rChooserButton.Show( bShow ); 56 sal_Int32 nWidhtDiff = 10 + 2; 57 if( bShow ) 58 nWidhtDiff = -nWidhtDiff; 59 Size aSize = rChooserButton.PixelToLogic( rEditField.GetSizePixel(), MAP_APPFONT ); 60 aSize.setWidth( aSize.getWidth() + nWidhtDiff ); 61 rEditField.SetSizePixel( rChooserButton.LogicToPixel( aSize, MAP_APPFONT )); 62 } 63 } 64 void lcl_enableRangeChoosing( bool bEnable, Dialog * pDialog ) 65 { 66 if( pDialog ) 67 { 68 pDialog->Show( bEnable ? sal_False : sal_True ); 69 pDialog->SetModalInputMode( bEnable ? sal_False : sal_True ); 70 } 71 } 72 void lcl_shiftControlY( Control & rControl, long nYOffset ) 73 { 74 Point aPos( rControl.GetPosPixel()); 75 aPos.setY( aPos.getY() + nYOffset ); 76 rControl.SetPosPixel( aPos ); 77 } 78 } // anonymous namespace 79 80 //............................................................................. 81 namespace chart 82 { 83 //............................................................................. 84 using namespace ::com::sun::star; 85 using namespace ::com::sun::star::chart2; 86 87 using ::com::sun::star::uno::Reference; 88 using ::com::sun::star::uno::Sequence; 89 90 91 RangeChooserTabPage::RangeChooserTabPage( Window* pParent 92 , DialogModel & rDialogModel 93 , ChartTypeTemplateProvider* pTemplateProvider 94 , Dialog * pParentDialog 95 , bool bHideDescription /* = false */ ) 96 97 : OWizardPage( pParent, SchResId(TP_RANGECHOOSER) ) 98 99 , m_aFT_Caption( this, SchResId( FT_CAPTION_FOR_WIZARD ) ) 100 , m_aFT_Range( this, SchResId( FT_RANGE ) ) 101 , m_aED_Range( this, SchResId( ED_RANGE ) ) 102 , m_aIB_Range( this, SchResId( IB_RANGE ) ) 103 , m_aRB_Rows( this, SchResId( RB_DATAROWS ) ) 104 , m_aRB_Columns( this, SchResId( RB_DATACOLS ) ) 105 , m_aCB_FirstRowAsLabel( this, SchResId( CB_FIRST_ROW_ASLABELS ) ) 106 , m_aCB_FirstColumnAsLabel( this, SchResId( CB_FIRST_COLUMN_ASLABELS ) ) 107 , m_nChangingControlCalls(0) 108 , m_bIsDirty(false) 109 , m_xDataProvider( 0 ) 110 , m_aLastValidRangeString() 111 , m_xCurrentChartTypeTemplate(0) 112 , m_pTemplateProvider(pTemplateProvider) 113 , m_rDialogModel( rDialogModel ) 114 , m_pParentDialog( pParentDialog ) 115 , m_pTabPageNotifiable( dynamic_cast< TabPageNotifiable * >( pParentDialog )) 116 { 117 FreeResource(); 118 119 if( bHideDescription ) 120 { 121 // note: the offset should be a negative value for shifting upwards, the 122 // 4 is for the offset difference between a wizard page and a tab-page 123 long nYOffset = - ( m_aFT_Range.GetPosPixel().getY() - m_aFT_Caption.GetPosPixel().getY() + 4 ); 124 m_aFT_Caption.Hide(); 125 126 // shift all controls by the offset space saved by hiding the caption 127 lcl_shiftControlY( m_aFT_Range, nYOffset ); 128 lcl_shiftControlY( m_aED_Range, nYOffset ); 129 lcl_shiftControlY( m_aIB_Range, nYOffset ); 130 lcl_shiftControlY( m_aRB_Rows, nYOffset ); 131 lcl_shiftControlY( m_aRB_Columns, nYOffset ); 132 lcl_shiftControlY( m_aCB_FirstRowAsLabel, nYOffset ); 133 lcl_shiftControlY( m_aCB_FirstColumnAsLabel, nYOffset ); 134 } 135 else 136 { 137 // make font of caption bold 138 Font aFont( m_aFT_Caption.GetControlFont() ); 139 aFont.SetWeight( WEIGHT_BOLD ); 140 m_aFT_Caption.SetControlFont( aFont ); 141 142 // no mnemonic 143 m_aFT_Caption.SetStyle( m_aFT_Caption.GetStyle() | WB_NOLABEL ); 144 } 145 146 this->SetText( String(SchResId(STR_PAGE_DATA_RANGE)) ); 147 m_aIB_Range.SetQuickHelpText( String(SchResId(STR_TIP_SELECT_RANGE)) ); 148 149 // set defaults as long as DetectArguments does not work 150 m_aRB_Columns.Check(); 151 m_aCB_FirstColumnAsLabel.Check(); 152 m_aCB_FirstRowAsLabel.Check(); 153 154 // BM: Note, that the range selection is not available, if there is no view. 155 // This happens for charts having their own embedded spreadsheet. If you 156 // force to get the range selection here, this would mean when entering this 157 // page the calc view would be created in this case. So, I enable the 158 // button here, and in the worst case nothing happens when it is pressed. 159 // Not nice, but I see no better solution for the moment. 160 m_aIB_Range.SetClickHdl( LINK( this, RangeChooserTabPage, ChooseRangeHdl )); 161 m_aED_Range.SetKeyInputHdl( LINK( this, RangeChooserTabPage, ChooseRangeHdl )); 162 163 // #i75179# enable setting the background to a different color 164 m_aED_Range.SetStyle( m_aED_Range.GetStyle() | WB_FORCECTRLBACKGROUND ); 165 166 m_aED_Range.SetUpdateDataHdl( LINK( this, RangeChooserTabPage, ControlChangedHdl )); 167 m_aED_Range.SetModifyHdl( LINK( this, RangeChooserTabPage, ControlEditedHdl )); 168 m_aRB_Rows.SetToggleHdl( LINK( this, RangeChooserTabPage, ControlChangedHdl ) ); 169 m_aCB_FirstRowAsLabel.SetToggleHdl( LINK( this, RangeChooserTabPage, ControlChangedHdl ) ); 170 m_aCB_FirstColumnAsLabel.SetToggleHdl( LINK( this, RangeChooserTabPage, ControlChangedHdl ) ); 171 } 172 173 RangeChooserTabPage::~RangeChooserTabPage() 174 { 175 } 176 177 void RangeChooserTabPage::ActivatePage() 178 { 179 OWizardPage::ActivatePage(); 180 initControlsFromModel(); 181 } 182 183 void RangeChooserTabPage::initControlsFromModel() 184 { 185 m_nChangingControlCalls++; 186 187 if(m_pTemplateProvider) 188 { 189 m_xCurrentChartTypeTemplate = m_pTemplateProvider->getCurrentTemplate(); 190 } 191 192 bool bUseColumns = ! m_aRB_Rows.IsChecked(); 193 bool bFirstCellAsLabel = bUseColumns ? m_aCB_FirstRowAsLabel.IsChecked() : m_aCB_FirstColumnAsLabel.IsChecked(); 194 bool bHasCategories = bUseColumns ? m_aCB_FirstColumnAsLabel.IsChecked() : m_aCB_FirstRowAsLabel.IsChecked(); 195 196 bool bIsValid = m_rDialogModel.allArgumentsForRectRangeDetected(); 197 if( bIsValid ) 198 m_rDialogModel.detectArguments( 199 m_aLastValidRangeString, bUseColumns, bFirstCellAsLabel, bHasCategories ); 200 else 201 m_aLastValidRangeString = String::EmptyString(); 202 203 m_aED_Range.SetText( m_aLastValidRangeString ); 204 205 m_aRB_Rows.Check( !bUseColumns ); 206 m_aRB_Columns.Check( bUseColumns ); 207 208 m_aCB_FirstRowAsLabel.Check( m_aRB_Rows.IsChecked()?bHasCategories:bFirstCellAsLabel ); 209 m_aCB_FirstColumnAsLabel.Check( m_aRB_Columns.IsChecked()?bHasCategories:bFirstCellAsLabel ); 210 211 isValid(); 212 213 m_nChangingControlCalls--; 214 } 215 216 void RangeChooserTabPage::DeactivatePage() 217 { 218 commitPage(); 219 svt::OWizardPage::DeactivatePage(); 220 } 221 222 void RangeChooserTabPage::commitPage() 223 { 224 commitPage(::svt::WizardTypes::eFinish); 225 } 226 227 sal_Bool RangeChooserTabPage::commitPage( ::svt::WizardTypes::CommitPageReason /*eReason*/ ) 228 { 229 //ranges may have been edited in the meanwhile (dirty is true in that case here) 230 if( isValid() ) 231 { 232 changeDialogModelAccordingToControls(); 233 return sal_True;//return false if this page should not be left 234 } 235 else 236 return sal_False; 237 } 238 239 void RangeChooserTabPage::changeDialogModelAccordingToControls() 240 { 241 if(m_nChangingControlCalls>0) 242 return; 243 244 if( !m_xCurrentChartTypeTemplate.is() ) 245 { 246 if(m_pTemplateProvider) 247 m_xCurrentChartTypeTemplate.set( m_pTemplateProvider->getCurrentTemplate()); 248 if( !m_xCurrentChartTypeTemplate.is()) 249 { 250 OSL_ENSURE( false, "Need a template to change data source" ); 251 return; 252 } 253 } 254 255 if( m_bIsDirty ) 256 { 257 sal_Bool bFirstCellAsLabel = ( m_aCB_FirstColumnAsLabel.IsChecked() && !m_aRB_Columns.IsChecked() ) 258 || ( m_aCB_FirstRowAsLabel.IsChecked() && !m_aRB_Rows.IsChecked() ); 259 sal_Bool bHasCategories = ( m_aCB_FirstColumnAsLabel.IsChecked() && m_aRB_Columns.IsChecked() ) 260 || ( m_aCB_FirstRowAsLabel.IsChecked() && m_aRB_Rows.IsChecked() ); 261 262 Sequence< beans::PropertyValue > aArguments( 263 DataSourceHelper::createArguments( 264 m_aRB_Columns.IsChecked(), bFirstCellAsLabel, bHasCategories ) ); 265 266 // only if range is valid 267 if( m_aLastValidRangeString.equals( m_aED_Range.GetText())) 268 { 269 m_rDialogModel.setTemplate( m_xCurrentChartTypeTemplate ); 270 aArguments.realloc( aArguments.getLength() + 1 ); 271 aArguments[aArguments.getLength() - 1] = 272 beans::PropertyValue( C2U("CellRangeRepresentation"), -1, 273 uno::makeAny( m_aLastValidRangeString ), 274 beans::PropertyState_DIRECT_VALUE ); 275 m_rDialogModel.setData( aArguments ); 276 m_bIsDirty = false; 277 } 278 279 //@todo warn user that the selected range is not valid 280 //@todo better: disable OK-Button if range is invalid 281 } 282 } 283 284 bool RangeChooserTabPage::isValid() 285 { 286 ::rtl::OUString aRange( m_aED_Range.GetText()); 287 sal_Bool bFirstCellAsLabel = ( m_aCB_FirstColumnAsLabel.IsChecked() && !m_aRB_Columns.IsChecked() ) 288 || ( m_aCB_FirstRowAsLabel.IsChecked() && !m_aRB_Rows.IsChecked() ); 289 sal_Bool bHasCategories = ( m_aCB_FirstColumnAsLabel.IsChecked() && m_aRB_Columns.IsChecked() ) 290 || ( m_aCB_FirstRowAsLabel.IsChecked() && m_aRB_Rows.IsChecked() ); 291 bool bIsValid = ( aRange.getLength() == 0 ) || 292 m_rDialogModel.getRangeSelectionHelper()->verifyArguments( 293 DataSourceHelper::createArguments( 294 aRange, Sequence< sal_Int32 >(), m_aRB_Columns.IsChecked(), bFirstCellAsLabel, bHasCategories )); 295 296 if( bIsValid ) 297 { 298 m_aED_Range.SetControlForeground(); 299 m_aED_Range.SetControlBackground(); 300 if( m_pTabPageNotifiable ) 301 m_pTabPageNotifiable->setValidPage( this ); 302 m_aLastValidRangeString = aRange; 303 } 304 else 305 { 306 m_aED_Range.SetControlBackground( RANGE_SELECTION_INVALID_RANGE_BACKGROUND_COLOR ); 307 m_aED_Range.SetControlForeground( RANGE_SELECTION_INVALID_RANGE_FOREGROUND_COLOR ); 308 if( m_pTabPageNotifiable ) 309 m_pTabPageNotifiable->setInvalidPage( this ); 310 } 311 312 // enable/disable controls 313 // #i79531# if the range is valid but an action of one of these buttons 314 // would render it invalid, the button should be disabled 315 if( bIsValid ) 316 { 317 bool bDataInColumns = m_aRB_Columns.IsChecked(); 318 bool bIsSwappedRangeValid = m_rDialogModel.getRangeSelectionHelper()->verifyArguments( 319 DataSourceHelper::createArguments( 320 aRange, Sequence< sal_Int32 >(), ! bDataInColumns, bHasCategories, bFirstCellAsLabel )); 321 m_aRB_Rows.Enable( bIsSwappedRangeValid ); 322 m_aRB_Columns.Enable( bIsSwappedRangeValid ); 323 324 m_aCB_FirstRowAsLabel.Enable( 325 m_rDialogModel.getRangeSelectionHelper()->verifyArguments( 326 DataSourceHelper::createArguments( 327 aRange, Sequence< sal_Int32 >(), m_aRB_Columns.IsChecked(), 328 bDataInColumns ? ! bFirstCellAsLabel : bFirstCellAsLabel, 329 bDataInColumns ? bHasCategories : ! bHasCategories ))); 330 m_aCB_FirstColumnAsLabel.Enable( 331 m_rDialogModel.getRangeSelectionHelper()->verifyArguments( 332 DataSourceHelper::createArguments( 333 aRange, Sequence< sal_Int32 >(), m_aRB_Columns.IsChecked(), 334 bDataInColumns ? bFirstCellAsLabel : ! bFirstCellAsLabel, 335 bDataInColumns ? ! bHasCategories : bHasCategories ))); 336 } 337 else 338 { 339 m_aRB_Rows.Enable( bIsValid ); 340 m_aRB_Columns.Enable( bIsValid ); 341 m_aCB_FirstRowAsLabel.Enable( bIsValid ); 342 m_aCB_FirstColumnAsLabel.Enable( bIsValid ); 343 } 344 sal_Bool bShowIB = m_rDialogModel.getRangeSelectionHelper()->hasRangeSelection(); 345 lcl_ShowChooserButton( m_aIB_Range, m_aED_Range, bShowIB ); 346 347 return bIsValid; 348 } 349 350 IMPL_LINK( RangeChooserTabPage, ControlEditedHdl, void*, EMPTYARG ) 351 { 352 setDirty(); 353 isValid(); 354 return 0; 355 } 356 357 IMPL_LINK( RangeChooserTabPage, ControlChangedHdl, void*, EMPTYARG ) 358 { 359 setDirty(); 360 if( isValid()) 361 changeDialogModelAccordingToControls(); 362 return 0; 363 } 364 365 IMPL_LINK( RangeChooserTabPage, ChooseRangeHdl, void *, EMPTYARG ) 366 { 367 rtl::OUString aRange = m_aED_Range.GetText(); 368 // using assignment for broken gcc 3.3 369 rtl::OUString aTitle = String( SchResId( STR_PAGE_DATA_RANGE ) ); 370 371 lcl_enableRangeChoosing( true, m_pParentDialog ); 372 m_rDialogModel.getRangeSelectionHelper()->chooseRange( aRange, aTitle, *this ); 373 374 return 0; 375 } 376 377 378 void RangeChooserTabPage::listeningFinished( const ::rtl::OUString & rNewRange ) 379 { 380 //user has selected a new range 381 382 rtl::OUString aRange( rNewRange ); 383 384 m_rDialogModel.startControllerLockTimer(); 385 386 // stop listening 387 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening(); 388 389 //update dialog state 390 ToTop(); 391 GrabFocus(); 392 m_aED_Range.SetText( String( aRange ) ); 393 m_aED_Range.GrabFocus(); 394 395 setDirty(); 396 if( isValid()) 397 changeDialogModelAccordingToControls(); 398 399 lcl_enableRangeChoosing( false, m_pParentDialog ); 400 } 401 void RangeChooserTabPage::disposingRangeSelection() 402 { 403 m_rDialogModel.getRangeSelectionHelper()->stopRangeListening( false ); 404 } 405 406 void RangeChooserTabPage::setDirty() 407 { 408 if( m_nChangingControlCalls == 0 ) 409 m_bIsDirty = true; 410 } 411 412 //............................................................................. 413 } //namespace chart 414 //............................................................................. 415