1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/debug.hxx>
21 #include <sal/log.hxx>
22 #include <xmloff/XMLShapeStyleContext.hxx>
23 #include <XMLShapePropertySetContext.hxx>
24 #include <xmloff/contextid.hxx>
25 #include <com/sun/star/drawing/XControlShape.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/beans/XPropertySetInfo.hpp>
28 #include <com/sun/star/lang/IllegalArgumentException.hpp>
29 #include <com/sun/star/container/XIndexReplace.hpp>
30 #include <xmloff/xmlimp.hxx>
31 #include <xmloff/xmlnumi.hxx>
32 #include <xmloff/xmlnamespace.hxx>
33 #include <xmloff/xmlprmap.hxx>
34 #include <xmloff/xmltoken.hxx>
35 #include <xmloff/xmlerror.hxx>
36 #include <xmloff/maptype.hxx>
37 #include <xmloff/xmlimppr.hxx>
39 #include <xmlsdtypes.hxx>
41 using namespace ::com::sun::star
;
42 using namespace ::com::sun::star::uno
;
43 using namespace ::com::sun::star::beans
;
44 using namespace ::com::sun::star::drawing
;
45 using ::xmloff::token::IsXMLToken
;
46 using ::xmloff::token::XML_TEXT_PROPERTIES
;
47 using ::xmloff::token::XML_GRAPHIC_PROPERTIES
;
48 using ::xmloff::token::XML_PARAGRAPH_PROPERTIES
;
51 XMLShapeStyleContext::XMLShapeStyleContext(
53 SvXMLStylesContext
& rStyles
,
54 XmlStyleFamily nFamily
)
55 : XMLPropStyleContext(rImport
, rStyles
, nFamily
),
56 m_bIsNumRuleAlreadyConverted( false )
60 XMLShapeStyleContext::~XMLShapeStyleContext()
64 void XMLShapeStyleContext::SetAttribute( sal_uInt16 nPrefixKey
, const OUString
& rLocalName
, const OUString
& rValue
)
66 if (m_sControlDataStyleName
.isEmpty() && (::xmloff::token::GetXMLToken(::xmloff::token::XML_DATA_STYLE_NAME
) == rLocalName
))
68 m_sControlDataStyleName
= rValue
;
70 else if( (XML_NAMESPACE_STYLE
== nPrefixKey
) && IsXMLToken( rLocalName
, ::xmloff::token::XML_LIST_STYLE_NAME
) )
72 m_sListStyleName
= rValue
;
76 XMLPropStyleContext::SetAttribute( nPrefixKey
, rLocalName
, rValue
);
78 if( (XML_NAMESPACE_STYLE
== nPrefixKey
) &&
79 ( IsXMLToken( rLocalName
, ::xmloff::token::XML_NAME
) || IsXMLToken( rLocalName
, ::xmloff::token::XML_DISPLAY_NAME
) ) )
81 if( !GetName().isEmpty() && !GetDisplayName().isEmpty() && GetName() != GetDisplayName() )
84 AddStyleDisplayName( GetFamily(), GetName(), GetDisplayName() );
90 css::uno::Reference
< css::xml::sax::XFastContextHandler
> XMLShapeStyleContext::createFastChildContext(
92 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
94 SvXMLImportContextRef xContext
;
96 if( IsTokenInNamespace(nElement
, XML_NAMESPACE_STYLE
) ||
97 IsTokenInNamespace(nElement
, XML_NAMESPACE_LO_EXT
) )
99 sal_Int32 nLocalName
= nElement
& TOKEN_MASK
;
100 sal_uInt32 nFamily
= 0;
101 if( nLocalName
== XML_TEXT_PROPERTIES
)
102 nFamily
= XML_TYPE_PROP_TEXT
;
103 else if( nLocalName
== XML_PARAGRAPH_PROPERTIES
)
104 nFamily
= XML_TYPE_PROP_PARAGRAPH
;
105 else if( nLocalName
== XML_GRAPHIC_PROPERTIES
)
106 nFamily
= XML_TYPE_PROP_GRAPHIC
;
109 rtl::Reference
< SvXMLImportPropertyMapper
> xImpPrMap
=
110 GetStyles()->GetImportPropertyMapper( GetFamily() );
112 return new XMLShapePropertySetContext( GetImport(), nElement
, xAttrList
,
119 return XMLPropStyleContext::createFastChildContext( nElement
, xAttrList
);
122 void XMLShapeStyleContext::FillPropertySet( const Reference
< beans::XPropertySet
> & rPropSet
)
124 if( !m_bIsNumRuleAlreadyConverted
)
126 m_bIsNumRuleAlreadyConverted
= true;
128 // for compatibility to beta files, search for CTF_SD_NUMBERINGRULES_NAME to
129 // import numbering rules from the style:properties element
130 const rtl::Reference
< XMLPropertySetMapper
>&rMapper
= GetStyles()->GetImportPropertyMapper( GetFamily() )->getPropertySetMapper();
132 ::std::vector
< XMLPropertyState
> &rProperties
= GetProperties();
133 ::std::vector
< XMLPropertyState
>::iterator
end( rProperties
.end() );
135 // first, look for the old format, where we had a text:list-style-name
136 // attribute in the style:properties element
137 auto property
= std::find_if(rProperties
.begin(), end
, [&rMapper
](XMLPropertyState
& rProp
) {
138 // find properties with context
139 return (rProp
.mnIndex
!= -1) && (rMapper
->GetEntryContextId( rProp
.mnIndex
) == CTF_SD_NUMBERINGRULES_NAME
); });
141 // if we did not find an old list-style-name in the properties, and we need one
142 // because we got a style:list-style attribute in the style-style element
144 if( (property
== end
) && ( !m_sListStyleName
.isEmpty() ) )
146 sal_Int32 nIndex
= rMapper
->FindEntryIndex( CTF_SD_NUMBERINGRULES_NAME
);
147 SAL_WARN_IF( -1 == nIndex
, "xmloff", "can't find numbering rules property entry, can't set numbering rule!" );
149 XMLPropertyState
aNewState( nIndex
);
150 rProperties
.push_back( aNewState
);
151 end
= rProperties
.end();
155 // so, if we have an old or a new list style name, we set its value to
157 if( property
!= end
)
159 if( m_sListStyleName
.isEmpty() )
161 property
->maValue
>>= m_sListStyleName
;
164 const SvxXMLListStyleContext
*pListStyle
= GetImport().GetTextImport()->FindAutoListStyle( m_sListStyleName
);
166 SAL_WARN_IF( !pListStyle
, "xmloff", "list-style not found for shape style" );
169 uno::Reference
< container::XIndexReplace
> xNumRule( SvxXMLListStyleContext::CreateNumRule( GetImport().GetModel() ) );
170 pListStyle
->FillUnoNumRule(xNumRule
);
171 property
->maValue
<<= xNumRule
;
175 property
->mnIndex
= -1;
180 struct ContextID_Index_Pair aContextIDs
[] =
182 { CTF_DASHNAME
, -1 },
183 { CTF_LINESTARTNAME
, -1 },
184 { CTF_LINEENDNAME
, -1 },
185 { CTF_FILLGRADIENTNAME
, -1 },
186 { CTF_FILLTRANSNAME
, -1 },
187 { CTF_FILLHATCHNAME
, -1 },
188 { CTF_FILLBITMAPNAME
, -1 },
189 { CTF_SD_OLE_VIS_AREA_IMPORT_LEFT
, -1 },
190 { CTF_SD_OLE_VIS_AREA_IMPORT_TOP
, -1 },
191 { CTF_SD_OLE_VIS_AREA_IMPORT_WIDTH
, -1 },
192 { CTF_SD_OLE_VIS_AREA_IMPORT_HEIGHT
, -1 },
195 static const XmlStyleFamily aFamilies
[] =
197 XmlStyleFamily::SD_STROKE_DASH_ID
,
198 XmlStyleFamily::SD_MARKER_ID
,
199 XmlStyleFamily::SD_MARKER_ID
,
200 XmlStyleFamily::SD_GRADIENT_ID
,
201 XmlStyleFamily::SD_GRADIENT_ID
,
202 XmlStyleFamily::SD_HATCH_ID
,
203 XmlStyleFamily::SD_FILL_IMAGE_ID
206 rtl::Reference
< SvXMLImportPropertyMapper
> xImpPrMap
=
207 GetStyles()->GetImportPropertyMapper( GetFamily() );
208 SAL_WARN_IF( !xImpPrMap
.is(), "xmloff", "There is the import prop mapper" );
210 xImpPrMap
->FillPropertySet( GetProperties(), rPropSet
, aContextIDs
);
212 Reference
< XPropertySetInfo
> xInfo
;
213 // get property set mapper
214 rtl::Reference
<XMLPropertySetMapper
> xPropMapper( xImpPrMap
->getPropertySetMapper() );
216 for( sal_uInt16 i
=0; aContextIDs
[i
].nContextID
!= -1; i
++ )
218 sal_Int32 nIndex
= aContextIDs
[i
].nIndex
;
219 if( nIndex
!= -1 ) switch( aContextIDs
[i
].nContextID
)
222 case CTF_LINESTARTNAME
:
223 case CTF_LINEENDNAME
:
224 case CTF_FILLGRADIENTNAME
:
225 case CTF_FILLTRANSNAME
:
226 case CTF_FILLHATCHNAME
:
227 case CTF_FILLBITMAPNAME
:
229 struct XMLPropertyState
& rState
= GetProperties()[nIndex
];
231 rState
.maValue
>>= sStyleName
;
232 sStyleName
= GetImport().GetStyleDisplayName( aFamilies
[i
], sStyleName
);
233 // All of these attributes refer to something with draw:name
234 // of type styleName = NCName which is non-empty.
235 // tdf#89802: for Writer frames there would be no exception here but
236 // it will fail later on attach() and take out the entire frame
237 if (sStyleName
.isEmpty() &&
238 ( CTF_FILLGRADIENTNAME
== aContextIDs
[i
].nContextID
239 || CTF_FILLTRANSNAME
== aContextIDs
[i
].nContextID
240 || CTF_FILLHATCHNAME
== aContextIDs
[i
].nContextID
241 || CTF_FILLBITMAPNAME
== aContextIDs
[i
].nContextID
))
243 Sequence
<OUString
> const seq
{ sStyleName
};
244 GetImport().SetError(
245 XMLERROR_STYLE_PROP_VALUE
| XMLERROR_FLAG_WARNING
,
246 seq
, "empty style name reference", nullptr );
254 const OUString
& rPropertyName
= xPropMapper
->GetEntryAPIName(rState
.mnIndex
);
256 xInfo
= rPropSet
->getPropertySetInfo();
257 if ( xInfo
->hasPropertyByName( rPropertyName
) )
259 rPropSet
->setPropertyValue( rPropertyName
, Any( sStyleName
) );
262 catch ( const css::lang::IllegalArgumentException
& e
)
264 Sequence
<OUString
> aSeq
{ sStyleName
};
265 GetImport().SetError(
266 XMLERROR_STYLE_PROP_VALUE
| XMLERROR_FLAG_WARNING
,
267 aSeq
, e
.Message
, nullptr );
271 case CTF_SD_OLE_VIS_AREA_IMPORT_LEFT
:
272 case CTF_SD_OLE_VIS_AREA_IMPORT_TOP
:
273 case CTF_SD_OLE_VIS_AREA_IMPORT_WIDTH
:
274 case CTF_SD_OLE_VIS_AREA_IMPORT_HEIGHT
:
276 struct XMLPropertyState
& rState
= GetProperties()[nIndex
];
277 const OUString
& rPropertyName
= xPropMapper
->GetEntryAPIName(rState
.mnIndex
);
281 xInfo
= rPropSet
->getPropertySetInfo();
282 if ( xInfo
->hasPropertyByName( rPropertyName
) )
284 rPropSet
->setPropertyValue( rPropertyName
, rState
.maValue
);
287 catch ( const css::lang::IllegalArgumentException
& e
)
289 Sequence
<OUString
> aSeq
;
290 GetImport().SetError(
291 XMLERROR_STYLE_PROP_VALUE
| XMLERROR_FLAG_WARNING
,
292 aSeq
, e
.Message
, nullptr );
299 if (m_sControlDataStyleName
.isEmpty())
302 // we had a data-style-name attribute
304 // set the formatting on the control model of the control shape
305 uno::Reference
< drawing::XControlShape
> xControlShape(rPropSet
, uno::UNO_QUERY
);
306 DBG_ASSERT(xControlShape
.is(), "XMLShapeStyleContext::FillPropertySet: data style for a non-control shape!");
307 if (xControlShape
.is())
309 uno::Reference
< beans::XPropertySet
> xControlModel(xControlShape
->getControl(), uno::UNO_QUERY
);
310 DBG_ASSERT(xControlModel
.is(), "XMLShapeStyleContext::FillPropertySet: no control model for the shape!");
311 if (xControlModel
.is())
313 GetImport().GetFormImport()->applyControlNumberStyle(xControlModel
, m_sControlDataStyleName
);
318 void XMLShapeStyleContext::Finish( bool /*bOverwrite*/ )
322 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */