1 /************************************************************************* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * Copyright 2000, 2010 Oracle and/or its affiliates. 5 * 6 * OpenOffice.org - a multi-platform office productivity suite 7 * 8 * This file is part of OpenOffice.org. 9 * 10 * OpenOffice.org is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU Lesser General Public License version 3 12 * only, as published by the Free Software Foundation. 13 * 14 * OpenOffice.org is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Lesser General Public License version 3 for more details 18 * (a copy is included in the LICENSE file that accompanied this code). 19 * 20 * You should have received a copy of the GNU Lesser General Public License 21 * version 3 along with OpenOffice.org. If not, see 22 * <http://www.openoffice.org/license.html> 23 * for a copy of the LGPLv3 License. 24 * 25 ************************************************************************/ 26 27 // MARKER(update_precomp.py): autogen include statement, do not remove 28 #include "precompiled_svx.hxx" 29 30 #include "svx/dbtoolsclient.hxx" 31 #include "formcontrolfactory.hxx" 32 #include "fmcontrollayout.hxx" 33 #include "fmprop.hrc" 34 #include "svx/fmresids.hrc" 35 #include "fmservs.hxx" 36 #include "svx/dialmgr.hxx" 37 #include "svx/svdouno.hxx" 38 39 /** === begin UNO includes === **/ 40 #include <com/sun/star/form/XFormComponent.hpp> 41 #include <com/sun/star/form/FormComponentType.hpp> 42 #include <com/sun/star/awt/ScrollBarOrientation.hpp> 43 #include <com/sun/star/awt/MouseWheelBehavior.hpp> 44 #include <com/sun/star/form/XGridColumnFactory.hpp> 45 #include <com/sun/star/style/VerticalAlignment.hpp> 46 #include <com/sun/star/awt/LineEndFormat.hpp> 47 #include <com/sun/star/awt/ImageScaleMode.hpp> 48 #include <com/sun/star/sdbc/DataType.hpp> 49 #include <com/sun/star/util/XNumberFormatTypes.hpp> 50 #include <com/sun/star/sdbc/ColumnValue.hpp> 51 #include <com/sun/star/text/WritingMode2.hpp> 52 #include <com/sun/star/awt/FontDescriptor.hpp> 53 /** === end UNO includes === **/ 54 55 #include <comphelper/componentcontext.hxx> 56 #include <comphelper/numbers.hxx> 57 #include <unotools/syslocale.hxx> 58 #include <tools/gen.hxx> 59 #include <tools/diagnose_ex.h> 60 61 #include <set> 62 63 //........................................................................ 64 namespace svxform 65 { 66 //........................................................................ 67 68 /** === begin UNO using === **/ 69 using ::com::sun::star::uno::Reference; 70 using ::com::sun::star::uno::XInterface; 71 using ::com::sun::star::uno::UNO_QUERY; 72 using ::com::sun::star::uno::UNO_QUERY_THROW; 73 using ::com::sun::star::uno::UNO_SET_THROW; 74 using ::com::sun::star::uno::Exception; 75 using ::com::sun::star::uno::RuntimeException; 76 using ::com::sun::star::uno::Any; 77 using ::com::sun::star::uno::makeAny; 78 using ::com::sun::star::uno::Sequence; 79 using ::com::sun::star::uno::Type; 80 using ::com::sun::star::beans::XPropertySet; 81 using ::com::sun::star::awt::XControlModel; 82 using ::com::sun::star::form::XFormComponent; 83 using ::com::sun::star::container::XIndexAccess; 84 using ::com::sun::star::beans::XPropertySetInfo; 85 using ::com::sun::star::beans::PropertyValue; 86 using ::com::sun::star::container::XChild; 87 using ::com::sun::star::form::XGridColumnFactory; 88 using ::com::sun::star::style::VerticalAlignment_MIDDLE; 89 using ::com::sun::star::beans::Property; 90 using ::com::sun::star::uno::TypeClass_DOUBLE; 91 using ::com::sun::star::uno::TypeClass_LONG; 92 using ::com::sun::star::util::XNumberFormats; 93 using ::com::sun::star::util::XNumberFormatTypes; 94 using ::com::sun::star::awt::FontDescriptor; 95 using ::com::sun::star::lang::Locale; 96 using ::com::sun::star::lang::XServiceInfo; 97 using ::com::sun::star::container::XNameAccess; 98 /** === end UNO using === **/ 99 namespace FormComponentType = ::com::sun::star::form::FormComponentType; 100 namespace ScrollBarOrientation = ::com::sun::star::awt::ScrollBarOrientation; 101 namespace MouseWheelBehavior = ::com::sun::star::awt::MouseWheelBehavior; 102 namespace LineEndFormat = ::com::sun::star::awt::LineEndFormat; 103 namespace ImageScaleMode = ::com::sun::star::awt::ImageScaleMode; 104 namespace DataType = ::com::sun::star::sdbc::DataType; 105 namespace ColumnValue = ::com::sun::star::sdbc::ColumnValue; 106 namespace WritingMode2 = ::com::sun::star::text::WritingMode2; 107 108 //==================================================================== 109 //= FormControlFactory_Data 110 //==================================================================== 111 struct FormControlFactory_Data 112 { 113 ::comphelper::ComponentContext m_aContext; 114 115 FormControlFactory_Data( const ::comphelper::ComponentContext& _rContext ) 116 :m_aContext( _rContext ) 117 { 118 } 119 }; 120 121 //==================================================================== 122 //= FormControlFactory 123 //==================================================================== 124 //-------------------------------------------------------------------- 125 FormControlFactory::FormControlFactory( const ::comphelper::ComponentContext& _rContext ) 126 :m_pData( new FormControlFactory_Data( _rContext ) ) 127 { 128 } 129 130 //-------------------------------------------------------------------- 131 FormControlFactory::~FormControlFactory() 132 { 133 } 134 135 //-------------------------------------------------------------------- 136 sal_Int16 FormControlFactory::initializeControlModel( const DocumentType _eDocType, const SdrUnoObj& _rObject ) 137 { 138 return initializeControlModel( 139 _eDocType, 140 Reference< XPropertySet >( _rObject.GetUnoControlModel(), UNO_QUERY ), 141 _rObject.GetCurrentBoundRect() 142 ); 143 } 144 145 //-------------------------------------------------------------------- 146 sal_Int16 FormControlFactory::initializeControlModel( const DocumentType _eDocType, const Reference< XPropertySet >& _rxControlModel ) 147 { 148 return initializeControlModel( 149 _eDocType, _rxControlModel, Rectangle() 150 ); 151 } 152 153 // ----------------------------------------------------------------------------- 154 namespace 155 { 156 //.................................................................... 157 static ::rtl::OUString lcl_getUniqueLabel_nothrow( const Reference< XPropertySet >& _rxControlModel, const ::rtl::OUString& _rBaseLabel ) 158 { 159 ::rtl::OUString sLabel( _rBaseLabel ); 160 try 161 { 162 typedef ::std::set< ::rtl::OUString > StringBag; 163 StringBag aUsedLabels; 164 165 Reference< XFormComponent > xFormComponent( _rxControlModel, UNO_QUERY_THROW ); 166 Reference< XIndexAccess > xContainer( xFormComponent->getParent(), UNO_QUERY_THROW ); 167 // loop through all siblings of the control model, and collect their labels 168 for ( sal_Int32 index=xContainer->getCount(); index>0; ) 169 { 170 Reference< XPropertySet > xElement( xContainer->getByIndex( --index ), UNO_QUERY_THROW ); 171 if ( xElement == _rxControlModel ) 172 continue; 173 174 Reference< XPropertySetInfo > xPSI( xElement->getPropertySetInfo(), UNO_SET_THROW ); 175 if ( !xPSI->hasPropertyByName( FM_PROP_LABEL ) ) 176 continue; 177 178 ::rtl::OUString sElementLabel; 179 OSL_VERIFY( xElement->getPropertyValue( FM_PROP_LABEL ) >>= sElementLabel ); 180 aUsedLabels.insert( sElementLabel ); 181 } 182 183 // now find a free label 184 sal_Int32 i=2; 185 while ( aUsedLabels.find( sLabel ) != aUsedLabels.end() ) 186 { 187 ::rtl::OUStringBuffer aBuffer( _rBaseLabel ); 188 aBuffer.appendAscii( " " ); 189 aBuffer.append( (sal_Int32)i++ ); 190 sLabel = aBuffer.makeStringAndClear(); 191 } 192 } 193 catch( const Exception& ) 194 { 195 DBG_UNHANDLED_EXCEPTION(); 196 } 197 return sLabel; 198 } 199 200 //.................................................................... 201 static Sequence< PropertyValue > lcl_getDataSourceIndirectProperties( const Reference< XPropertySet >& _rxControlModel, 202 const ::comphelper::ComponentContext& _rContext ) 203 { 204 OSL_PRECOND( _rxControlModel.is(), "lcl_getDataSourceIndirectProperties: invalid model!" ); 205 206 Sequence< PropertyValue > aInfo; 207 try 208 { 209 Reference< XChild > xChild( _rxControlModel, UNO_QUERY ); 210 Reference< XPropertySet > xForm; 211 if ( xChild.is() ) 212 xForm = xForm.query( xChild->getParent() ); 213 214 if ( Reference< XGridColumnFactory >( xForm, UNO_QUERY ).is() ) 215 { // hmm. the model is a grid column, in real 216 xChild = xChild.query( xForm ); 217 xForm = xForm.query( xChild->getParent() ); 218 } 219 220 OSL_ENSURE( xForm.is(), "lcl_getDataSourceIndirectProperties: could not determine the form!" ); 221 if ( !xForm.is() ) 222 return aInfo; 223 ::rtl::OUString sDataSourceName; 224 xForm->getPropertyValue( FM_PROP_DATASOURCE ) >>= sDataSourceName; 225 226 Reference< XPropertySet > xDsProperties; 227 if ( sDataSourceName.getLength() ) 228 xDsProperties = xDsProperties.query( OStaticDataAccessTools().getDataSource( sDataSourceName, _rContext.getLegacyServiceFactory() ) ); 229 if ( xDsProperties.is() ) 230 xDsProperties->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Info" ) ) ) >>= aInfo; 231 } 232 catch( const Exception& ) 233 { 234 OSL_ENSURE( sal_False, "lcl_getDataSourceIndirectProperties: caught an exception!" ); 235 } 236 return aInfo; 237 } 238 239 //.................................................................... 240 static const sal_Char* aCharacterAndParagraphProperties[] = 241 { 242 "CharFontName", 243 "CharFontStyleName", 244 "CharFontFamily", 245 "CharFontCharSet", 246 "CharFontPitch", 247 "CharColor", 248 "CharEscapement", 249 "CharHeight", 250 "CharUnderline", 251 "CharWeight", 252 "CharPosture", 253 "CharAutoKerning", 254 "CharBackColor", 255 "CharBackTransparent", 256 "CharCaseMap", 257 "CharCrossedOut", 258 "CharFlash", 259 "CharStrikeout", 260 "CharWordMode", 261 "CharKerning", 262 "CharLocale", 263 "CharKeepTogether", 264 "CharNoLineBreak", 265 "CharShadowed", 266 "CharFontType", 267 "CharStyleName", 268 "CharContoured", 269 "CharCombineIsOn", 270 "CharCombinePrefix", 271 "CharCombineSuffix", 272 "CharEmphasize", 273 "CharRelief", 274 "RubyText", 275 "RubyAdjust", 276 "RubyCharStyleName", 277 "RubyIsAbove", 278 "CharRotation", 279 "CharRotationIsFitToLine", 280 "CharScaleWidth", 281 "HyperLinkURL", 282 "HyperLinkTarget", 283 "HyperLinkName", 284 "VisitedCharStyleName", 285 "UnvisitedCharStyleName", 286 "CharEscapementHeight", 287 "CharNoHyphenation", 288 "CharUnderlineColor", 289 "CharUnderlineHasColor", 290 "CharStyleNames", 291 "CharHeightAsian", 292 "CharWeightAsian", 293 "CharFontNameAsian", 294 "CharFontStyleNameAsian", 295 "CharFontFamilyAsian", 296 "CharFontCharSetAsian", 297 "CharFontPitchAsian", 298 "CharPostureAsian", 299 "CharLocaleAsian", 300 "ParaIsCharacterDistance", 301 "ParaIsForbiddenRules", 302 "ParaIsHangingPunctuation", 303 "CharHeightComplex", 304 "CharWeightComplex", 305 "CharFontNameComplex", 306 "CharFontStyleNameComplex", 307 "CharFontFamilyComplex", 308 "CharFontCharSetComplex", 309 "CharFontPitchComplex", 310 "CharPostureComplex", 311 "CharLocaleComplex", 312 "ParaAdjust", 313 "ParaLineSpacing", 314 "ParaBackColor", 315 "ParaBackTransparent", 316 "ParaBackGraphicURL", 317 "ParaBackGraphicFilter", 318 "ParaBackGraphicLocation", 319 "ParaLastLineAdjust", 320 "ParaExpandSingleWord", 321 "ParaLeftMargin", 322 "ParaRightMargin", 323 "ParaTopMargin", 324 "ParaBottomMargin", 325 "ParaLineNumberCount", 326 "ParaLineNumberStartValue", 327 "PageDescName", 328 "PageNumberOffset", 329 "ParaRegisterModeActive", 330 "ParaTabStops", 331 "ParaStyleName", 332 "DropCapFormat", 333 "DropCapWholeWord", 334 "ParaKeepTogether", 335 "Setting", 336 "ParaSplit", 337 "Setting", 338 "NumberingLevel", 339 "NumberingRules", 340 "NumberingStartValue", 341 "ParaIsNumberingRestart", 342 "NumberingStyleName", 343 "ParaOrphans", 344 "ParaWidows", 345 "ParaShadowFormat", 346 "LeftBorder", 347 "RightBorder", 348 "TopBorder", 349 "BottomBorder", 350 "BorderDistance", 351 "LeftBorderDistance", 352 "RightBorderDistance", 353 "TopBorderDistance", 354 "BottomBorderDistance", 355 "BreakType", 356 "DropCapCharStyleName", 357 "ParaFirstLineIndent", 358 "ParaIsAutoFirstLineIndent", 359 "ParaIsHyphenation", 360 "ParaHyphenationMaxHyphens", 361 "ParaHyphenationMaxLeadingChars", 362 "ParaHyphenationMaxTrailingChars", 363 "ParaVertAlignment", 364 "ParaUserDefinedAttributes", 365 "NumberingIsNumber", 366 "ParaIsConnectBorder", 367 NULL 368 }; 369 370 //.................................................................... 371 static void lcl_initializeCharacterAttributes( const Reference< XPropertySet >& _rxModel ) 372 { 373 try 374 { 375 Reference< XPropertySet > xStyle( ControlLayouter::getDefaultDocumentTextStyle( _rxModel ), UNO_SET_THROW ); 376 377 // transfer all properties which are described by the style 378 Reference< XPropertySetInfo > xSourcePropInfo( xStyle->getPropertySetInfo(), UNO_SET_THROW ); 379 Reference< XPropertySetInfo > xDestPropInfo( _rxModel->getPropertySetInfo(), UNO_SET_THROW ); 380 381 ::rtl::OUString sPropertyName; 382 const sal_Char** pCharacterProperty = aCharacterAndParagraphProperties; 383 while ( *pCharacterProperty ) 384 { 385 sPropertyName = ::rtl::OUString::createFromAscii( *pCharacterProperty ); 386 387 if ( xSourcePropInfo->hasPropertyByName( sPropertyName ) && xDestPropInfo->hasPropertyByName( sPropertyName ) ) 388 _rxModel->setPropertyValue( sPropertyName, xStyle->getPropertyValue( sPropertyName ) ); 389 390 ++pCharacterProperty; 391 } 392 } 393 catch( const Exception& ) 394 { 395 DBG_UNHANDLED_EXCEPTION(); 396 } 397 } 398 } 399 400 //-------------------------------------------------------------------- 401 sal_Int16 FormControlFactory::initializeControlModel( const DocumentType _eDocType, const Reference< XPropertySet >& _rxControlModel, 402 const Rectangle& _rControlBoundRect ) 403 { 404 sal_Int16 nClassId = FormComponentType::CONTROL; 405 406 OSL_ENSURE( _rxControlModel.is(), "FormControlFactory::initializeControlModel: invalid model!" ); 407 if ( !_rxControlModel.is() ) 408 return nClassId; 409 410 try 411 { 412 ControlLayouter::initializeControlLayout( _rxControlModel, _eDocType ); 413 414 _rxControlModel->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId; 415 Reference< XPropertySetInfo > xPSI( _rxControlModel->getPropertySetInfo(), UNO_SET_THROW ); 416 switch ( nClassId ) 417 { 418 case FormComponentType::SCROLLBAR: 419 _rxControlModel->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LiveScroll" ) ), makeAny( (sal_Bool)sal_True ) ); 420 // NO break! 421 case FormComponentType::SPINBUTTON: 422 { 423 sal_Int32 eOrientation = ScrollBarOrientation::HORIZONTAL; 424 if ( !_rControlBoundRect.IsEmpty() && ( _rControlBoundRect.GetWidth() < _rControlBoundRect.GetHeight() ) ) 425 eOrientation = ScrollBarOrientation::VERTICAL; 426 _rxControlModel->setPropertyValue( FM_PROP_ORIENTATION, makeAny( eOrientation ) ); 427 } 428 break; 429 430 case FormComponentType::LISTBOX: 431 case FormComponentType::COMBOBOX: 432 { 433 sal_Bool bDropDown = !_rControlBoundRect.IsEmpty() && ( _rControlBoundRect.GetWidth() >= 3 * _rControlBoundRect.GetHeight() ); 434 if ( xPSI->hasPropertyByName( FM_PROP_DROPDOWN ) ) 435 _rxControlModel->setPropertyValue( FM_PROP_DROPDOWN, makeAny( (sal_Bool)bDropDown ) ); 436 _rxControlModel->setPropertyValue( FM_PROP_LINECOUNT, makeAny( sal_Int16( 20 ) ) ); 437 } 438 break; 439 440 case FormComponentType::TEXTFIELD: 441 { 442 initializeTextFieldLineEnds( _rxControlModel ); 443 lcl_initializeCharacterAttributes( _rxControlModel ); 444 445 if ( !_rControlBoundRect.IsEmpty() 446 && !( _rControlBoundRect.GetWidth() > 4 * _rControlBoundRect.GetHeight() ) 447 ) 448 { 449 if ( xPSI->hasPropertyByName( FM_PROP_MULTILINE ) ) 450 _rxControlModel->setPropertyValue( FM_PROP_MULTILINE, makeAny( (sal_Bool)sal_True ) ); 451 } 452 } 453 break; 454 455 case FormComponentType::RADIOBUTTON: 456 case FormComponentType::CHECKBOX: 457 case FormComponentType::FIXEDTEXT: 458 { 459 ::rtl::OUString sVertAlignPropertyName( RTL_CONSTASCII_USTRINGPARAM( "VerticalAlign" ) ); 460 if ( xPSI->hasPropertyByName( sVertAlignPropertyName ) ) 461 _rxControlModel->setPropertyValue( sVertAlignPropertyName, makeAny( VerticalAlignment_MIDDLE ) ); 462 } 463 break; 464 465 case FormComponentType::IMAGEBUTTON: 466 case FormComponentType::IMAGECONTROL: 467 { 468 const ::rtl::OUString sScaleModeProperty( RTL_CONSTASCII_USTRINGPARAM( "ScaleMode" ) ); 469 if ( xPSI->hasPropertyByName( sScaleModeProperty ) ) 470 _rxControlModel->setPropertyValue( sScaleModeProperty, makeAny( ImageScaleMode::Isotropic ) ); 471 } 472 break; 473 } 474 475 // initial default label for the control 476 if ( xPSI->hasPropertyByName( FM_PROP_LABEL ) ) 477 { 478 ::rtl::OUString sExistingLabel; 479 OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_LABEL ) >>= sExistingLabel ); 480 if ( !sExistingLabel.getLength() ) 481 { 482 ::rtl::OUString sInitialLabel; 483 OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_NAME ) >>= sInitialLabel ); 484 485 sal_uInt16 nTitleResId = 0; 486 switch ( nClassId ) 487 { 488 case FormComponentType::COMMANDBUTTON: nTitleResId = RID_STR_PROPTITLE_PUSHBUTTON; break; 489 case FormComponentType::RADIOBUTTON: nTitleResId = RID_STR_PROPTITLE_RADIOBUTTON; break; 490 case FormComponentType::CHECKBOX: nTitleResId = RID_STR_PROPTITLE_CHECKBOX; break; 491 case FormComponentType::GROUPBOX: nTitleResId = RID_STR_PROPTITLE_GROUPBOX; break; 492 case FormComponentType::FIXEDTEXT: nTitleResId = RID_STR_PROPTITLE_FIXEDTEXT; break; 493 } 494 495 if ( nTitleResId ) 496 sInitialLabel = String( SVX_RES( nTitleResId ) ); 497 498 _rxControlModel->setPropertyValue( 499 FM_PROP_LABEL, 500 makeAny( lcl_getUniqueLabel_nothrow( _rxControlModel, sInitialLabel ) ) 501 ); 502 } 503 } 504 505 // strict format = yes is the default (i93467) 506 if ( xPSI->hasPropertyByName( FM_PROP_STRICTFORMAT ) ) 507 { 508 _rxControlModel->setPropertyValue( FM_PROP_STRICTFORMAT, makeAny( sal_Bool( sal_True ) ) ); 509 } 510 511 // mouse wheel: don't use it for scrolling by default (i110036) 512 if ( xPSI->hasPropertyByName( FM_PROP_MOUSE_WHEEL_BEHAVIOR ) ) 513 { 514 _rxControlModel->setPropertyValue( FM_PROP_MOUSE_WHEEL_BEHAVIOR, makeAny( MouseWheelBehavior::SCROLL_DISABLED ) ); 515 } 516 517 if ( xPSI->hasPropertyByName( FM_PROP_WRITING_MODE ) ) 518 _rxControlModel->setPropertyValue( FM_PROP_WRITING_MODE, makeAny( WritingMode2::CONTEXT ) ); 519 } 520 catch( const Exception& ) 521 { 522 DBG_UNHANDLED_EXCEPTION(); 523 } 524 return nClassId; 525 } 526 527 //------------------------------------------------------------------------------ 528 void FormControlFactory::initializeTextFieldLineEnds( const Reference< XPropertySet >& _rxModel ) 529 { 530 OSL_PRECOND( _rxModel.is(), "initializeTextFieldLineEnds: invalid model!" ); 531 if ( !_rxModel.is() ) 532 return; 533 534 try 535 { 536 Reference< XPropertySetInfo > xInfo = _rxModel->getPropertySetInfo(); 537 if ( !xInfo.is() || !xInfo->hasPropertyByName( FM_PROP_LINEENDFORMAT ) ) 538 return; 539 540 // let's see if the data source which the form belongs to (if any) 541 // has a setting for the preferred line end format 542 sal_Bool bDosLineEnds = sal_False; 543 Sequence< PropertyValue > aInfo = lcl_getDataSourceIndirectProperties( _rxModel, m_pData->m_aContext ); 544 const PropertyValue* pInfo = aInfo.getConstArray(); 545 const PropertyValue* pInfoEnd = pInfo + aInfo.getLength(); 546 for ( ; pInfo != pInfoEnd; ++pInfo ) 547 { 548 if ( pInfo->Name.equalsAscii( "PreferDosLikeLineEnds" ) ) 549 { 550 pInfo->Value >>= bDosLineEnds; 551 break; 552 } 553 } 554 555 sal_Int16 nLineEndFormat = bDosLineEnds ? LineEndFormat::CARRIAGE_RETURN_LINE_FEED : LineEndFormat::LINE_FEED; 556 _rxModel->setPropertyValue( FM_PROP_LINEENDFORMAT, makeAny( nLineEndFormat ) ); 557 } 558 catch( const Exception& ) 559 { 560 DBG_UNHANDLED_EXCEPTION(); 561 } 562 } 563 564 //------------------------------------------------------------------------------ 565 void FormControlFactory::initializeFieldDependentProperties( const Reference< XPropertySet >& _rxDatabaseField, 566 const Reference< XPropertySet >& _rxControlModel, const Reference< XNumberFormats >& _rxNumberFormats ) 567 { 568 OSL_PRECOND( _rxDatabaseField.is() && _rxControlModel.is(), 569 "FormControlFactory::initializeFieldDependentProperties: illegal params!" ); 570 if ( !_rxDatabaseField.is() || !_rxControlModel.is() ) 571 return; 572 573 try 574 { 575 //////////////////////////////////////////////////////////////////////// 576 // if the field has a numeric format, and the model has a "Scale" property, sync it 577 Reference< XPropertySetInfo > xFieldPSI( _rxDatabaseField->getPropertySetInfo(), UNO_SET_THROW ); 578 Reference< XPropertySetInfo > xModelPSI( _rxControlModel->getPropertySetInfo(), UNO_SET_THROW ); 579 580 if ( xModelPSI->hasPropertyByName( FM_PROP_DECIMAL_ACCURACY ) ) 581 { 582 sal_Int32 nFormatKey = 0; 583 if ( xFieldPSI->hasPropertyByName( FM_PROP_FORMATKEY ) ) 584 { 585 _rxDatabaseField->getPropertyValue( FM_PROP_FORMATKEY ) >>= nFormatKey; 586 } 587 else 588 { 589 nFormatKey = OStaticDataAccessTools().getDefaultNumberFormat( 590 _rxDatabaseField, 591 Reference< XNumberFormatTypes >( _rxNumberFormats, UNO_QUERY ), 592 SvtSysLocale().GetLocaleData().getLocale() 593 ); 594 } 595 596 Any aScaleVal( ::comphelper::getNumberFormatDecimals( _rxNumberFormats, nFormatKey ) ); 597 _rxControlModel->setPropertyValue( FM_PROP_DECIMAL_ACCURACY, aScaleVal ); 598 } 599 600 //////////////////////////////////////////////////////////////////////// 601 // minimum and maximum of the control according to the type of the database field 602 sal_Int32 nDataType = DataType::OTHER; 603 OSL_VERIFY( _rxDatabaseField->getPropertyValue( FM_PROP_FIELDTYPE ) >>= nDataType ); 604 605 if ( xModelPSI->hasPropertyByName( FM_PROP_VALUEMIN ) 606 && xModelPSI->hasPropertyByName( FM_PROP_VALUEMAX ) 607 ) 608 { 609 sal_Int32 nMinValue = -1000000000, nMaxValue = 1000000000; 610 switch ( nDataType ) 611 { 612 case DataType::TINYINT : nMinValue = 0; nMaxValue = 255; break; 613 case DataType::SMALLINT : nMinValue = -32768; nMaxValue = 32767; break; 614 case DataType::INTEGER : nMinValue = 0x80000000; nMaxValue = 0x7FFFFFFF; break; 615 // double and singles are ignored 616 } 617 618 Any aValue; 619 620 // both the minimum and the maximum value properties can be either Long or Double 621 Property aProperty = xModelPSI->getPropertyByName( FM_PROP_VALUEMIN ); 622 if ( aProperty.Type.getTypeClass() == TypeClass_DOUBLE ) 623 aValue <<= (double)nMinValue; 624 else if ( aProperty.Type.getTypeClass() == TypeClass_LONG ) 625 aValue <<= (sal_Int32)nMinValue; 626 else 627 { 628 DBG_ERROR( "FormControlFactory::initializeFieldDependentProperties: unexpected property type (MinValue)!" ); 629 } 630 _rxControlModel->setPropertyValue( FM_PROP_VALUEMIN, aValue ); 631 632 // both the minimum and the maximum value properties can be either Long or Double 633 aProperty = xModelPSI->getPropertyByName( FM_PROP_VALUEMAX ); 634 if ( aProperty.Type.getTypeClass() == TypeClass_DOUBLE ) 635 aValue <<= (double)nMaxValue; 636 else if ( aProperty.Type.getTypeClass() == TypeClass_LONG ) 637 aValue <<= (sal_Int32)nMaxValue; 638 else 639 { 640 DBG_ERROR( "FormControlFactory::initializeFieldDependentProperties: unexpected property type (MaxValue)!" ); 641 } 642 _rxControlModel->setPropertyValue( FM_PROP_VALUEMAX, aValue ); 643 } 644 645 //////////////////////////////////////////////////////////////////////// 646 // a check box can be tristate if and only if the column it is bound to is nullable 647 sal_Int16 nClassId = FormComponentType::CONTROL; 648 OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId ); 649 if ( nClassId == FormComponentType::CHECKBOX ) 650 { 651 sal_Int32 nNullable = ColumnValue::NULLABLE_UNKNOWN; 652 OSL_VERIFY( _rxDatabaseField->getPropertyValue( FM_PROP_ISNULLABLE ) >>= nNullable ); 653 _rxControlModel->setPropertyValue( FM_PROP_TRISTATE, makeAny( sal_Bool( ColumnValue::NO_NULLS != nNullable ) ) ); 654 } 655 } 656 catch( const Exception& ) 657 { 658 DBG_UNHANDLED_EXCEPTION(); 659 } 660 } 661 662 //------------------------------------------------------------------------------ 663 ::rtl::OUString FormControlFactory::getDefaultName( sal_Int16 _nClassId, const Reference< XServiceInfo >& _rxObject ) 664 { 665 sal_uInt16 nResId(0); 666 667 switch ( _nClassId ) 668 { 669 case FormComponentType::COMMANDBUTTON: nResId = RID_STR_PROPTITLE_PUSHBUTTON; break; 670 case FormComponentType::RADIOBUTTON: nResId = RID_STR_PROPTITLE_RADIOBUTTON; break; 671 case FormComponentType::CHECKBOX: nResId = RID_STR_PROPTITLE_CHECKBOX; break; 672 case FormComponentType::LISTBOX: nResId = RID_STR_PROPTITLE_LISTBOX; break; 673 case FormComponentType::COMBOBOX: nResId = RID_STR_PROPTITLE_COMBOBOX; break; 674 case FormComponentType::GROUPBOX: nResId = RID_STR_PROPTITLE_GROUPBOX; break; 675 case FormComponentType::IMAGEBUTTON: nResId = RID_STR_PROPTITLE_IMAGEBUTTON; break; 676 case FormComponentType::FIXEDTEXT: nResId = RID_STR_PROPTITLE_FIXEDTEXT; break; 677 case FormComponentType::GRIDCONTROL: nResId = RID_STR_PROPTITLE_DBGRID; break; 678 case FormComponentType::FILECONTROL: nResId = RID_STR_PROPTITLE_FILECONTROL; break; 679 case FormComponentType::DATEFIELD: nResId = RID_STR_PROPTITLE_DATEFIELD; break; 680 case FormComponentType::TIMEFIELD: nResId = RID_STR_PROPTITLE_TIMEFIELD; break; 681 case FormComponentType::NUMERICFIELD: nResId = RID_STR_PROPTITLE_NUMERICFIELD; break; 682 case FormComponentType::CURRENCYFIELD: nResId = RID_STR_PROPTITLE_CURRENCYFIELD; break; 683 case FormComponentType::PATTERNFIELD: nResId = RID_STR_PROPTITLE_PATTERNFIELD; break; 684 case FormComponentType::IMAGECONTROL: nResId = RID_STR_PROPTITLE_IMAGECONTROL; break; 685 case FormComponentType::HIDDENCONTROL: nResId = RID_STR_PROPTITLE_HIDDEN; break; 686 case FormComponentType::SCROLLBAR: nResId = RID_STR_PROPTITLE_SCROLLBAR; break; 687 case FormComponentType::SPINBUTTON: nResId = RID_STR_PROPTITLE_SPINBUTTON; break; 688 case FormComponentType::NAVIGATIONBAR: nResId = RID_STR_PROPTITLE_NAVBAR; break; 689 690 case FormComponentType::TEXTFIELD: 691 nResId = RID_STR_PROPTITLE_EDIT; 692 if ( _rxObject.is() && _rxObject->supportsService( FM_SUN_COMPONENT_FORMATTEDFIELD ) ) 693 nResId = RID_STR_PROPTITLE_FORMATTED; 694 break; 695 696 default: 697 nResId = RID_STR_CONTROL; break; 698 } 699 700 return String( SVX_RES( nResId ) ); 701 } 702 703 //------------------------------------------------------------------------------ 704 ::rtl::OUString FormControlFactory::getDefaultUniqueName_ByComponentType( const Reference< XNameAccess >& _rxContainer, 705 const Reference< XPropertySet >& _rxObject ) 706 { 707 sal_Int16 nClassId = FormComponentType::CONTROL; 708 OSL_VERIFY( _rxObject->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId ); 709 ::rtl::OUString sBaseName = getDefaultName( nClassId, Reference< XServiceInfo >( _rxObject, UNO_QUERY ) ); 710 711 return getUniqueName( _rxContainer, sBaseName ); 712 } 713 714 //------------------------------------------------------------------------------ 715 ::rtl::OUString FormControlFactory::getUniqueName( const Reference< XNameAccess >& _rxContainer, const ::rtl::OUString& _rBaseName ) 716 { 717 sal_Int32 n = 0; 718 ::rtl::OUString sName; 719 do 720 { 721 ::rtl::OUStringBuffer aBuf( _rBaseName ); 722 aBuf.appendAscii( " " ); 723 aBuf.append( ++n ); 724 sName = aBuf.makeStringAndClear(); 725 } 726 while ( _rxContainer->hasByName( sName ) ); 727 728 return sName; 729 } 730 731 //........................................................................ 732 } // namespace svxform 733 //........................................................................ 734