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/FillStyle.hpp>
26 #include <com/sun/star/drawing/XControlShape.hpp>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/beans/XPropertySetInfo.hpp>
29 #include <com/sun/star/lang/IllegalArgumentException.hpp>
30 #include <com/sun/star/container/XIndexReplace.hpp>
31 #include <xmloff/xmlimp.hxx>
32 #include <xmloff/xmlnumi.hxx>
33 #include <xmloff/xmlnamespace.hxx>
34 #include <xmloff/xmlprmap.hxx>
35 #include <xmloff/xmltoken.hxx>
36 #include <xmloff/xmlerror.hxx>
37 #include <xmloff/maptype.hxx>
38 #include <xmloff/xmlimppr.hxx>
40 #include <xmlsdtypes.hxx>
42 using namespace ::com::sun::star
;
43 using namespace ::com::sun::star::uno
;
44 using namespace ::com::sun::star::beans
;
45 using namespace ::com::sun::star::drawing
;
46 using namespace ::xmloff::token
;
49 XMLShapeStyleContext::XMLShapeStyleContext(
51 SvXMLStylesContext
& rStyles
,
52 XmlStyleFamily nFamily
)
53 : XMLPropStyleContext(rImport
, rStyles
, nFamily
),
54 m_bIsNumRuleAlreadyConverted( false )
58 XMLShapeStyleContext::~XMLShapeStyleContext()
62 void XMLShapeStyleContext::SetAttribute( sal_Int32 nElement
, const OUString
& rValue
)
64 if (m_sControlDataStyleName
.isEmpty() && (nElement
& TOKEN_MASK
) == XML_DATA_STYLE_NAME
)
66 m_sControlDataStyleName
= rValue
;
68 else if( nElement
== XML_ELEMENT(STYLE
, XML_LIST_STYLE_NAME
) )
70 m_sListStyleName
= rValue
;
74 XMLPropStyleContext::SetAttribute( nElement
, rValue
);
76 if( nElement
== XML_ELEMENT(STYLE
, XML_NAME
) || nElement
== XML_ELEMENT(STYLE
, XML_DISPLAY_NAME
) )
78 if( !GetName().isEmpty() && !GetDisplayName().isEmpty() && GetName() != GetDisplayName() )
81 AddStyleDisplayName( GetFamily(), GetName(), GetDisplayName() );
87 css::uno::Reference
< css::xml::sax::XFastContextHandler
> XMLShapeStyleContext::createFastChildContext(
89 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
91 if( IsTokenInNamespace(nElement
, XML_NAMESPACE_STYLE
) ||
92 IsTokenInNamespace(nElement
, XML_NAMESPACE_LO_EXT
) )
94 sal_Int32 nLocalName
= nElement
& TOKEN_MASK
;
95 sal_uInt32 nFamily
= 0;
96 if( nLocalName
== XML_TEXT_PROPERTIES
)
97 nFamily
= XML_TYPE_PROP_TEXT
;
98 else if( nLocalName
== XML_PARAGRAPH_PROPERTIES
)
99 nFamily
= XML_TYPE_PROP_PARAGRAPH
;
100 else if( nLocalName
== XML_GRAPHIC_PROPERTIES
)
101 nFamily
= XML_TYPE_PROP_GRAPHIC
;
104 rtl::Reference
< SvXMLImportPropertyMapper
> xImpPrMap
=
105 GetStyles()->GetImportPropertyMapper( GetFamily() );
107 return new XMLShapePropertySetContext( GetImport(), nElement
, xAttrList
,
114 return XMLPropStyleContext::createFastChildContext( nElement
, xAttrList
);
117 void XMLShapeStyleContext::FillPropertySet( const Reference
< beans::XPropertySet
> & rPropSet
)
119 if( !m_bIsNumRuleAlreadyConverted
)
121 m_bIsNumRuleAlreadyConverted
= true;
123 // for compatibility to beta files, search for CTF_SD_NUMBERINGRULES_NAME to
124 // import numbering rules from the style:properties element
125 const rtl::Reference
< XMLPropertySetMapper
>&rMapper
= GetStyles()->GetImportPropertyMapper( GetFamily() )->getPropertySetMapper();
127 ::std::vector
< XMLPropertyState
> &rProperties
= GetProperties();
128 ::std::vector
< XMLPropertyState
>::iterator
end( rProperties
.end() );
130 // first, look for the old format, where we had a text:list-style-name
131 // attribute in the style:properties element
132 auto property
= std::find_if(rProperties
.begin(), end
, [&rMapper
](XMLPropertyState
& rProp
) {
133 // find properties with context
134 return (rProp
.mnIndex
!= -1) && (rMapper
->GetEntryContextId( rProp
.mnIndex
) == CTF_SD_NUMBERINGRULES_NAME
); });
136 // if we did not find an old list-style-name in the properties, and we need one
137 // because we got a style:list-style attribute in the style-style element
139 if( (property
== end
) && ( !m_sListStyleName
.isEmpty() ) )
141 sal_Int32 nIndex
= rMapper
->FindEntryIndex( CTF_SD_NUMBERINGRULES_NAME
);
142 SAL_WARN_IF( -1 == nIndex
, "xmloff", "can't find numbering rules property entry, can't set numbering rule!" );
144 XMLPropertyState
aNewState( nIndex
);
145 rProperties
.push_back( aNewState
);
146 end
= rProperties
.end();
150 // so, if we have an old or a new list style name, we set its value to
152 if( property
!= end
)
154 if( m_sListStyleName
.isEmpty() )
156 property
->maValue
>>= m_sListStyleName
;
159 const SvxXMLListStyleContext
*pListStyle
= GetImport().GetTextImport()->FindAutoListStyle( m_sListStyleName
);
161 SAL_WARN_IF( !pListStyle
, "xmloff", "list-style not found for shape style" );
164 uno::Reference
< container::XIndexReplace
> xNumRule( SvxXMLListStyleContext::CreateNumRule( GetImport().GetModel() ) );
165 pListStyle
->FillUnoNumRule(xNumRule
);
166 property
->maValue
<<= xNumRule
;
170 property
->mnIndex
= -1;
175 struct ContextID_Index_Pair aContextIDs
[] =
177 { CTF_DASHNAME
, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE
},
178 { CTF_LINESTARTNAME
, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE
},
179 { CTF_LINEENDNAME
, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE
},
180 { CTF_FILLGRADIENTNAME
, -1, drawing::FillStyle::FillStyle_GRADIENT
},
181 { CTF_FILLTRANSNAME
, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE
},
182 { CTF_FILLHATCHNAME
, -1, drawing::FillStyle::FillStyle_HATCH
},
183 { CTF_FILLBITMAPNAME
, -1, drawing::FillStyle::FillStyle_BITMAP
},
184 { CTF_SD_OLE_VIS_AREA_IMPORT_LEFT
, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE
},
185 { CTF_SD_OLE_VIS_AREA_IMPORT_TOP
, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE
},
186 { CTF_SD_OLE_VIS_AREA_IMPORT_WIDTH
, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE
},
187 { CTF_SD_OLE_VIS_AREA_IMPORT_HEIGHT
, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE
},
188 { -1, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE
}
190 static const XmlStyleFamily aFamilies
[] =
192 XmlStyleFamily::SD_STROKE_DASH_ID
,
193 XmlStyleFamily::SD_MARKER_ID
,
194 XmlStyleFamily::SD_MARKER_ID
,
195 XmlStyleFamily::SD_GRADIENT_ID
,
196 XmlStyleFamily::SD_GRADIENT_ID
,
197 XmlStyleFamily::SD_HATCH_ID
,
198 XmlStyleFamily::SD_FILL_IMAGE_ID
201 rtl::Reference
< SvXMLImportPropertyMapper
> xImpPrMap
=
202 GetStyles()->GetImportPropertyMapper( GetFamily() );
203 SAL_WARN_IF( !xImpPrMap
.is(), "xmloff", "There is the import prop mapper" );
205 xImpPrMap
->FillPropertySet( GetProperties(), rPropSet
, aContextIDs
);
207 Reference
< XPropertySetInfo
> xInfo
;
208 // get property set mapper
209 rtl::Reference
<XMLPropertySetMapper
> xPropMapper( xImpPrMap
->getPropertySetMapper() );
211 for( sal_uInt16 i
=0; aContextIDs
[i
].nContextID
!= -1; i
++ )
213 sal_Int32 nIndex
= aContextIDs
[i
].nIndex
;
214 if( nIndex
!= -1 ) switch( aContextIDs
[i
].nContextID
)
217 case CTF_LINESTARTNAME
:
218 case CTF_LINEENDNAME
:
219 case CTF_FILLGRADIENTNAME
:
220 case CTF_FILLTRANSNAME
:
221 case CTF_FILLHATCHNAME
:
222 case CTF_FILLBITMAPNAME
:
224 struct XMLPropertyState
& rState
= GetProperties()[nIndex
];
226 rState
.maValue
>>= sStyleName
;
227 sStyleName
= GetImport().GetStyleDisplayName( aFamilies
[i
], sStyleName
);
228 // All of these attributes refer to something with draw:name
229 // of type styleName = NCName which is non-empty.
230 // tdf#89802: for Writer frames there would be no exception here but
231 // it will fail later on attach() and take out the entire frame
232 if (sStyleName
.isEmpty() &&
233 ( CTF_FILLGRADIENTNAME
== aContextIDs
[i
].nContextID
234 || CTF_FILLTRANSNAME
== aContextIDs
[i
].nContextID
235 || CTF_FILLHATCHNAME
== aContextIDs
[i
].nContextID
236 || CTF_FILLBITMAPNAME
== aContextIDs
[i
].nContextID
))
238 Sequence
<OUString
> const seq
{ sStyleName
};
239 GetImport().SetError(
240 XMLERROR_STYLE_PROP_VALUE
| XMLERROR_FLAG_WARNING
,
241 seq
, "empty style name reference", nullptr );
245 if (::xmloff::IsIgnoreFillStyleNamedItem(rPropSet
, aContextIDs
[i
].nExpectedFillStyle
))
247 SAL_INFO("xmloff.style", "ShapeStyleContext: dropping fill named item: " << sStyleName
);
248 break; // ignore it, it's not used
255 const OUString
& rPropertyName
= xPropMapper
->GetEntryAPIName(rState
.mnIndex
);
257 xInfo
= rPropSet
->getPropertySetInfo();
258 if ( xInfo
->hasPropertyByName( rPropertyName
) )
260 rPropSet
->setPropertyValue( rPropertyName
, Any( sStyleName
) );
263 catch ( const css::lang::IllegalArgumentException
& e
)
265 Sequence
<OUString
> aSeq
{ sStyleName
};
266 GetImport().SetError(
267 XMLERROR_STYLE_PROP_VALUE
| XMLERROR_FLAG_WARNING
,
268 aSeq
, e
.Message
, nullptr );
272 case CTF_SD_OLE_VIS_AREA_IMPORT_LEFT
:
273 case CTF_SD_OLE_VIS_AREA_IMPORT_TOP
:
274 case CTF_SD_OLE_VIS_AREA_IMPORT_WIDTH
:
275 case CTF_SD_OLE_VIS_AREA_IMPORT_HEIGHT
:
277 struct XMLPropertyState
& rState
= GetProperties()[nIndex
];
278 const OUString
& rPropertyName
= xPropMapper
->GetEntryAPIName(rState
.mnIndex
);
282 xInfo
= rPropSet
->getPropertySetInfo();
283 if ( xInfo
->hasPropertyByName( rPropertyName
) )
285 rPropSet
->setPropertyValue( rPropertyName
, rState
.maValue
);
288 catch ( const css::lang::IllegalArgumentException
& e
)
290 Sequence
<OUString
> aSeq
;
291 GetImport().SetError(
292 XMLERROR_STYLE_PROP_VALUE
| XMLERROR_FLAG_WARNING
,
293 aSeq
, e
.Message
, nullptr );
300 if (m_sControlDataStyleName
.isEmpty())
303 // we had a data-style-name attribute
305 // set the formatting on the control model of the control shape
306 uno::Reference
< drawing::XControlShape
> xControlShape(rPropSet
, uno::UNO_QUERY
);
307 DBG_ASSERT(xControlShape
.is(), "XMLShapeStyleContext::FillPropertySet: data style for a non-control shape!");
308 if (xControlShape
.is())
310 uno::Reference
< beans::XPropertySet
> xControlModel(xControlShape
->getControl(), uno::UNO_QUERY
);
311 DBG_ASSERT(xControlModel
.is(), "XMLShapeStyleContext::FillPropertySet: no control model for the shape!");
312 if (xControlModel
.is())
314 GetImport().GetFormImport()->applyControlNumberStyle(xControlModel
, m_sControlDataStyleName
);
319 void XMLShapeStyleContext::Finish( bool /*bOverwrite*/ )
323 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */