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 "fmcontrollayout.hxx"
28 #include "fmprop.hrc"
29 
30 /** === begin UNO includes === **/
31 #include <com/sun/star/form/FormComponentType.hpp>
32 #include <com/sun/star/awt/VisualEffect.hpp>
33 #include <com/sun/star/i18n/ScriptType.hpp>
34 #include <com/sun/star/lang/Locale.hpp>
35 #include <com/sun/star/awt/FontDescriptor.hpp>
36 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/container/XChild.hpp>
39 /** === end UNO includes === **/
40 
41 #include <comphelper/processfactory.hxx>
42 #include <i18npool/mslangid.hxx>
43 #include <unotools/syslocale.hxx>
44 
45 #include <toolkit/helper/vclunohelper.hxx>
46 #include <tools/debug.hxx>
47 #include <tools/diagnose_ex.h>
48 #include <vcl/outdev.hxx>
49 
50 //........................................................................
51 namespace svxform
52 {
53 //........................................................................
54 
55     using namespace ::utl;
56 	/** === begin UNO using === **/
57 	using ::com::sun::star::uno::Reference;
58 	using ::com::sun::star::uno::XInterface;
59 	using ::com::sun::star::uno::UNO_QUERY;
60 	using ::com::sun::star::uno::UNO_QUERY_THROW;
61 	using ::com::sun::star::uno::UNO_SET_THROW;
62 	using ::com::sun::star::uno::Exception;
63 	using ::com::sun::star::uno::RuntimeException;
64 	using ::com::sun::star::uno::Any;
65 	using ::com::sun::star::uno::makeAny;
66 	using ::com::sun::star::uno::Sequence;
67 	using ::com::sun::star::uno::Type;
68     using ::com::sun::star::beans::XPropertySet;
69     using ::com::sun::star::beans::XPropertySetInfo;
70     using ::com::sun::star::lang::Locale;
71     using ::com::sun::star::awt::FontDescriptor;
72     using ::com::sun::star::style::XStyleFamiliesSupplier;
73     using ::com::sun::star::lang::XServiceInfo;
74     using ::com::sun::star::container::XNameAccess;
75     using ::com::sun::star::container::XChild;
76 	/** === end UNO using === **/
77     namespace FormComponentType = ::com::sun::star::form::FormComponentType;
78     namespace VisualEffect = ::com::sun::star::awt::VisualEffect;
79     namespace ScriptType = ::com::sun::star::i18n::ScriptType;
80 
81 	//--------------------------------------------------------------------
82     namespace
83     {
84         //....................................................................
85         template< class INTERFACE_TYPE >
getTypedModelNode(const Reference<XInterface> & _rxModelNode)86         Reference< INTERFACE_TYPE > getTypedModelNode( const Reference< XInterface >& _rxModelNode )
87         {
88             Reference< INTERFACE_TYPE > xTypedNode( _rxModelNode, UNO_QUERY );
89             if ( xTypedNode.is() )
90                 return xTypedNode;
91             else
92             {
93                 Reference< XChild > xChild( _rxModelNode, UNO_QUERY );
94                 if ( xChild.is() )
95                     return getTypedModelNode< INTERFACE_TYPE >( xChild->getParent() );
96                 else
97                     return NULL;
98             }
99         }
100 
101         //....................................................................
lcl_getDocumentDefaultStyleAndFamily(const Reference<XInterface> & _rxDocument,::rtl::OUString & _rFamilyName,::rtl::OUString & _rStyleName)102         static bool lcl_getDocumentDefaultStyleAndFamily( const Reference< XInterface >& _rxDocument, ::rtl::OUString& _rFamilyName, ::rtl::OUString& _rStyleName ) SAL_THROW(( Exception ))
103         {
104             bool bSuccess = true;
105             Reference< XServiceInfo > xDocumentSI( _rxDocument, UNO_QUERY );
106             if ( xDocumentSI.is() )
107             {
108                 if (  xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" ) ) )
109                    || xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.WebDocument" ) ) )
110                    )
111                 {
112                     _rFamilyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ParagraphStyles" ) );
113                     _rStyleName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
114                 }
115                 else if ( xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.SpreadsheetDocument" ) ) ) )
116                 {
117                     _rFamilyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CellStyles" ) );
118                     _rStyleName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Default" ) );
119                 }
120                 else if (  xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DrawingDocument" ) ) )
121                         || xDocumentSI->supportsService( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" ) ) )
122                         )
123                 {
124                     _rFamilyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "graphics" ) );
125                     _rStyleName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "standard" ) );
126                 }
127                 else
128                     bSuccess = false;
129             }
130             return bSuccess;
131         }
132 
133         //....................................................................
lcl_initializeControlFont(const Reference<XPropertySet> & _rxModel)134         static void lcl_initializeControlFont( const Reference< XPropertySet >& _rxModel )
135         {
136             try
137             {
138                 Reference< XPropertySet > xStyle( ControlLayouter::getDefaultDocumentTextStyle( _rxModel ), UNO_SET_THROW );
139                 Reference< XPropertySetInfo > xStylePSI( xStyle->getPropertySetInfo(), UNO_SET_THROW );
140 
141                 // determine the script type associated with the system locale
142                 const LocaleDataWrapper& rSysLocaleData = SvtSysLocale().GetLocaleData();
143                 const sal_Int16 eSysLocaleScriptType = MsLangId::getScriptType( MsLangId::convertLocaleToLanguage( rSysLocaleData.getLocale() ) );
144 
145                 // depending on this script type, use the right property from the document's style which controls the
146                 // default locale for document content
147                 const sal_Char* pCharLocalePropertyName = "CharLocale";
148                 switch ( eSysLocaleScriptType )
149                 {
150                 case ScriptType::LATIN:
151                     // already defaulted above
152                     break;
153                 case ScriptType::ASIAN:
154                     pCharLocalePropertyName = "CharLocaleAsian";
155                     break;
156                 case ScriptType::COMPLEX:
157                     pCharLocalePropertyName = "CharLocaleComplex";
158                     break;
159                 default:
160                     OSL_ENSURE( false, "lcl_initializeControlFont: unexpected script type for system locale!" );
161                     break;
162                 }
163 
164                 ::rtl::OUString sCharLocalePropertyName = ::rtl::OUString::createFromAscii( pCharLocalePropertyName );
165                 Locale aDocumentCharLocale;
166                 if ( xStylePSI->hasPropertyByName( sCharLocalePropertyName ) )
167                 {
168                     OSL_VERIFY( xStyle->getPropertyValue( sCharLocalePropertyName ) >>= aDocumentCharLocale );
169                 }
170                 // fall back to CharLocale property at the style
171                 if ( !aDocumentCharLocale.Language.getLength() )
172                 {
173                     sCharLocalePropertyName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CharLocale" ) );
174                     if ( xStylePSI->hasPropertyByName( sCharLocalePropertyName ) )
175                     {
176                         OSL_VERIFY( xStyle->getPropertyValue( sCharLocalePropertyName ) >>= aDocumentCharLocale );
177                     }
178                 }
179                 // fall back to the system locale
180                 if ( !aDocumentCharLocale.Language.getLength() )
181                 {
182                     aDocumentCharLocale = rSysLocaleData.getLocale();
183                 }
184 
185                 // retrieve a default font for this locale, and set it at the control
186                 Font aFont = OutputDevice::GetDefaultFont( DEFAULTFONT_SANS, MsLangId::convertLocaleToLanguage( aDocumentCharLocale ), DEFAULTFONT_FLAGS_ONLYONE );
187                 FontDescriptor aFontDesc = VCLUnoHelper::CreateFontDescriptor( aFont );
188                 _rxModel->setPropertyValue(
189                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FontDescriptor" ) ),
190                     makeAny( aFontDesc )
191                 );
192             }
193             catch( const Exception& )
194             {
195                 DBG_UNHANDLED_EXCEPTION();
196             }
197         }
198     }
199 
200     //====================================================================
201 	//= ControlLayouter
202 	//====================================================================
203 	//--------------------------------------------------------------------
getDefaultDocumentTextStyle(const Reference<XPropertySet> & _rxModel)204     Reference< XPropertySet > ControlLayouter::getDefaultDocumentTextStyle( const Reference< XPropertySet >& _rxModel )
205     {
206         // the style family collection
207         Reference< XStyleFamiliesSupplier > xSuppStyleFamilies( getTypedModelNode< XStyleFamiliesSupplier >( _rxModel.get() ), UNO_SET_THROW );
208         Reference< XNameAccess > xStyleFamilies( xSuppStyleFamilies->getStyleFamilies(), UNO_SET_THROW );
209 
210         // the names of the family, and the style - depends on the document type we live in
211         ::rtl::OUString sFamilyName, sStyleName;
212         if ( !lcl_getDocumentDefaultStyleAndFamily( xSuppStyleFamilies.get(), sFamilyName, sStyleName ) )
213             throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unknown document type!" ) ), NULL );
214 
215         // the concrete style
216         Reference< XNameAccess > xStyleFamily( xStyleFamilies->getByName( sFamilyName ), UNO_QUERY_THROW );
217         return Reference< XPropertySet >( xStyleFamily->getByName( sStyleName ), UNO_QUERY_THROW );
218     }
219 
220 	//--------------------------------------------------------------------
initializeControlLayout(const Reference<XPropertySet> & _rxControlModel,DocumentType _eDocType)221     void ControlLayouter::initializeControlLayout( const Reference< XPropertySet >& _rxControlModel, DocumentType _eDocType )
222     {
223         DBG_ASSERT( _rxControlModel.is(), "ControlLayouter::initializeControlLayout: invalid model!" );
224         if ( !_rxControlModel.is() )
225             return;
226 
227         try
228         {
229             Reference< XPropertySetInfo > xPSI( _rxControlModel->getPropertySetInfo(), UNO_SET_THROW );
230 
231             // the control type
232             sal_Int16 nClassId = FormComponentType::CONTROL;
233             _rxControlModel->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId;
234 
235             // the document type
236             if ( _eDocType == eUnknownDocumentType )
237                 _eDocType = DocumentClassification::classifyHostDocument( _rxControlModel.get() );
238 
239             // let's see what the configuration says about the visual effect
240             OConfigurationNode  aConfig = getLayoutSettings( _eDocType );
241             Any aVisualEffect = aConfig.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VisualEffect" ) ) );
242             if ( aVisualEffect.hasValue() )
243             {
244                 ::rtl::OUString sVisualEffect;
245                 OSL_VERIFY( aVisualEffect >>= sVisualEffect );
246 
247                 sal_Int16 nVisualEffect = VisualEffect::NONE;
248                 if ( sVisualEffect.equalsAscii( "flat" ) )
249                     nVisualEffect = VisualEffect::FLAT;
250                 else if ( sVisualEffect.equalsAscii( "3D" ) )
251                     nVisualEffect = VisualEffect::LOOK3D;
252 
253                 if ( xPSI->hasPropertyByName( FM_PROP_BORDER ) )
254                 {
255                     if  (  ( nClassId != FormComponentType::COMMANDBUTTON )
256                         && ( nClassId != FormComponentType::RADIOBUTTON )
257 						&& ( nClassId != FormComponentType::CHECKBOX	)
258                         && ( nClassId != FormComponentType::GROUPBOX )
259                         && ( nClassId != FormComponentType::FIXEDTEXT )
260                         && ( nClassId != FormComponentType::SCROLLBAR )
261                         && ( nClassId != FormComponentType::SPINBUTTON )
262                         )
263                     {
264                         _rxControlModel->setPropertyValue( FM_PROP_BORDER, makeAny( nVisualEffect ) );
265                         if  (   ( nVisualEffect == VisualEffect::FLAT )
266                             &&  ( xPSI->hasPropertyByName( FM_PROP_BORDERCOLOR ) )
267                             )
268                             // light gray flat border
269                             _rxControlModel->setPropertyValue( FM_PROP_BORDERCOLOR, makeAny( (sal_Int32)0x00C0C0C0 ) );
270                     }
271                 }
272                 if ( xPSI->hasPropertyByName( FM_PROP_VISUALEFFECT ) )
273                     _rxControlModel->setPropertyValue( FM_PROP_VISUALEFFECT, makeAny( nVisualEffect ) );
274             }
275 
276             // the font (only if we use the document's ref devices for rendering control text, otherwise, the
277             // default font of VCL controls is assumed to be fine)
278             if  (   useDocumentReferenceDevice( _eDocType )
279                 &&  xPSI->hasPropertyByName( FM_PROP_FONT )
280                 )
281                 lcl_initializeControlFont( _rxControlModel );
282         }
283         catch( const Exception& )
284         {
285         	OSL_ENSURE( sal_False, "ControlLayouter::initializeControlLayout: caught an exception!" );
286         }
287     }
288 
289 	//--------------------------------------------------------------------
getLayoutSettings(DocumentType _eDocType)290     ::utl::OConfigurationNode ControlLayouter::getLayoutSettings( DocumentType _eDocType )
291     {
292         ::rtl::OUString sConfigName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Forms/ControlLayout/" ) );
293         sConfigName += DocumentClassification::getModuleIdentifierForDocumentType( _eDocType );
294         return OConfigurationTreeRoot::createWithServiceFactory(
295             ::comphelper::getProcessServiceFactory(),    // TODO
296             sConfigName );
297     }
298 
299 	//--------------------------------------------------------------------
useDynamicBorderColor(DocumentType _eDocType)300     bool ControlLayouter::useDynamicBorderColor( DocumentType _eDocType )
301     {
302         OConfigurationNode aConfig = getLayoutSettings( _eDocType );
303         Any aDynamicBorderColor = aConfig.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DynamicBorderColors" ) ) );
304         bool bDynamicBorderColor = false;
305         OSL_VERIFY( aDynamicBorderColor >>= bDynamicBorderColor );
306         return bDynamicBorderColor;
307     }
308 
309 	//--------------------------------------------------------------------
useDocumentReferenceDevice(DocumentType _eDocType)310     bool ControlLayouter::useDocumentReferenceDevice( DocumentType _eDocType )
311     {
312         if ( _eDocType == eUnknownDocumentType )
313             return false;
314         OConfigurationNode aConfig = getLayoutSettings( _eDocType );
315         Any aUseRefDevice = aConfig.getNodeValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentTextMetrics" ) ) );
316         bool bUseRefDevice = false;
317         OSL_VERIFY( aUseRefDevice >>= bUseRefDevice );
318         return bUseRefDevice;
319     }
320 
321 //........................................................................
322 } // namespace svxform
323 //........................................................................
324 
325