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_xmloff.hxx"
26 
27 #include <tools/debug.hxx>
28 #include <xmloff/XMLShapeStyleContext.hxx>
29 #include "XMLShapePropertySetContext.hxx"
30 #include <xmloff/contextid.hxx>
31 #include <com/sun/star/drawing/XControlShape.hpp>
32 #include "com/sun/star/beans/XPropertySetInfo.hpp"
33 #include <com/sun/star/lang/IllegalArgumentException.hpp>
34 #include <com/sun/star/drawing/FillStyle.hpp>
35 #include <xmloff/xmlimp.hxx>
36 #include <xmloff/xmlnumi.hxx>
37 #include <xmloff/xmlnmspe.hxx>
38 #include <xmloff/xmltoken.hxx>
39 #include "xmloff/xmlerror.hxx"
40 #include <xmloff/maptype.hxx>
41 
42 #include "sdpropls.hxx"
43 
44 using ::rtl::OUString;
45 using ::rtl::OUStringBuffer;
46 
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::uno;
49 using namespace ::com::sun::star::beans;
50 using namespace ::com::sun::star::drawing;
51 using ::xmloff::token::IsXMLToken;
52 using ::xmloff::token::XML_TEXT_PROPERTIES;
53 using ::xmloff::token::XML_GRAPHIC_PROPERTIES;
54 using ::xmloff::token::XML_PARAGRAPH_PROPERTIES;
55 
56 //////////////////////////////////////////////////////////////////////////////
57 
58 TYPEINIT1( XMLShapeStyleContext, XMLPropStyleContext );
59 
60 XMLShapeStyleContext::XMLShapeStyleContext(
61 	SvXMLImport& rImport,
62 	sal_uInt16 nPrfx,
63 	const OUString& rLName,
64 	const uno::Reference< xml::sax::XAttributeList >& xAttrList,
65 	SvXMLStylesContext& rStyles,
66 	sal_uInt16 nFamily)
67 :	XMLPropStyleContext(rImport, nPrfx, rLName, xAttrList, rStyles, nFamily ),
68 	m_bIsNumRuleAlreadyConverted( sal_False ),
69     m_bIsFillStyleAlreadyConverted( sal_False ) //UUUU
70 {
71 }
72 
73 XMLShapeStyleContext::~XMLShapeStyleContext()
74 {
75 }
76 
77 void XMLShapeStyleContext::SetAttribute( sal_uInt16 nPrefixKey, const ::rtl::OUString& rLocalName, const ::rtl::OUString& rValue )
78 {
79 	if ((0 == m_sControlDataStyleName.getLength()) && (::xmloff::token::GetXMLToken(::xmloff::token::XML_DATA_STYLE_NAME) == rLocalName))
80 	{
81 		m_sControlDataStyleName = rValue;
82 	}
83 	else if( (XML_NAMESPACE_STYLE == nPrefixKey) && IsXMLToken( rLocalName, ::xmloff::token::XML_LIST_STYLE_NAME ) )
84 	{
85 		m_sListStyleName = rValue;
86 	}
87 	else
88 	{
89 		XMLPropStyleContext::SetAttribute( nPrefixKey, rLocalName, rValue );
90 
91 		if( (XML_NAMESPACE_STYLE == nPrefixKey) &&
92 			( IsXMLToken( rLocalName, ::xmloff::token::XML_NAME ) || IsXMLToken( rLocalName, ::xmloff::token::XML_DISPLAY_NAME ) ) )
93 		{
94 			if( GetName().getLength() && GetDisplayName().getLength() && GetName() != GetDisplayName() )
95 			{
96 				const_cast< SvXMLImport&>( GetImport() ).
97 					AddStyleDisplayName( GetFamily(), GetName(), GetDisplayName() );
98 			}
99 		}
100 	}
101 }
102 
103 SvXMLImportContext *XMLShapeStyleContext::CreateChildContext(
104 		sal_uInt16 nPrefix,
105 		const OUString& rLocalName,
106 		const Reference< xml::sax::XAttributeList > & xAttrList )
107 {
108 	SvXMLImportContext *pContext = 0;
109 
110 	if( XML_NAMESPACE_STYLE == nPrefix )
111 	{
112 		sal_uInt32 nFamily = 0;
113 		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_GRAPHIC_PROPERTIES ) )
118 			nFamily = XML_TYPE_PROP_GRAPHIC;
119 		if( nFamily )
120 		{
121 			UniReference < SvXMLImportPropertyMapper > xImpPrMap =
122 				GetStyles()->GetImportPropertyMapper( GetFamily() );
123 			if( xImpPrMap.is() )
124 				pContext = new XMLShapePropertySetContext( GetImport(), nPrefix,
125 														rLocalName, xAttrList,
126 														nFamily,
127 														GetProperties(),
128 														xImpPrMap );
129 		}
130 	}
131 
132 	if( !pContext )
133 		pContext = XMLPropStyleContext::CreateChildContext( nPrefix, rLocalName,
134 														  xAttrList );
135 
136 	return pContext;
137 }
138 
139 void XMLShapeStyleContext::FillPropertySet( const Reference< beans::XPropertySet > & rPropSet )
140 {
141 	if( !m_bIsNumRuleAlreadyConverted )
142 	{
143 		m_bIsNumRuleAlreadyConverted = sal_True;
144 
145 		// for compatibility to beta files, search for CTF_SD_NUMBERINGRULES_NAME to
146 		// import numbering rules from the style:properties element
147 		const UniReference< XMLPropertySetMapper >&rMapper = GetStyles()->GetImportPropertyMapper( GetFamily() )->getPropertySetMapper();
148 
149 		::std::vector< XMLPropertyState > &rProperties = GetProperties();
150 		::std::vector< XMLPropertyState >::iterator end( rProperties.end() );
151 		::std::vector< XMLPropertyState >::iterator property;
152 
153 		// first, look for the old format, where we had a text:list-style-name
154 		// attribute in the style:properties element
155 		for( property = rProperties.begin(); property != end; property++ )
156 		{
157 			// find properties with context
158 			if( (property->mnIndex != -1) && (rMapper->GetEntryContextId( property->mnIndex ) == CTF_SD_NUMBERINGRULES_NAME) )
159 				break;
160 		}
161 
162 		// if we did not find an old list-style-name in the properties, and we need one
163 		// because we got a style:list-style attribute in the style-style element
164 		// we generate one
165 		if( (property == end) && ( 0 != m_sListStyleName.getLength() ) )
166 		{
167 			sal_Int32 nIndex = rMapper->FindEntryIndex( CTF_SD_NUMBERINGRULES_NAME );
168 			DBG_ASSERT( -1 != nIndex, "can't find numbering rules property entry, can't set numbering rule!" );
169 
170 			XMLPropertyState aNewState( nIndex );
171 			rProperties.push_back( aNewState );
172 			end = rProperties.end();
173 			property = end - 1;
174 		}
175 
176 		// so, if we have an old or a new list style name, we set its value to
177 		// a numbering rule
178 		if( property != end )
179 		{
180 			if( 0 == m_sListStyleName.getLength() )
181 			{
182 				property->maValue >>= m_sListStyleName;
183 			}
184 
185 			const SvxXMLListStyleContext *pListStyle = GetImport().GetTextImport()->FindAutoListStyle( m_sListStyleName );
186 
187 			DBG_ASSERT( pListStyle, "list-style not found for shape style" );
188 			if( pListStyle )
189 			{
190 				uno::Reference< container::XIndexReplace > xNumRule( pListStyle->CreateNumRule( GetImport().GetModel() ) );
191 				pListStyle->FillUnoNumRule(xNumRule, NULL /* const SvI18NMap * ??? */ );
192 				property->maValue <<= xNumRule;
193 			}
194 			else
195 			{
196 				property->mnIndex = -1;
197 			}
198 		}
199 	}
200 
201     if(!m_bIsFillStyleAlreadyConverted && GetProperties().size())
202     {
203         const UniReference< XMLPropertySetMapper >&rMapper = GetStyles()->GetImportPropertyMapper(GetFamily())->getPropertySetMapper();
204         ::std::vector< XMLPropertyState >& rProperties = GetProperties();
205         ::std::vector< XMLPropertyState >::iterator a;
206         FillStyle eFS(FillStyle_NONE);
207         static ::rtl::OUString s_FillStyle(RTL_CONSTASCII_USTRINGPARAM("FillStyle"));
208 
209         // try to find a FillStyle entry and a value from it
210         for(a = rProperties.begin(); a != rProperties.end(); a++)
211         {
212             if(a->mnIndex != -1)
213             {
214                 const OUString& rPropName = rMapper->GetEntryAPIName(a->mnIndex);
215 
216                 if(rPropName == s_FillStyle)
217                 {
218                     if(a->maValue >>= eFS)
219                     {
220                         // okay, type was good, eFS is set
221                     }
222                     else
223                     {
224                         // also try an int (see XFillStyleItem::PutValue)
225                         sal_Int32 nFS = 0;
226 
227                         if(a->maValue >>= nFS)
228                         {
229                             eFS = (FillStyle)nFS;
230                         }
231                     }
232 
233                     // exit loop, we found out what we needed to know
234                     break;
235                 }
236             }
237         }
238 
239         if(FillStyle_NONE != eFS)
240         {
241             //UUUU a FillStyle was found, thus the new [XATTR_FILL_FIRST .. XATTR_FILL_LAST]
242             // description for the Fill definitions is used. All formally used props based
243             // on RES_BACKGROUND need to be deleted to get no conflicts between the two
244             // sets of properties; old files will keep these and adapt accordingly
245             static ::rtl::OUString s_BackColorRGB(RTL_CONSTASCII_USTRINGPARAM("BackColorRGB"));
246             static ::rtl::OUString s_BackTransparent(RTL_CONSTASCII_USTRINGPARAM("BackTransparent"));
247             static ::rtl::OUString s_BackColorTransparency(RTL_CONSTASCII_USTRINGPARAM("BackColorTransparency"));
248             static ::rtl::OUString s_BackGraphicURL(RTL_CONSTASCII_USTRINGPARAM("BackGraphicURL"));
249             static ::rtl::OUString s_BackGraphicFilter(RTL_CONSTASCII_USTRINGPARAM("BackGraphicFilter"));
250             static ::rtl::OUString s_BackGraphicLocation(RTL_CONSTASCII_USTRINGPARAM("BackGraphicLocation"));
251             static ::rtl::OUString s_BackGraphicTransparency(RTL_CONSTASCII_USTRINGPARAM("BackGraphicTransparency"));
252 
253             for(a = rProperties.begin(); a != rProperties.end(); a++)
254             {
255                 if(a->mnIndex != -1)
256                 {
257                     const OUString& rPropName = rMapper->GetEntryAPIName(a->mnIndex);
258 
259                     if(s_BackColorRGB == rPropName
260                         || s_BackTransparent == rPropName
261                         || s_BackColorTransparency == rPropName
262                         || s_BackGraphicURL == rPropName
263                         || s_BackGraphicFilter == rPropName
264                         || s_BackGraphicLocation == rPropName
265                         || s_BackGraphicTransparency== rPropName)
266                     {
267                         // mark entry as inactive
268                         a->mnIndex = -1;
269                     }
270                 }
271             }
272         }
273 
274         m_bIsFillStyleAlreadyConverted = sal_True;
275     }
276 
277 	struct _ContextID_Index_Pair aContextIDs[] =
278 	{
279 		{ CTF_DASHNAME , -1 },
280 		{ CTF_LINESTARTNAME , -1 },
281 		{ CTF_LINEENDNAME , -1 },
282 		{ CTF_FILLGRADIENTNAME, -1 },
283 		{ CTF_FILLTRANSNAME , -1 },
284 		{ CTF_FILLHATCHNAME , -1 },
285 		{ CTF_FILLBITMAPNAME , -1 },
286 		{ CTF_SD_OLE_VIS_AREA_IMPORT_LEFT, -1 },
287 		{ CTF_SD_OLE_VIS_AREA_IMPORT_TOP, -1 },
288 		{ CTF_SD_OLE_VIS_AREA_IMPORT_WIDTH, -1 },
289 		{ CTF_SD_OLE_VIS_AREA_IMPORT_HEIGHT, -1 },
290 		{ -1, -1 }
291 	};
292 	static sal_uInt16 aFamilies[] =
293 	{
294 		XML_STYLE_FAMILY_SD_STROKE_DASH_ID,
295 		XML_STYLE_FAMILY_SD_MARKER_ID,
296 		XML_STYLE_FAMILY_SD_MARKER_ID,
297 		XML_STYLE_FAMILY_SD_GRADIENT_ID,
298 		XML_STYLE_FAMILY_SD_GRADIENT_ID,
299 		XML_STYLE_FAMILY_SD_HATCH_ID,
300 		XML_STYLE_FAMILY_SD_FILL_IMAGE_ID
301 	};
302 
303 	UniReference < SvXMLImportPropertyMapper > xImpPrMap =
304 		GetStyles()->GetImportPropertyMapper( GetFamily() );
305 	DBG_ASSERT( xImpPrMap.is(), "There is the import prop mapper" );
306 	if( xImpPrMap.is() )
307 		xImpPrMap->FillPropertySet( GetProperties(), rPropSet, aContextIDs );
308 
309 	Reference< XPropertySetInfo > xInfo;
310 	// get property set mapper
311 	UniReference<XMLPropertySetMapper> xPropMapper(	xImpPrMap->getPropertySetMapper() );
312 
313 	for( sal_uInt16 i=0; aContextIDs[i].nContextID != -1; i++ )
314 	{
315 		sal_Int32 nIndex = aContextIDs[i].nIndex;
316 		if( nIndex != -1 ) switch( aContextIDs[i].nContextID )
317 		{
318 		case CTF_DASHNAME:
319 		case CTF_LINESTARTNAME:
320 		case CTF_LINEENDNAME:
321 		case CTF_FILLGRADIENTNAME:
322 		case CTF_FILLTRANSNAME:
323 		case CTF_FILLHATCHNAME:
324 		case CTF_FILLBITMAPNAME:
325 		{
326 			struct XMLPropertyState& rState = GetProperties()[nIndex];
327 			OUString sStyleName;
328 			rState.maValue >>= sStyleName;
329 			sStyleName = GetImport().GetStyleDisplayName( aFamilies[i], sStyleName );
330 			try
331 			{
332 
333 				// set property
334 				const OUString& rPropertyName =	xPropMapper->GetEntryAPIName(rState.mnIndex);
335 				if( !xInfo.is() )
336 					xInfo = rPropSet->getPropertySetInfo();
337 				if ( xInfo->hasPropertyByName( rPropertyName ) )
338 				{
339 					rPropSet->setPropertyValue( rPropertyName, Any( sStyleName ) );
340 				}
341 			}
342 			catch ( ::com::sun::star::lang::IllegalArgumentException& e )
343 			{
344 				Sequence<OUString> aSeq(1);
345 				aSeq[0] = sStyleName;
346 				GetImport().SetError(
347 					XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_WARNING,
348 					aSeq, e.Message, NULL );
349 			}
350 			break;
351 		}
352 		case CTF_SD_OLE_VIS_AREA_IMPORT_LEFT:
353 		case CTF_SD_OLE_VIS_AREA_IMPORT_TOP:
354 		case CTF_SD_OLE_VIS_AREA_IMPORT_WIDTH:
355 		case CTF_SD_OLE_VIS_AREA_IMPORT_HEIGHT:
356 		{
357 			struct XMLPropertyState& rState = GetProperties()[nIndex];
358 			const OUString& rPropertyName =	xPropMapper->GetEntryAPIName(rState.mnIndex);
359 			try
360 			{
361 				if( !xInfo.is() )
362 					xInfo = rPropSet->getPropertySetInfo();
363 				if ( xInfo->hasPropertyByName( rPropertyName ) )
364 				{
365 					rPropSet->setPropertyValue( rPropertyName, rState.maValue );
366 				}
367 			}
368 			catch ( ::com::sun::star::lang::IllegalArgumentException& e )
369 			{
370 				Sequence<OUString> aSeq;
371 				GetImport().SetError(
372 					XMLERROR_STYLE_PROP_VALUE | XMLERROR_FLAG_WARNING,
373 					aSeq, e.Message, NULL );
374 			}
375 			break;
376 		}
377 		}
378 	}
379 
380 	if (m_sControlDataStyleName.getLength())
381 	{	// we had a data-style-name attribute
382 
383 		// set the formatting on the control model of the control shape
384 		uno::Reference< drawing::XControlShape > xControlShape(rPropSet, uno::UNO_QUERY);
385 		DBG_ASSERT(xControlShape.is(), "XMLShapeStyleContext::FillPropertySet: data style for a non-control shape!");
386 		if (xControlShape.is())
387 		{
388 			uno::Reference< beans::XPropertySet > xControlModel(xControlShape->getControl(), uno::UNO_QUERY);
389 			DBG_ASSERT(xControlModel.is(), "XMLShapeStyleContext::FillPropertySet: no control model for the shape!");
390 			if (xControlModel.is())
391 			{
392 				GetImport().GetFormImport()->applyControlNumberStyle(xControlModel, m_sControlDataStyleName);
393 			}
394 		}
395 	}
396 }
397 
398 void XMLShapeStyleContext::Finish( sal_Bool /*bOverwrite*/ )
399 {
400 }
401 
402