xref: /trunk/main/xmloff/source/draw/XMLShapeStyleContext.cxx (revision 07a3d7f126518b23ae382088cf657ec498e294b1)
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