merge the formfield patch from ooo-build
[ooovba.git] / svx / source / form / formcontrolfactory.cxx
blob4e28c62a83252965e7611905d90d89ed0b481797
1 /*************************************************************************
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * Copyright 2008 by Sun Microsystems, Inc.
6 * OpenOffice.org - a multi-platform office productivity suite
8 * $RCSfile: formcontrolfactory.cxx,v $
10 * $Revision: 1.1.2.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
28 ************************************************************************/
30 // MARKER(update_precomp.py): autogen include statement, do not remove
31 #include "precompiled_svx.hxx"
33 #include "svx/dbtoolsclient.hxx"
34 #include "formcontrolfactory.hxx"
35 #include "fmcontrollayout.hxx"
36 #include "fmprop.hrc"
37 #include "fmresids.hrc"
38 #include "fmservs.hxx"
39 #include "svx/dialmgr.hxx"
40 #include "svx/svdouno.hxx"
42 /** === begin UNO includes === **/
43 #include <com/sun/star/form/XFormComponent.hpp>
44 #include <com/sun/star/form/FormComponentType.hpp>
45 #include <com/sun/star/awt/ScrollBarOrientation.hpp>
46 #include <com/sun/star/form/XGridColumnFactory.hpp>
47 #include <com/sun/star/lang/XServiceInfo.hpp>
48 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
49 #include <com/sun/star/style/VerticalAlignment.hpp>
50 #include <com/sun/star/awt/LineEndFormat.hpp>
51 #include <com/sun/star/awt/ImageScaleMode.hpp>
52 #include <com/sun/star/sdbc/DataType.hpp>
53 #include <com/sun/star/util/XNumberFormatTypes.hpp>
54 #include <com/sun/star/sdbc/ColumnValue.hpp>
55 #include <com/sun/star/text/WritingMode2.hpp>
56 /** === end UNO includes === **/
58 #include <comphelper/componentcontext.hxx>
59 #include <comphelper/numbers.hxx>
60 #include <svtools/syslocale.hxx>
61 #include <tools/gen.hxx>
62 #include <tools/diagnose_ex.h>
64 #include <set>
66 //........................................................................
67 namespace svxform
69 //........................................................................
71 /** === begin UNO using === **/
72 using ::com::sun::star::uno::Reference;
73 using ::com::sun::star::uno::XInterface;
74 using ::com::sun::star::uno::UNO_QUERY;
75 using ::com::sun::star::uno::UNO_QUERY_THROW;
76 using ::com::sun::star::uno::UNO_SET_THROW;
77 using ::com::sun::star::uno::Exception;
78 using ::com::sun::star::uno::RuntimeException;
79 using ::com::sun::star::uno::Any;
80 using ::com::sun::star::uno::makeAny;
81 using ::com::sun::star::uno::Sequence;
82 using ::com::sun::star::uno::Type;
83 using ::com::sun::star::beans::XPropertySet;
84 using ::com::sun::star::awt::XControlModel;
85 using ::com::sun::star::form::XFormComponent;
86 using ::com::sun::star::container::XIndexAccess;
87 using ::com::sun::star::beans::XPropertySetInfo;
88 using ::com::sun::star::beans::PropertyValue;
89 using ::com::sun::star::container::XChild;
90 using ::com::sun::star::form::XGridColumnFactory;
91 using ::com::sun::star::lang::XServiceInfo;
92 using ::com::sun::star::style::XStyleFamiliesSupplier;
93 using ::com::sun::star::container::XNameAccess;
94 using ::com::sun::star::style::VerticalAlignment_MIDDLE;
95 using ::com::sun::star::beans::Property;
96 using ::com::sun::star::uno::TypeClass_DOUBLE;
97 using ::com::sun::star::uno::TypeClass_LONG;
98 using ::com::sun::star::util::XNumberFormats;
99 using ::com::sun::star::util::XNumberFormatTypes;
100 /** === end UNO using === **/
101 namespace FormComponentType = ::com::sun::star::form::FormComponentType;
102 namespace ScrollBarOrientation = ::com::sun::star::awt::ScrollBarOrientation;
103 namespace LineEndFormat = ::com::sun::star::awt::LineEndFormat;
104 namespace ImageScaleMode = ::com::sun::star::awt::ImageScaleMode;
105 namespace DataType = ::com::sun::star::sdbc::DataType;
106 namespace ColumnValue = ::com::sun::star::sdbc::ColumnValue;
107 namespace WritingMode2 = ::com::sun::star::text::WritingMode2;
109 //====================================================================
110 //= FormControlFactory_Data
111 //====================================================================
112 struct FormControlFactory_Data
114 ::comphelper::ComponentContext m_aContext;
116 FormControlFactory_Data( const ::comphelper::ComponentContext& _rContext )
117 :m_aContext( _rContext )
122 //====================================================================
123 //= FormControlFactory
124 //====================================================================
125 //--------------------------------------------------------------------
126 FormControlFactory::FormControlFactory( const ::comphelper::ComponentContext& _rContext )
127 :m_pData( new FormControlFactory_Data( _rContext ) )
131 //--------------------------------------------------------------------
132 FormControlFactory::~FormControlFactory()
136 //--------------------------------------------------------------------
137 sal_Int16 FormControlFactory::initializeControlModel( const DocumentType _eDocType, const SdrUnoObj& _rObject )
139 return initializeControlModel(
140 _eDocType,
141 Reference< XPropertySet >( _rObject.GetUnoControlModel(), UNO_QUERY ),
142 _rObject.GetCurrentBoundRect()
146 //--------------------------------------------------------------------
147 sal_Int16 FormControlFactory::initializeControlModel( const DocumentType _eDocType, const Reference< XPropertySet >& _rxControlModel )
149 return initializeControlModel(
150 _eDocType, _rxControlModel, Rectangle()
154 // -----------------------------------------------------------------------------
155 namespace
157 //....................................................................
158 static ::rtl::OUString lcl_getUniqueLabel_nothrow( const Reference< XPropertySet >& _rxControlModel, const ::rtl::OUString& _rBaseLabel )
160 ::rtl::OUString sLabel( _rBaseLabel );
163 typedef ::std::set< ::rtl::OUString > StringBag;
164 StringBag aUsedLabels;
166 Reference< XFormComponent > xFormComponent( _rxControlModel, UNO_QUERY_THROW );
167 Reference< XIndexAccess > xContainer( xFormComponent->getParent(), UNO_QUERY_THROW );
168 // loop through all siblings of the control model, and collect their labels
169 for ( sal_Int32 index=xContainer->getCount(); index>0; )
171 Reference< XPropertySet > xElement( xContainer->getByIndex( --index ), UNO_QUERY_THROW );
172 if ( xElement == _rxControlModel )
173 continue;
175 Reference< XPropertySetInfo > xPSI( xElement->getPropertySetInfo(), UNO_SET_THROW );
176 if ( !xPSI->hasPropertyByName( FM_PROP_LABEL ) )
177 continue;
179 ::rtl::OUString sElementLabel;
180 OSL_VERIFY( xElement->getPropertyValue( FM_PROP_LABEL ) >>= sElementLabel );
181 aUsedLabels.insert( sElementLabel );
184 // now find a free label
185 sal_Int32 i=2;
186 while ( aUsedLabels.find( sLabel ) != aUsedLabels.end() )
188 ::rtl::OUStringBuffer aBuffer( _rBaseLabel );
189 aBuffer.appendAscii( " " );
190 aBuffer.append( (sal_Int32)i++ );
191 sLabel = aBuffer.makeStringAndClear();
194 catch( const Exception& )
196 DBG_UNHANDLED_EXCEPTION();
198 return sLabel;
201 //....................................................................
202 static Sequence< PropertyValue > lcl_getDataSourceIndirectProperties( const Reference< XPropertySet >& _rxControlModel,
203 const ::comphelper::ComponentContext& _rContext )
205 OSL_PRECOND( _rxControlModel.is(), "lcl_getDataSourceIndirectProperties: invalid model!" );
207 Sequence< PropertyValue > aInfo;
210 Reference< XChild > xChild( _rxControlModel, UNO_QUERY );
211 Reference< XPropertySet > xForm;
212 if ( xChild.is() )
213 xForm = xForm.query( xChild->getParent() );
215 if ( Reference< XGridColumnFactory >( xForm, UNO_QUERY ).is() )
216 { // hmm. the model is a grid column, in real
217 xChild = xChild.query( xForm );
218 xForm = xForm.query( xChild->getParent() );
221 OSL_ENSURE( xForm.is(), "lcl_getDataSourceIndirectProperties: could not determine the form!" );
222 if ( !xForm.is() )
223 return aInfo;
224 ::rtl::OUString sDataSourceName;
225 xForm->getPropertyValue( FM_PROP_DATASOURCE ) >>= sDataSourceName;
227 Reference< XPropertySet > xDsProperties;
228 if ( sDataSourceName.getLength() )
229 xDsProperties = xDsProperties.query( OStaticDataAccessTools().getDataSource( sDataSourceName, _rContext.getLegacyServiceFactory() ) );
230 if ( xDsProperties.is() )
231 xDsProperties->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Info" ) ) ) >>= aInfo;
233 catch( const Exception& )
235 OSL_ENSURE( sal_False, "lcl_getDataSourceIndirectProperties: caught an exception!" );
237 return aInfo;
240 ATTENTION!
241 Broken for solaris? It seems that the old used template argument TYPE was already
242 defined as a macro ... which expand to ... "TYPE "!?
243 All platforms are OK - excepting Solaris. There the line "template< class TYPE >"
244 was expanded to "template < class TYPE " where the closing ">" was missing.
246 #ifdef MYTYPE
247 #error "Who defines the macro MYTYPE, which is used as template argument here?"
248 #endif
250 //....................................................................
251 template< class MYTYPE >
252 Reference< MYTYPE > getTypedModelNode( const Reference< XInterface >& _rxModelNode )
254 Reference< MYTYPE > xTypedNode( _rxModelNode, UNO_QUERY );
255 if ( xTypedNode.is() )
256 return xTypedNode;
257 else
259 Reference< XChild > xChild( _rxModelNode, UNO_QUERY );
260 if ( xChild.is() )
261 return getTypedModelNode< MYTYPE >( xChild->getParent() );
262 else
263 return NULL;
267 //....................................................................
268 static bool lcl_getDocumentDefaultStyleAndFamily( const Reference< XInterface >& _rxDocument, ::rtl::OUString& _rFamilyName, ::rtl::OUString& _rStyleName ) SAL_THROW(( Exception ))
270 bool bSuccess = true;
271 Reference< XServiceInfo > xDocumentSI( _rxDocument, UNO_QUERY );
272 if ( xDocumentSI.is() )
274 if ( xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" ) ) )
275 || xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.WebDocument" ) ) )
278 _rFamilyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParagraphStyles" ) );
279 _rStyleName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
281 else if ( xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.SpreadsheetDocument" ) ) ) )
283 _rFamilyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CellStyles" ) );
284 _rStyleName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Default" ) );
286 else if ( xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DrawingDocument" ) ) )
287 || xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" ) ) )
290 _rFamilyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "graphics" ) );
291 _rStyleName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "standard" ) );
293 else
294 bSuccess = false;
296 return bSuccess;
299 //....................................................................
300 static const sal_Char* aCharacterAndParagraphProperties[] =
302 "CharFontName",
303 "CharFontStyleName",
304 "CharFontFamily",
305 "CharFontCharSet",
306 "CharFontPitch",
307 "CharColor",
308 "CharEscapement",
309 "CharHeight",
310 "CharUnderline",
311 "CharWeight",
312 "CharPosture",
313 "CharAutoKerning",
314 "CharBackColor",
315 "CharBackTransparent",
316 "CharCaseMap",
317 "CharCrossedOut",
318 "CharFlash",
319 "CharStrikeout",
320 "CharWordMode",
321 "CharKerning",
322 "CharLocale",
323 "CharKeepTogether",
324 "CharNoLineBreak",
325 "CharShadowed",
326 "CharFontType",
327 "CharStyleName",
328 "CharContoured",
329 "CharCombineIsOn",
330 "CharCombinePrefix",
331 "CharCombineSuffix",
332 "CharEmphasize",
333 "CharRelief",
334 "RubyText",
335 "RubyAdjust",
336 "RubyCharStyleName",
337 "RubyIsAbove",
338 "CharRotation",
339 "CharRotationIsFitToLine",
340 "CharScaleWidth",
341 "HyperLinkURL",
342 "HyperLinkTarget",
343 "HyperLinkName",
344 "VisitedCharStyleName",
345 "UnvisitedCharStyleName",
346 "CharEscapementHeight",
347 "CharNoHyphenation",
348 "CharUnderlineColor",
349 "CharUnderlineHasColor",
350 "CharStyleNames",
351 "CharHeightAsian",
352 "CharWeightAsian",
353 "CharFontNameAsian",
354 "CharFontStyleNameAsian",
355 "CharFontFamilyAsian",
356 "CharFontCharSetAsian",
357 "CharFontPitchAsian",
358 "CharPostureAsian",
359 "CharLocaleAsian",
360 "ParaIsCharacterDistance",
361 "ParaIsForbiddenRules",
362 "ParaIsHangingPunctuation",
363 "CharHeightComplex",
364 "CharWeightComplex",
365 "CharFontNameComplex",
366 "CharFontStyleNameComplex",
367 "CharFontFamilyComplex",
368 "CharFontCharSetComplex",
369 "CharFontPitchComplex",
370 "CharPostureComplex",
371 "CharLocaleComplex",
372 "ParaAdjust",
373 "ParaLineSpacing",
374 "ParaBackColor",
375 "ParaBackTransparent",
376 "ParaBackGraphicURL",
377 "ParaBackGraphicFilter",
378 "ParaBackGraphicLocation",
379 "ParaLastLineAdjust",
380 "ParaExpandSingleWord",
381 "ParaLeftMargin",
382 "ParaRightMargin",
383 "ParaTopMargin",
384 "ParaBottomMargin",
385 "ParaLineNumberCount",
386 "ParaLineNumberStartValue",
387 "PageDescName",
388 "PageNumberOffset",
389 "ParaRegisterModeActive",
390 "ParaTabStops",
391 "ParaStyleName",
392 "DropCapFormat",
393 "DropCapWholeWord",
394 "ParaKeepTogether",
395 "Setting",
396 "ParaSplit",
397 "Setting",
398 "NumberingLevel",
399 "NumberingRules",
400 "NumberingStartValue",
401 "ParaIsNumberingRestart",
402 "NumberingStyleName",
403 "ParaOrphans",
404 "ParaWidows",
405 "ParaShadowFormat",
406 "LeftBorder",
407 "RightBorder",
408 "TopBorder",
409 "BottomBorder",
410 "BorderDistance",
411 "LeftBorderDistance",
412 "RightBorderDistance",
413 "TopBorderDistance",
414 "BottomBorderDistance",
415 "BreakType",
416 "DropCapCharStyleName",
417 "ParaFirstLineIndent",
418 "ParaIsAutoFirstLineIndent",
419 "ParaIsHyphenation",
420 "ParaHyphenationMaxHyphens",
421 "ParaHyphenationMaxLeadingChars",
422 "ParaHyphenationMaxTrailingChars",
423 "ParaVertAlignment",
424 "ParaUserDefinedAttributes",
425 "NumberingIsNumber",
426 "ParaIsConnectBorder",
427 NULL
430 //....................................................................
431 static void lcl_initializeCharacterAttributes( const Reference< XPropertySet >& _rxModel )
433 // need to initialize the attributes from the "Default" style of the document we live in
437 // the style family collection
438 Reference< XStyleFamiliesSupplier > xSuppStyleFamilies = getTypedModelNode< XStyleFamiliesSupplier >( _rxModel.get() );
439 Reference< XNameAccess > xStyleFamilies;
440 if ( xSuppStyleFamilies.is() )
441 xStyleFamilies = xSuppStyleFamilies->getStyleFamilies();
442 OSL_ENSURE( xStyleFamilies.is(), "lcl_initializeCharacterAttributes: could not obtain the style families!" );
443 if ( !xStyleFamilies.is() )
444 return;
446 // the names of the family, and the style - depends on the document type we live in
447 ::rtl::OUString sFamilyName, sStyleName;
448 bool bKnownDocumentType = lcl_getDocumentDefaultStyleAndFamily( xSuppStyleFamilies.get(), sFamilyName, sStyleName );
449 OSL_ENSURE( bKnownDocumentType, "lcl_initializeCharacterAttributes: Huh? What document type is this?" );
450 if ( !bKnownDocumentType )
451 return;
453 // the concrete style
454 Reference< XNameAccess > xStyleFamily( xStyleFamilies->getByName( sFamilyName ), UNO_QUERY );
455 Reference< XPropertySet > xStyle;
456 if ( xStyleFamily.is() )
457 xStyleFamily->getByName( sStyleName ) >>= xStyle;
458 OSL_ENSURE( xStyle.is(), "lcl_initializeCharacterAttributes: could not retrieve the style!" );
459 if ( !xStyle.is() )
460 return;
462 // transfer all properties which are described by the com.sun.star.style.
463 Reference< XPropertySetInfo > xSourcePropInfo( xStyle->getPropertySetInfo() );
464 Reference< XPropertySetInfo > xDestPropInfo( _rxModel->getPropertySetInfo() );
465 OSL_ENSURE( xSourcePropInfo.is() && xDestPropInfo.is(), "lcl_initializeCharacterAttributes: no property set info!" );
466 if ( !xSourcePropInfo.is() || !xDestPropInfo.is() )
467 return;
469 ::rtl::OUString sPropertyName;
470 const sal_Char** pCharacterProperty = aCharacterAndParagraphProperties;
471 while ( *pCharacterProperty )
473 sPropertyName = ::rtl::OUString::createFromAscii( *pCharacterProperty );
475 if ( xSourcePropInfo->hasPropertyByName( sPropertyName ) && xDestPropInfo->hasPropertyByName( sPropertyName ) )
476 _rxModel->setPropertyValue( sPropertyName, xStyle->getPropertyValue( sPropertyName ) );
478 ++pCharacterProperty;
481 catch( const Exception& )
483 DBG_UNHANDLED_EXCEPTION();
488 //--------------------------------------------------------------------
489 sal_Int16 FormControlFactory::initializeControlModel( const DocumentType _eDocType, const Reference< XPropertySet >& _rxControlModel,
490 const Rectangle& _rControlBoundRect )
492 sal_Int16 nClassId = FormComponentType::CONTROL;
494 OSL_ENSURE( _rxControlModel.is(), "FormControlFactory::initializeControlModel: invalid model!" );
495 if ( !_rxControlModel.is() )
496 return nClassId;
500 ControlLayouter::initializeControlLayout( _rxControlModel, _eDocType );
502 _rxControlModel->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId;
503 Reference< XPropertySetInfo > xPSI( _rxControlModel->getPropertySetInfo(), UNO_SET_THROW );
504 switch ( nClassId )
506 case FormComponentType::SCROLLBAR:
507 _rxControlModel->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LiveScroll" ) ), makeAny( (sal_Bool)sal_True ) );
508 // NO break!
509 case FormComponentType::SPINBUTTON:
511 sal_Int32 eOrientation = ScrollBarOrientation::HORIZONTAL;
512 if ( !_rControlBoundRect.IsEmpty() && ( _rControlBoundRect.GetWidth() < _rControlBoundRect.GetHeight() ) )
513 eOrientation = ScrollBarOrientation::VERTICAL;
514 _rxControlModel->setPropertyValue( FM_PROP_ORIENTATION, makeAny( eOrientation ) );
516 break;
518 case FormComponentType::LISTBOX:
519 case FormComponentType::COMBOBOX:
521 sal_Bool bDropDown = !_rControlBoundRect.IsEmpty() && ( _rControlBoundRect.GetWidth() >= 3 * _rControlBoundRect.GetHeight() );
522 _rxControlModel->setPropertyValue( FM_PROP_DROPDOWN, makeAny( (sal_Bool)bDropDown ) );
523 _rxControlModel->setPropertyValue( FM_PROP_LINECOUNT, makeAny( sal_Int16( 20 ) ) );
525 break;
527 case FormComponentType::TEXTFIELD:
529 initializeTextFieldLineEnds( _rxControlModel );
530 lcl_initializeCharacterAttributes( _rxControlModel );
532 if ( !_rControlBoundRect.IsEmpty()
533 && !( _rControlBoundRect.GetWidth() > 4 * _rControlBoundRect.GetHeight() )
536 if ( xPSI->hasPropertyByName( FM_PROP_MULTILINE ) )
537 _rxControlModel->setPropertyValue( FM_PROP_MULTILINE, makeAny( (sal_Bool)sal_True ) );
540 break;
542 case FormComponentType::RADIOBUTTON:
543 case FormComponentType::CHECKBOX:
544 case FormComponentType::FIXEDTEXT:
546 ::rtl::OUString sVertAlignPropertyName( RTL_CONSTASCII_USTRINGPARAM( "VerticalAlign" ) );
547 if ( xPSI->hasPropertyByName( sVertAlignPropertyName ) )
548 _rxControlModel->setPropertyValue( sVertAlignPropertyName, makeAny( VerticalAlignment_MIDDLE ) );
550 break;
552 case FormComponentType::IMAGEBUTTON:
553 case FormComponentType::IMAGECONTROL:
555 const ::rtl::OUString sScaleModeProperty( RTL_CONSTASCII_USTRINGPARAM( "ScaleMode" ) );
556 if ( xPSI->hasPropertyByName( sScaleModeProperty ) )
557 _rxControlModel->setPropertyValue( sScaleModeProperty, makeAny( ImageScaleMode::Isotropic ) );
559 break;
562 // initial default label for the control
563 if ( xPSI->hasPropertyByName( FM_PROP_LABEL ) )
565 ::rtl::OUString sExistingLabel;
566 OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_LABEL ) >>= sExistingLabel );
567 if ( !sExistingLabel.getLength() )
569 ::rtl::OUString sInitialLabel;
570 OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_NAME ) >>= sInitialLabel );
572 sal_uInt16 nTitleResId = 0;
573 switch ( nClassId )
575 case FormComponentType::COMMANDBUTTON: nTitleResId = RID_STR_PROPTITLE_PUSHBUTTON; break;
576 case FormComponentType::RADIOBUTTON: nTitleResId = RID_STR_PROPTITLE_RADIOBUTTON; break;
577 case FormComponentType::CHECKBOX: nTitleResId = RID_STR_PROPTITLE_CHECKBOX; break;
578 case FormComponentType::GROUPBOX: nTitleResId = RID_STR_PROPTITLE_GROUPBOX; break;
579 case FormComponentType::FIXEDTEXT: nTitleResId = RID_STR_PROPTITLE_FIXEDTEXT; break;
582 if ( nTitleResId )
583 sInitialLabel = String( SVX_RES( nTitleResId ) );
585 _rxControlModel->setPropertyValue(
586 FM_PROP_LABEL,
587 makeAny( lcl_getUniqueLabel_nothrow( _rxControlModel, sInitialLabel ) )
592 // strict format = yes is the default (i93467)
593 if ( xPSI->hasPropertyByName( FM_PROP_STRICTFORMAT ) )
595 _rxControlModel->setPropertyValue( FM_PROP_STRICTFORMAT, makeAny( sal_Bool( sal_True ) ) );
598 if ( xPSI->hasPropertyByName( FM_PROP_WRITING_MODE ) )
599 _rxControlModel->setPropertyValue( FM_PROP_WRITING_MODE, makeAny( WritingMode2::CONTEXT ) );
601 catch( const Exception& )
603 DBG_UNHANDLED_EXCEPTION();
605 return nClassId;
608 //------------------------------------------------------------------------------
609 void FormControlFactory::initializeTextFieldLineEnds( const Reference< XPropertySet >& _rxModel )
611 OSL_PRECOND( _rxModel.is(), "initializeTextFieldLineEnds: invalid model!" );
612 if ( !_rxModel.is() )
613 return;
617 Reference< XPropertySetInfo > xInfo = _rxModel->getPropertySetInfo();
618 if ( !xInfo.is() || !xInfo->hasPropertyByName( FM_PROP_LINEENDFORMAT ) )
619 return;
621 // let's see if the data source which the form belongs to (if any)
622 // has a setting for the preferred line end format
623 sal_Bool bDosLineEnds = sal_False;
624 Sequence< PropertyValue > aInfo = lcl_getDataSourceIndirectProperties( _rxModel, m_pData->m_aContext );
625 const PropertyValue* pInfo = aInfo.getConstArray();
626 const PropertyValue* pInfoEnd = pInfo + aInfo.getLength();
627 for ( ; pInfo != pInfoEnd; ++pInfo )
629 if ( pInfo->Name.equalsAscii( "PreferDosLikeLineEnds" ) )
631 pInfo->Value >>= bDosLineEnds;
632 break;
636 sal_Int16 nLineEndFormat = bDosLineEnds ? LineEndFormat::CARRIAGE_RETURN_LINE_FEED : LineEndFormat::LINE_FEED;
637 _rxModel->setPropertyValue( FM_PROP_LINEENDFORMAT, makeAny( nLineEndFormat ) );
639 catch( const Exception& )
641 DBG_UNHANDLED_EXCEPTION();
645 //------------------------------------------------------------------------------
646 void FormControlFactory::initializeFieldDependentProperties( const Reference< XPropertySet >& _rxDatabaseField,
647 const Reference< XPropertySet >& _rxControlModel, const Reference< XNumberFormats >& _rxNumberFormats )
649 OSL_PRECOND( _rxDatabaseField.is() && _rxControlModel.is(),
650 "FormControlFactory::initializeFieldDependentProperties: illegal params!" );
651 if ( !_rxDatabaseField.is() || !_rxControlModel.is() )
652 return;
656 ////////////////////////////////////////////////////////////////////////
657 // if the field has a numeric format, and the model has a "Scale" property, sync it
658 Reference< XPropertySetInfo > xFieldPSI( _rxDatabaseField->getPropertySetInfo(), UNO_SET_THROW );
659 Reference< XPropertySetInfo > xModelPSI( _rxControlModel->getPropertySetInfo(), UNO_SET_THROW );
661 if ( xModelPSI->hasPropertyByName( FM_PROP_DECIMAL_ACCURACY ) )
663 sal_Int32 nFormatKey = 0;
664 if ( xFieldPSI->hasPropertyByName( FM_PROP_FORMATKEY ) )
666 _rxDatabaseField->getPropertyValue( FM_PROP_FORMATKEY ) >>= nFormatKey;
668 else
670 nFormatKey = OStaticDataAccessTools().getDefaultNumberFormat(
671 _rxDatabaseField,
672 Reference< XNumberFormatTypes >( _rxNumberFormats, UNO_QUERY ),
673 SvtSysLocale().GetLocaleData().getLocale()
677 Any aScaleVal( ::comphelper::getNumberFormatDecimals( _rxNumberFormats, nFormatKey ) );
678 _rxControlModel->setPropertyValue( FM_PROP_DECIMAL_ACCURACY, aScaleVal );
681 ////////////////////////////////////////////////////////////////////////
682 // minimum and maximum of the control according to the type of the database field
683 sal_Int32 nDataType = DataType::OTHER;
684 OSL_VERIFY( _rxDatabaseField->getPropertyValue( FM_PROP_FIELDTYPE ) >>= nDataType );
686 if ( xModelPSI->hasPropertyByName( FM_PROP_VALUEMIN )
687 && xModelPSI->hasPropertyByName( FM_PROP_VALUEMAX )
690 sal_Int32 nMinValue = -1000000000, nMaxValue = 1000000000;
691 switch ( nDataType )
693 case DataType::TINYINT : nMinValue = 0; nMaxValue = 255; break;
694 case DataType::SMALLINT : nMinValue = -32768; nMaxValue = 32767; break;
695 case DataType::INTEGER : nMinValue = 0x80000000; nMaxValue = 0x7FFFFFFF; break;
696 // double and singles are ignored
699 Any aValue;
701 // both the minimum and the maximum value properties can be either Long or Double
702 Property aProperty = xModelPSI->getPropertyByName( FM_PROP_VALUEMIN );
703 if ( aProperty.Type.getTypeClass() == TypeClass_DOUBLE )
704 aValue <<= (double)nMinValue;
705 else if ( aProperty.Type.getTypeClass() == TypeClass_LONG )
706 aValue <<= (sal_Int32)nMinValue;
707 else
709 DBG_ERROR( "FormControlFactory::initializeFieldDependentProperties: unexpected property type (MinValue)!" );
711 _rxControlModel->setPropertyValue( FM_PROP_VALUEMIN, aValue );
713 // both the minimum and the maximum value properties can be either Long or Double
714 aProperty = xModelPSI->getPropertyByName( FM_PROP_VALUEMAX );
715 if ( aProperty.Type.getTypeClass() == TypeClass_DOUBLE )
716 aValue <<= (double)nMaxValue;
717 else if ( aProperty.Type.getTypeClass() == TypeClass_LONG )
718 aValue <<= (sal_Int32)nMaxValue;
719 else
721 DBG_ERROR( "FormControlFactory::initializeFieldDependentProperties: unexpected property type (MaxValue)!" );
723 _rxControlModel->setPropertyValue( FM_PROP_VALUEMAX, aValue );
726 ////////////////////////////////////////////////////////////////////////
727 // a check box can be tristate if and only if the column it is bound to is nullable
728 sal_Int16 nClassId = FormComponentType::CONTROL;
729 OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId );
730 if ( nClassId == FormComponentType::CHECKBOX )
732 sal_Int32 nNullable = ColumnValue::NULLABLE_UNKNOWN;
733 OSL_VERIFY( _rxDatabaseField->getPropertyValue( FM_PROP_ISNULLABLE ) >>= nNullable );
734 _rxControlModel->setPropertyValue( FM_PROP_TRISTATE, makeAny( sal_Bool( ColumnValue::NO_NULLS != nNullable ) ) );
737 catch( const Exception& )
739 DBG_UNHANDLED_EXCEPTION();
743 //------------------------------------------------------------------------------
744 ::rtl::OUString FormControlFactory::getDefaultName( sal_Int16 _nClassId, const Reference< XServiceInfo >& _rxObject )
746 sal_uInt16 nResId(0);
748 switch ( _nClassId )
750 case FormComponentType::COMMANDBUTTON: nResId = RID_STR_PROPTITLE_PUSHBUTTON; break;
751 case FormComponentType::RADIOBUTTON: nResId = RID_STR_PROPTITLE_RADIOBUTTON; break;
752 case FormComponentType::CHECKBOX: nResId = RID_STR_PROPTITLE_CHECKBOX; break;
753 case FormComponentType::LISTBOX: nResId = RID_STR_PROPTITLE_LISTBOX; break;
754 case FormComponentType::COMBOBOX: nResId = RID_STR_PROPTITLE_COMBOBOX; break;
755 case FormComponentType::GROUPBOX: nResId = RID_STR_PROPTITLE_GROUPBOX; break;
756 case FormComponentType::IMAGEBUTTON: nResId = RID_STR_PROPTITLE_IMAGEBUTTON; break;
757 case FormComponentType::FIXEDTEXT: nResId = RID_STR_PROPTITLE_FIXEDTEXT; break;
758 case FormComponentType::GRIDCONTROL: nResId = RID_STR_PROPTITLE_DBGRID; break;
759 case FormComponentType::FILECONTROL: nResId = RID_STR_PROPTITLE_FILECONTROL; break;
760 case FormComponentType::DATEFIELD: nResId = RID_STR_PROPTITLE_DATEFIELD; break;
761 case FormComponentType::TIMEFIELD: nResId = RID_STR_PROPTITLE_TIMEFIELD; break;
762 case FormComponentType::NUMERICFIELD: nResId = RID_STR_PROPTITLE_NUMERICFIELD; break;
763 case FormComponentType::CURRENCYFIELD: nResId = RID_STR_PROPTITLE_CURRENCYFIELD; break;
764 case FormComponentType::PATTERNFIELD: nResId = RID_STR_PROPTITLE_PATTERNFIELD; break;
765 case FormComponentType::IMAGECONTROL: nResId = RID_STR_PROPTITLE_IMAGECONTROL; break;
766 case FormComponentType::HIDDENCONTROL: nResId = RID_STR_PROPTITLE_HIDDEN; break;
767 case FormComponentType::SCROLLBAR: nResId = RID_STR_PROPTITLE_SCROLLBAR; break;
768 case FormComponentType::SPINBUTTON: nResId = RID_STR_PROPTITLE_SPINBUTTON; break;
769 case FormComponentType::NAVIGATIONBAR: nResId = RID_STR_PROPTITLE_NAVBAR; break;
771 case FormComponentType::TEXTFIELD:
772 nResId = RID_STR_PROPTITLE_EDIT;
773 if ( _rxObject.is() && _rxObject->supportsService( FM_SUN_COMPONENT_FORMATTEDFIELD ) )
774 nResId = RID_STR_PROPTITLE_FORMATTED;
775 break;
777 default:
778 nResId = RID_STR_CONTROL; break;
781 return String( SVX_RES( nResId ) );
784 //------------------------------------------------------------------------------
785 ::rtl::OUString FormControlFactory::getDefaultUniqueName_ByComponentType( const Reference< XNameAccess >& _rxContainer,
786 const Reference< XPropertySet >& _rxObject )
788 sal_Int16 nClassId = FormComponentType::CONTROL;
789 OSL_VERIFY( _rxObject->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId );
790 ::rtl::OUString sBaseName = getDefaultName( nClassId, Reference< XServiceInfo >( _rxObject, UNO_QUERY ) );
792 return getUniqueName( _rxContainer, sBaseName );
795 //------------------------------------------------------------------------------
796 ::rtl::OUString FormControlFactory::getUniqueName( const Reference< XNameAccess >& _rxContainer, const ::rtl::OUString& _rBaseName )
798 sal_Int32 n = 0;
799 ::rtl::OUString sName;
802 ::rtl::OUStringBuffer aBuf( _rBaseName );
803 aBuf.appendAscii( " " );
804 aBuf.append( ++n );
805 sName = aBuf.makeStringAndClear();
807 while ( _rxContainer->hasByName( sName ) );
809 return sName;
812 //........................................................................
813 } // namespace svxform
814 //........................................................................