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