xref: /trunk/main/xmloff/source/style/prstylei.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 
31 
32 #include <tools/debug.hxx>
33 #ifndef __SGI_STL_SET
34 #include <set>
35 #endif
36 #include "xmloff/xmlnmspe.hxx"
37 #include <xmloff/xmltoken.hxx>
38 #include <xmloff/xmlprcon.hxx>
39 #include <com/sun/star/style/XStyle.hpp>
40 #include <com/sun/star/style/XAutoStyleFamily.hpp>
41 #include <com/sun/star/container/XNameContainer.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/beans/XPropertyState.hpp>
44 #include <com/sun/star/beans/XMultiPropertyStates.hpp>
45 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
46 #include <xmloff/xmlimp.hxx>
47 
48 #ifndef _XMLOFF_PRSTYLEI_HXX
49 #include <xmloff/prstylei.hxx>
50 #endif
51 #include <xmloff/attrlist.hxx>
52 #include "xmloff/xmlerror.hxx"
53 
54 using ::rtl::OUString;
55 using ::rtl::OUStringBuffer;
56 
57 using namespace ::com::sun::star;
58 using namespace ::com::sun::star::uno;
59 using namespace ::com::sun::star::xml::sax;
60 using namespace ::com::sun::star::style;
61 using namespace ::com::sun::star::container;
62 using namespace ::com::sun::star::beans;
63 using namespace ::com::sun::star::lang;
64 using namespace ::xmloff::token;
65 
66 
67 void XMLPropStyleContext::SetAttribute( sal_uInt16 nPrefixKey,
68 										const OUString& rLocalName,
69 										const OUString& rValue )
70 {
71 	if( XML_NAMESPACE_STYLE == nPrefixKey && IsXMLToken( rLocalName, XML_FAMILY ) )
72 	{
73 		DBG_ASSERT( GetFamily() == ((SvXMLStylesContext *)&mxStyles)->GetFamily( rValue ), "unexpected style family" );
74 	}
75 	else
76 	{
77 		SvXMLStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
78 	}
79 }
80 
81 TYPEINIT1( XMLPropStyleContext, SvXMLStyleContext );
82 
83 XMLPropStyleContext::XMLPropStyleContext( SvXMLImport& rImport,
84 		sal_uInt16 nPrfx, const OUString& rLName,
85 		const Reference< XAttributeList > & xAttrList,
86 		SvXMLStylesContext& rStyles, sal_uInt16 nFamily,
87 		sal_Bool bDefault )
88 :	SvXMLStyleContext( rImport, nPrfx, rLName, xAttrList, nFamily, bDefault )
89 ,	msIsPhysical( RTL_CONSTASCII_USTRINGPARAM( "IsPhysical" ) )
90 ,	msFollowStyle( RTL_CONSTASCII_USTRINGPARAM( "FollowStyle" ) )
91 ,	mxStyles( &rStyles )
92 {
93 }
94 
95 XMLPropStyleContext::~XMLPropStyleContext()
96 {
97 }
98 
99 SvXMLImportContext *XMLPropStyleContext::CreateChildContext(
100 		sal_uInt16 nPrefix,
101 		const OUString& rLocalName,
102 		const Reference< XAttributeList > & xAttrList )
103 {
104 	SvXMLImportContext *pContext = 0;
105 
106 	sal_uInt32 nFamily = 0;
107 	if( XML_NAMESPACE_STYLE == nPrefix )
108 	{
109 		if( IsXMLToken( rLocalName, XML_GRAPHIC_PROPERTIES ) )
110 			nFamily = XML_TYPE_PROP_GRAPHIC;
111 		else if( IsXMLToken( rLocalName, XML_DRAWING_PAGE_PROPERTIES )  )
112 			nFamily = XML_TYPE_PROP_DRAWING_PAGE;
113 		else if( IsXMLToken( rLocalName, XML_TEXT_PROPERTIES )  )
114 			nFamily = XML_TYPE_PROP_TEXT;
115 		else if( IsXMLToken( rLocalName, XML_PARAGRAPH_PROPERTIES )  )
116 			nFamily = XML_TYPE_PROP_PARAGRAPH;
117 		else if( IsXMLToken( rLocalName, XML_RUBY_PROPERTIES )  )
118 			nFamily = XML_TYPE_PROP_RUBY;
119 		else if( IsXMLToken( rLocalName, XML_SECTION_PROPERTIES )  )
120 			nFamily = XML_TYPE_PROP_SECTION;
121 		else if( IsXMLToken( rLocalName, XML_TABLE_PROPERTIES )  )
122 			nFamily = XML_TYPE_PROP_TABLE;
123 		else if( IsXMLToken( rLocalName, XML_TABLE_COLUMN_PROPERTIES )  )
124 			nFamily = XML_TYPE_PROP_TABLE_COLUMN;
125 		else if( IsXMLToken( rLocalName, XML_TABLE_ROW_PROPERTIES )  )
126 			nFamily = XML_TYPE_PROP_TABLE_ROW;
127 		else if( IsXMLToken( rLocalName, XML_TABLE_CELL_PROPERTIES )  )
128 			nFamily = XML_TYPE_PROP_TABLE_CELL;
129 		else if( IsXMLToken( rLocalName, XML_CHART_PROPERTIES ) )
130 			nFamily = XML_TYPE_PROP_CHART;
131 	}
132 	if( nFamily )
133 	{
134 		UniReference < SvXMLImportPropertyMapper > xImpPrMap =
135 			((SvXMLStylesContext *)&mxStyles)->GetImportPropertyMapper(
136 														GetFamily() );
137 		if( xImpPrMap.is() )
138 			pContext = new SvXMLPropertySetContext( GetImport(), nPrefix,
139 													rLocalName, xAttrList,
140 													nFamily,
141 													maProperties,
142 													xImpPrMap );
143 	}
144 
145 	if( !pContext )
146 		pContext = SvXMLStyleContext::CreateChildContext( nPrefix, rLocalName,
147 														  xAttrList );
148 
149 	return pContext;
150 }
151 
152 void XMLPropStyleContext::FillPropertySet(
153 			const Reference< XPropertySet > & rPropSet )
154 {
155 	UniReference < SvXMLImportPropertyMapper > xImpPrMap =
156 		((SvXMLStylesContext *)&mxStyles)->GetImportPropertyMapper(
157 																GetFamily() );
158 	DBG_ASSERT( xImpPrMap.is(), "There is the import prop mapper" );
159 	if( xImpPrMap.is() )
160 		xImpPrMap->FillPropertySet( maProperties, rPropSet );
161 }
162 
163 void XMLPropStyleContext::SetDefaults()
164 {
165 }
166 
167 Reference < XStyle > XMLPropStyleContext::Create()
168 {
169 	Reference < XStyle > xNewStyle;
170 
171 	OUString sServiceName(
172 		((SvXMLStylesContext *)&mxStyles)->GetServiceName( GetFamily() ) );
173 	if( sServiceName.getLength() )
174 	{
175 		Reference< XMultiServiceFactory > xFactory( GetImport().GetModel(),
176 													UNO_QUERY );
177 		if( xFactory.is() )
178 		{
179 			Reference < XInterface > xIfc =
180 				xFactory->createInstance( sServiceName );
181 			if( xIfc.is() )
182 				xNewStyle = Reference < XStyle >( xIfc, UNO_QUERY );
183 		}
184 	}
185 
186 	return xNewStyle;
187 }
188 
189 typedef ::std::set < OUString, ::comphelper::UStringLess > PropertyNameSet;
190 
191 void XMLPropStyleContext::CreateAndInsert( sal_Bool bOverwrite )
192 {
193     if( ((SvXMLStylesContext *)&mxStyles)->IsAutomaticStyle()
194         && ( GetFamily() == XML_STYLE_FAMILY_TEXT_TEXT || GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH ) )
195     {
196         Reference < XAutoStyleFamily > xAutoFamily =
197                 ((SvXMLStylesContext *)&mxStyles)->GetAutoStyles( GetFamily() );
198         if( !xAutoFamily.is() )
199             return;
200         UniReference < SvXMLImportPropertyMapper > xImpPrMap =
201             ((SvXMLStylesContext *)&mxStyles)->GetImportPropertyMapper( GetFamily() );
202         DBG_ASSERT( xImpPrMap.is(), "There is no import prop mapper" );
203         if( xImpPrMap.is() )
204         {
205             Sequence< PropertyValue > aValues;
206             xImpPrMap->FillPropertySequence( maProperties, aValues );
207 
208             sal_Int32 nLen = aValues.getLength();
209             if( nLen )
210             {
211                 if( GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH )
212                 {
213                     aValues.realloc( nLen + 2 );
214                     PropertyValue *pProps = aValues.getArray() + nLen;
215                     pProps->Name = rtl::OUString::createFromAscii("ParaStyleName");
216                     OUString sParent( GetParentName() );
217                     if( sParent.getLength() )
218                         sParent = GetImport().GetStyleDisplayName( GetFamily(), sParent );
219                     else
220                         sParent =  rtl::OUString::createFromAscii("Standard");
221                     pProps->Value <<= sParent;
222                     ++pProps;
223                     pProps->Name = rtl::OUString::createFromAscii("ParaConditionalStyleName");
224                     pProps->Value <<= sParent;
225                 }
226 
227                 Reference < XAutoStyle > xAutoStyle = xAutoFamily->insertStyle( aValues );
228                 if( xAutoStyle.is() )
229                 {
230                     Sequence< OUString > aPropNames(1);
231                     aPropNames[0] = GetFamily() == XML_STYLE_FAMILY_TEXT_PARAGRAPH ?
232                         rtl::OUString::createFromAscii("ParaAutoStyleName") :
233                         rtl::OUString::createFromAscii("CharAutoStyleName");
234                     Sequence< Any > aAny = xAutoStyle->getPropertyValues( aPropNames );
235                     if( aAny.hasElements() )
236                     {
237                         OUString aName;
238                         aAny[0] >>= aName;
239                         SetAutoName( aName );
240                     }
241                 }
242             }
243         }
244     }
245     else
246     {
247         const OUString& rName = GetDisplayName();
248         if( 0 == rName.getLength() || IsDefaultStyle() )
249             return;
250 
251         Reference < XNameContainer > xFamilies =
252                 ((SvXMLStylesContext *)&mxStyles)->GetStylesContainer( GetFamily() );
253         if( !xFamilies.is() )
254             return;
255 
256         sal_Bool bNew = sal_False;
257         if( xFamilies->hasByName( rName ) )
258         {
259             Any aAny = xFamilies->getByName( rName );
260             aAny >>= mxStyle;
261         }
262         else
263         {
264             mxStyle = Create();
265             if( !mxStyle.is() )
266                 return;
267 
268             Any aAny;
269             aAny <<= mxStyle;
270             xFamilies->insertByName( rName, aAny );
271             bNew = sal_True;
272         }
273 
274         Reference < XPropertySet > xPropSet( mxStyle, UNO_QUERY );
275         Reference< XPropertySetInfo > xPropSetInfo =
276                     xPropSet->getPropertySetInfo();
277         if( !bNew && xPropSetInfo->hasPropertyByName( msIsPhysical ) )
278         {
279             Any aAny = xPropSet->getPropertyValue( msIsPhysical );
280             bNew = !*(sal_Bool *)aAny.getValue();
281         }
282         SetNew( bNew );
283         if( rName != GetName() )
284             GetImport().AddStyleDisplayName( GetFamily(), GetName(), rName );
285 
286         if( bOverwrite || bNew )
287         {
288             Reference< XPropertyState > xPropState( xPropSet, uno::UNO_QUERY );
289 
290             UniReference < XMLPropertySetMapper > xPrMap;
291             UniReference < SvXMLImportPropertyMapper > xImpPrMap =
292                 ((SvXMLStylesContext *)&mxStyles)->GetImportPropertyMapper(
293                                                                     GetFamily() );
294             DBG_ASSERT( xImpPrMap.is(), "There is the import prop mapper" );
295             if( xImpPrMap.is() )
296                 xPrMap = xImpPrMap->getPropertySetMapper();
297             if( xPrMap.is() )
298             {
299                 Reference < XMultiPropertyStates > xMultiStates( xPropSet,
300                                                                  UNO_QUERY );
301                 if( xMultiStates.is() )
302                 {
303                     xMultiStates->setAllPropertiesToDefault();
304                 }
305                 else
306                 {
307                     PropertyNameSet aNameSet;
308                     sal_Int32 nCount = xPrMap->GetEntryCount();
309                     sal_Int32 i;
310                     for( i = 0; i < nCount; i++ )
311                     {
312                         const OUString& rPrName = xPrMap->GetEntryAPIName( i );
313                         if( xPropSetInfo->hasPropertyByName( rPrName ) )
314                             aNameSet.insert( rPrName );
315                     }
316 
317                     nCount = aNameSet.size();
318                     Sequence < OUString > aNames( nCount );
319                     OUString *pNames = aNames.getArray();
320                     PropertyNameSet::iterator aIter = aNameSet.begin();
321                     while( aIter != aNameSet.end() )
322                         *pNames++ = *aIter++;
323 
324                     Sequence < PropertyState > aStates(
325                         xPropState->getPropertyStates( aNames ) );
326                     const PropertyState *pStates = aStates.getConstArray();
327                     pNames = aNames.getArray();
328 
329                     for( i = 0; i < nCount; i++ )
330                     {
331                         if( PropertyState_DIRECT_VALUE == *pStates++ )
332                             xPropState->setPropertyToDefault( pNames[i] );
333                     }
334                 }
335             }
336 
337             if (mxStyle.is())
338                 mxStyle->setParentStyle(OUString());
339 
340             FillPropertySet( xPropSet );
341         }
342         else
343         {
344             SetValid( sal_False );
345         }
346     }
347 }
348 
349 void XMLPropStyleContext::Finish( sal_Bool bOverwrite )
350 {
351 	if( mxStyle.is() && (IsNew() || bOverwrite) )
352 	{
353 		// The families cintaner must exist
354 		Reference < XNameContainer > xFamilies =
355 			((SvXMLStylesContext *)&mxStyles)->GetStylesContainer( GetFamily() );
356 		DBG_ASSERT( xFamilies.is(), "Families lost" );
357 		if( !xFamilies.is() )
358 			return;
359 
360 		// connect parent
361         OUString sParent( GetParentName() );
362 		if( sParent.getLength() )
363 			sParent = GetImport().GetStyleDisplayName( GetFamily(), sParent );
364 		if( sParent.getLength() && !xFamilies->hasByName( sParent ) )
365 			sParent = OUString();
366 
367         if(	sParent != mxStyle->getParentStyle() )
368         {
369             // this may except if setting the parent style forms a
370             // circle in the style depencies; especially if the parent
371             // style is the same as the current style
372             try
373             {
374                 mxStyle->setParentStyle( sParent );
375             }
376             catch( uno::Exception e )
377             {
378                 // according to the API definition, I would expect a
379                 // container::NoSuchElementException. But it throws an
380                 // uno::RuntimeException instead. I catch
381                 // uno::Exception in order to process both of them.
382 
383                 // We can't set the parent style. For a proper
384                 // Error-Message, we should pass in the name of the
385                 // style, as well as the desired parent style.
386                 Sequence<OUString> aSequence(2);
387 
388                 // getName() throws no non-Runtime exception:
389                 aSequence[0] = mxStyle->getName();
390                 aSequence[1] = sParent;
391 
392                 GetImport().SetError(
393                     XMLERROR_FLAG_ERROR | XMLERROR_PARENT_STYLE_NOT_ALLOWED,
394                     aSequence, e.Message, NULL );
395             }
396         }
397 
398 		// connect follow
399 		OUString sFollow( GetFollow() );
400 		if( sFollow.getLength() )
401 			sFollow = GetImport().GetStyleDisplayName( GetFamily(), sFollow );
402 		if( !sFollow.getLength() || !xFamilies->hasByName( sFollow ) )
403 			sFollow = mxStyle->getName();
404 
405 		Reference < XPropertySet > xPropSet( mxStyle, UNO_QUERY );
406 		Reference< XPropertySetInfo > xPropSetInfo =
407 			xPropSet->getPropertySetInfo();
408 		if( xPropSetInfo->hasPropertyByName( msFollowStyle ) )
409 		{
410 			Any aAny = xPropSet->getPropertyValue( msFollowStyle );
411 			OUString sCurrFollow;
412 			aAny >>= sCurrFollow;
413 			if( sCurrFollow != sFollow )
414 			{
415 				aAny <<= sFollow;
416 				xPropSet->setPropertyValue( msFollowStyle, aAny );
417 			}
418 		}
419 	}
420 }
421 
422 
423