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 <sal/config.h>
22 #include <com/sun/star/frame/XModel.hpp>
23 #include <com/sun/star/text/XTextColumns.hpp>
24 #include <com/sun/star/text/TextColumn.hpp>
25 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
26 #include <com/sun/star/style/VerticalAlignment.hpp>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <sal/log.hxx>
29 #include <sax/tools/converter.hxx>
30 #include <xmloff/xmluconv.hxx>
31 #include <xmloff/xmlnamespace.hxx>
32 #include <xmloff/xmlimp.hxx>
33 #include <xmloff/xmltoken.hxx>
34 #include <xmloff/xmlement.hxx>
35 #include <XMLTextColumnsContext.hxx>
37 using namespace ::com::sun::star
;
38 using namespace ::com::sun::star::uno
;
39 using namespace ::com::sun::star::lang
;
40 using namespace ::com::sun::star::text
;
41 using namespace ::com::sun::star::style
;
42 using namespace ::com::sun::star::beans
;
43 using namespace ::xmloff::token
;
45 SvXMLEnumMapEntry
<sal_Int8
> const pXML_Sep_Style_Enum
[] =
51 { XML_TOKEN_INVALID
, 0 }
54 SvXMLEnumMapEntry
<VerticalAlignment
> const pXML_Sep_Align_Enum
[] =
56 { XML_TOP
, VerticalAlignment_TOP
},
57 { XML_MIDDLE
, VerticalAlignment_MIDDLE
},
58 { XML_BOTTOM
, VerticalAlignment_BOTTOM
},
59 { XML_TOKEN_INVALID
, VerticalAlignment(0) }
62 class XMLTextColumnContext_Impl
: public SvXMLImportContext
64 text::TextColumn aColumn
;
68 XMLTextColumnContext_Impl( SvXMLImport
& rImport
, sal_Int32 nElement
,
70 xml::sax::XFastAttributeList
> & xAttrList
);
72 text::TextColumn
& getTextColumn() { return aColumn
; }
76 XMLTextColumnContext_Impl::XMLTextColumnContext_Impl(
77 SvXMLImport
& rImport
, sal_Int32
/*nElement*/,
79 xml::sax::XFastAttributeList
> & xAttrList
) :
80 SvXMLImportContext( rImport
)
83 aColumn
.LeftMargin
= 0;
84 aColumn
.RightMargin
= 0;
86 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
89 switch( aIter
.getToken() )
91 case XML_ELEMENT(STYLE
, XML_REL_WIDTH
):
93 size_t nPos
= aIter
.toView().find( '*' );
94 if( nPos
!= std::string_view::npos
&& static_cast<sal_Int32
>(nPos
+1) == aIter
.getLength() )
96 if (::sax::Converter::convertNumber(
98 aIter
.toView().substr(0, nPos
),
100 aColumn
.Width
= nVal
;
104 case XML_ELEMENT(FO
, XML_START_INDENT
):
105 case XML_ELEMENT(FO_COMPAT
, XML_START_INDENT
):
106 if( GetImport().GetMM100UnitConverter().
107 convertMeasureToCore( nVal
, aIter
.toView() ) )
108 aColumn
.LeftMargin
= nVal
;
110 case XML_ELEMENT(FO
, XML_END_INDENT
):
111 case XML_ELEMENT(FO_COMPAT
, XML_END_INDENT
):
112 if( GetImport().GetMM100UnitConverter().
113 convertMeasureToCore( nVal
, aIter
.toView() ) )
114 aColumn
.RightMargin
= nVal
;
117 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
123 class XMLTextColumnSepContext_Impl
: public SvXMLImportContext
129 VerticalAlignment eVertAlign
;
133 XMLTextColumnSepContext_Impl( SvXMLImport
& rImport
, sal_Int32 nElement
,
134 const uno::Reference
<
135 xml::sax::XFastAttributeList
> & xAttrList
);
137 sal_Int32
GetWidth() const { return nWidth
; }
138 sal_Int32
GetColor() const { return nColor
; }
139 sal_Int8
GetHeight() const { return nHeight
; }
140 sal_Int8
GetStyle() const { return nStyle
; }
141 VerticalAlignment
GetVertAlign() const { return eVertAlign
; }
145 XMLTextColumnSepContext_Impl::XMLTextColumnSepContext_Impl(
146 SvXMLImport
& rImport
, sal_Int32
/*nElement*/,
147 const uno::Reference
<
148 xml::sax::XFastAttributeList
> & xAttrList
) :
149 SvXMLImportContext( rImport
),
154 eVertAlign( VerticalAlignment_TOP
)
156 for (auto &aIter
: sax_fastparser::castToFastAttributeList( xAttrList
))
159 switch( aIter
.getToken() )
161 case XML_ELEMENT(STYLE
, XML_WIDTH
):
162 if( GetImport().GetMM100UnitConverter().
163 convertMeasureToCore( nVal
, aIter
.toView() ) )
166 case XML_ELEMENT(STYLE
, XML_HEIGHT
):
167 if (::sax::Converter::convertPercent( nVal
, aIter
.toView() ) &&
168 nVal
>=1 && nVal
<= 100 )
169 nHeight
= static_cast<sal_Int8
>(nVal
);
171 case XML_ELEMENT(STYLE
, XML_COLOR
):
172 ::sax::Converter::convertColor( nColor
, aIter
.toView() );
174 case XML_ELEMENT(STYLE
, XML_VERTICAL_ALIGN
):
175 SvXMLUnitConverter::convertEnum( eVertAlign
, aIter
.toView(),
176 pXML_Sep_Align_Enum
);
178 case XML_ELEMENT(STYLE
, XML_STYLE
):
179 SvXMLUnitConverter::convertEnum( nStyle
, aIter
.toView(),
180 pXML_Sep_Style_Enum
);
183 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
188 constexpr OUStringLiteral
gsSeparatorLineIsOn(u
"SeparatorLineIsOn");
189 constexpr OUStringLiteral
gsSeparatorLineWidth(u
"SeparatorLineWidth");
190 constexpr OUStringLiteral
gsSeparatorLineColor(u
"SeparatorLineColor");
191 constexpr OUStringLiteral
gsSeparatorLineRelativeHeight(u
"SeparatorLineRelativeHeight");
192 constexpr OUStringLiteral
gsSeparatorLineVerticalAlignment(u
"SeparatorLineVerticalAlignment");
193 constexpr OUStringLiteral
gsAutomaticDistance(u
"AutomaticDistance");
194 constexpr OUStringLiteral
gsSeparatorLineStyle(u
"SeparatorLineStyle");
196 XMLTextColumnsContext::XMLTextColumnsContext(
197 SvXMLImport
& rImport
, sal_Int32 nElement
,
198 const Reference
< xml::sax::XFastAttributeList
>& xAttrList
,
199 const XMLPropertyState
& rProp
,
200 ::std::vector
< XMLPropertyState
> &rProps
)
201 : XMLElementPropertyContext( rImport
, nElement
, rProp
, rProps
)
203 , bAutomatic( false )
204 , nAutomaticDistance( 0 )
207 for (auto &aIter
: sax_fastparser::castToFastAttributeList(xAttrList
))
209 switch(aIter
.getToken())
211 case XML_ELEMENT(FO
, XML_COLUMN_COUNT
):
212 case XML_ELEMENT(FO_COMPAT
, XML_COLUMN_COUNT
):
213 if(::sax::Converter::convertNumber( nVal
, aIter
.toView(), 0, SHRT_MAX
))
214 nCount
= static_cast<sal_Int16
>(nVal
);
216 case XML_ELEMENT(FO
, XML_COLUMN_GAP
):
217 case XML_ELEMENT(FO_COMPAT
, XML_COLUMN_GAP
):
219 bAutomatic
= GetImport().GetMM100UnitConverter().
220 convertMeasureToCore( nAutomaticDistance
, aIter
.toView() );
224 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
229 css::uno::Reference
< css::xml::sax::XFastContextHandler
> XMLTextColumnsContext::createFastChildContext(
231 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
233 if( nElement
== XML_ELEMENT(STYLE
, XML_COLUMN
) )
235 const rtl::Reference
<XMLTextColumnContext_Impl
> xColumn
{
236 new XMLTextColumnContext_Impl( GetImport(), nElement
, xAttrList
)};
238 // add new tabstop to array of tabstops
239 maColumns
.push_back( xColumn
);
243 else if( nElement
== XML_ELEMENT(STYLE
, XML_COLUMN_SEP
) )
246 new XMLTextColumnSepContext_Impl( GetImport(), nElement
, xAttrList
));
250 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement
);
254 void XMLTextColumnsContext::endFastElement(sal_Int32 nElement
)
256 Reference
<XMultiServiceFactory
> xFactory(GetImport().GetModel(),UNO_QUERY
);
260 Reference
<XInterface
> xIfc
= xFactory
->createInstance(u
"com.sun.star.text.TextColumns"_ustr
);
264 Reference
< XTextColumns
> xColumns( xIfc
, UNO_QUERY
);
267 // zero columns = no columns -> 1 column
268 xColumns
->setColumnCount( 1 );
270 else if( !bAutomatic
&&
271 maColumns
.size() == static_cast<sal_uInt16
>(nCount
) )
273 // if we have column descriptions, one per column, and we don't use
274 // automatic width, then set the column widths
276 sal_Int32 nRelWidth
= 0;
277 sal_uInt16 nColumnsWithWidth
= 0;
280 for( i
= 0; i
< nCount
; i
++ )
282 const TextColumn
& rColumn
=
283 maColumns
[static_cast<sal_uInt16
>(i
)]->getTextColumn();
284 if( rColumn
.Width
> 0 )
286 nRelWidth
+= rColumn
.Width
;
290 if( nColumnsWithWidth
< nCount
)
292 sal_Int32 nColWidth
= 0==nRelWidth
294 : nRelWidth
/ nColumnsWithWidth
;
296 for( i
=0; i
< nCount
; i
++ )
298 TextColumn
& rColumn
=
299 maColumns
[static_cast<sal_uInt16
>(i
)]->getTextColumn();
300 if( rColumn
.Width
== 0 )
302 rColumn
.Width
= nColWidth
;
303 nRelWidth
+= rColumn
.Width
;
304 if( 0 == --nColumnsWithWidth
)
310 Sequence
< TextColumn
> aColumns( static_cast<sal_Int32
>(nCount
) );
311 TextColumn
*pTextColumns
= aColumns
.getArray();
312 for( i
=0; i
< nCount
; i
++ )
313 *pTextColumns
++ = maColumns
[static_cast<sal_uInt16
>(i
)]->getTextColumn();
315 xColumns
->setColumns( aColumns
);
319 // only set column count (and let the columns be distributed
322 xColumns
->setColumnCount( nCount
);
325 Reference
< XPropertySet
> xPropSet( xColumns
, UNO_QUERY
);
328 bool bOn
= mxColumnSep
!= nullptr;
330 xPropSet
->setPropertyValue( gsSeparatorLineIsOn
, Any(bOn
) );
332 if( mxColumnSep
.is() )
334 if( mxColumnSep
->GetWidth() )
336 xPropSet
->setPropertyValue( gsSeparatorLineWidth
, Any(mxColumnSep
->GetWidth()) );
338 if( mxColumnSep
->GetHeight() )
340 xPropSet
->setPropertyValue( gsSeparatorLineRelativeHeight
,
341 Any(mxColumnSep
->GetHeight()) );
343 if ( mxColumnSep
->GetStyle() )
345 xPropSet
->setPropertyValue( gsSeparatorLineStyle
, Any(mxColumnSep
->GetStyle()) );
348 xPropSet
->setPropertyValue( gsSeparatorLineColor
, Any(mxColumnSep
->GetColor()) );
350 xPropSet
->setPropertyValue( gsSeparatorLineVerticalAlignment
, Any(mxColumnSep
->GetVertAlign()) );
353 // handle 'automatic columns': column distance
356 xPropSet
->setPropertyValue( gsAutomaticDistance
, Any(nAutomaticDistance
) );
360 aProp
.maValue
<<= xColumns
;
363 XMLElementPropertyContext::endFastElement(nElement
);
367 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */