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