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