1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <com/sun/star/text/XTextColumns.hpp>
30 #include <com/sun/star/text/TextColumn.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/style/VerticalAlignment.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <sax/tools/converter.hxx>
35 #include <xmloff/xmltkmap.hxx>
36 #include <xmloff/xmluconv.hxx>
37 #include <xmloff/nmspmap.hxx>
38 #include "xmloff/xmlnmspe.hxx"
39 #include <xmloff/xmlimp.hxx>
40 #include <xmloff/xmltoken.hxx>
41 #include "XMLTextColumnsContext.hxx"
42 #include <svl/svstdarr.hxx>
44 using ::rtl::OUString
;
45 using ::rtl::OUStringBuffer
;
47 using namespace ::com::sun::star
;
48 using namespace ::com::sun::star::uno
;
49 using namespace ::com::sun::star::lang
;
50 using namespace ::com::sun::star::text
;
51 using namespace ::com::sun::star::style
;
52 using namespace ::com::sun::star::beans
;
53 using namespace ::xmloff::token
;
55 enum SvXMLTokenMapAttrs
58 XML_TOK_COLUMN_MARGIN_LEFT
,
59 XML_TOK_COLUMN_MARGIN_RIGHT
,
60 XML_TOK_COLUMN_END
=XML_TOK_UNKNOWN
63 enum SvXMLSepTokenMapAttrs
65 XML_TOK_COLUMN_SEP_WIDTH
,
66 XML_TOK_COLUMN_SEP_HEIGHT
,
67 XML_TOK_COLUMN_SEP_COLOR
,
68 XML_TOK_COLUMN_SEP_ALIGN
,
69 XML_TOK_COLUMN_SEP_STYLE
,
70 XML_TOK_COLUMN_SEP_END
=XML_TOK_UNKNOWN
73 static SvXMLTokenMapEntry aColAttrTokenMap
[] =
75 { XML_NAMESPACE_STYLE
, XML_REL_WIDTH
, XML_TOK_COLUMN_WIDTH
},
76 { XML_NAMESPACE_FO
, XML_START_INDENT
, XML_TOK_COLUMN_MARGIN_LEFT
},
77 { XML_NAMESPACE_FO
, XML_END_INDENT
, XML_TOK_COLUMN_MARGIN_RIGHT
},
81 static SvXMLTokenMapEntry aColSepAttrTokenMap
[] =
83 { XML_NAMESPACE_STYLE
, XML_WIDTH
, XML_TOK_COLUMN_SEP_WIDTH
},
84 { XML_NAMESPACE_STYLE
, XML_COLOR
, XML_TOK_COLUMN_SEP_COLOR
},
85 { XML_NAMESPACE_STYLE
, XML_HEIGHT
, XML_TOK_COLUMN_SEP_HEIGHT
},
86 { XML_NAMESPACE_STYLE
, XML_VERTICAL_ALIGN
, XML_TOK_COLUMN_SEP_ALIGN
},
87 { XML_NAMESPACE_STYLE
, XML_STYLE
, XML_TOK_COLUMN_SEP_STYLE
},
91 SvXMLEnumMapEntry
const pXML_Sep_Style_Enum
[] =
97 { XML_TOKEN_INVALID
, 0 }
100 SvXMLEnumMapEntry
const pXML_Sep_Align_Enum
[] =
102 { XML_TOP
, VerticalAlignment_TOP
},
103 { XML_MIDDLE
, VerticalAlignment_MIDDLE
},
104 { XML_BOTTOM
, VerticalAlignment_BOTTOM
},
105 { XML_TOKEN_INVALID
, 0 }
108 class XMLTextColumnContext_Impl
: public SvXMLImportContext
110 text::TextColumn aColumn
;
115 XMLTextColumnContext_Impl( SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
116 const OUString
& rLName
,
117 const uno::Reference
<
118 xml::sax::XAttributeList
> & xAttrList
,
119 const SvXMLTokenMap
& rTokenMap
);
121 virtual ~XMLTextColumnContext_Impl();
123 text::TextColumn
& getTextColumn() { return aColumn
; }
126 TYPEINIT1( XMLTextColumnContext_Impl
, SvXMLImportContext
);
128 XMLTextColumnContext_Impl::XMLTextColumnContext_Impl(
129 SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
130 const OUString
& rLName
,
131 const uno::Reference
<
132 xml::sax::XAttributeList
> & xAttrList
,
133 const SvXMLTokenMap
& rTokenMap
) :
134 SvXMLImportContext( rImport
, nPrfx
, rLName
)
137 aColumn
.LeftMargin
= 0;
138 aColumn
.RightMargin
= 0;
140 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
141 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
143 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
146 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
148 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
151 switch( rTokenMap
.Get( nPrefix
, aLocalName
) )
153 case XML_TOK_COLUMN_WIDTH
:
155 sal_Int32 nPos
= rValue
.indexOf( (sal_Unicode
)'*' );
156 if( nPos
!= -1 && nPos
+1 == rValue
.getLength() )
158 OUString
sTmp( rValue
.copy( 0, nPos
) );
159 if (::sax::Converter::convertNumber(
160 nVal
, sTmp
, 0, USHRT_MAX
))
161 aColumn
.Width
= nVal
;
165 case XML_TOK_COLUMN_MARGIN_LEFT
:
166 if( GetImport().GetMM100UnitConverter().
167 convertMeasureToCore( nVal
, rValue
) )
168 aColumn
.LeftMargin
= nVal
;
170 case XML_TOK_COLUMN_MARGIN_RIGHT
:
172 if( GetImport().GetMM100UnitConverter().
173 convertMeasureToCore( nVal
, rValue
) )
174 aColumn
.RightMargin
= nVal
;
182 XMLTextColumnContext_Impl::~XMLTextColumnContext_Impl()
186 // --------------------------------------------------------------------------
188 class XMLTextColumnSepContext_Impl
: public SvXMLImportContext
194 VerticalAlignment eVertAlign
;
200 XMLTextColumnSepContext_Impl( SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
201 const OUString
& rLName
,
202 const uno::Reference
<
203 xml::sax::XAttributeList
> & xAttrList
,
204 const SvXMLTokenMap
& rTokenMap
);
206 virtual ~XMLTextColumnSepContext_Impl();
208 sal_Int32
GetWidth() const { return nWidth
; }
209 sal_Int32
GetColor() const { return nColor
; }
210 sal_Int8
GetHeight() const { return nHeight
; }
211 sal_Int8
GetStyle() const { return nStyle
; }
212 VerticalAlignment
GetVertAlign() const { return eVertAlign
; }
216 TYPEINIT1( XMLTextColumnSepContext_Impl
, SvXMLImportContext
);
218 XMLTextColumnSepContext_Impl::XMLTextColumnSepContext_Impl(
219 SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
220 const OUString
& rLName
,
221 const uno::Reference
<
222 xml::sax::XAttributeList
> & xAttrList
,
223 const SvXMLTokenMap
& rTokenMap
) :
224 SvXMLImportContext( rImport
, nPrfx
, rLName
),
229 eVertAlign( VerticalAlignment_TOP
)
231 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
232 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
234 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
237 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
239 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
242 switch( rTokenMap
.Get( nPrefix
, aLocalName
) )
244 case XML_TOK_COLUMN_SEP_WIDTH
:
245 if( GetImport().GetMM100UnitConverter().
246 convertMeasureToCore( nVal
, rValue
) )
249 case XML_TOK_COLUMN_SEP_HEIGHT
:
250 if (::sax::Converter::convertPercent( nVal
, rValue
) &&
251 nVal
>=1 && nVal
<= 100 )
252 nHeight
= (sal_Int8
)nVal
;
254 case XML_TOK_COLUMN_SEP_COLOR
:
256 ::sax::Converter::convertColor( nColor
, rValue
);
259 case XML_TOK_COLUMN_SEP_ALIGN
:
262 if( GetImport().GetMM100UnitConverter().
263 convertEnum( nAlign
, rValue
,
264 pXML_Sep_Align_Enum
) )
265 eVertAlign
= (VerticalAlignment
)nAlign
;
268 case XML_TOK_COLUMN_SEP_STYLE
:
270 sal_uInt16 nStyleVal
;
271 if( GetImport().GetMM100UnitConverter().
272 convertEnum( nStyleVal
, rValue
,
273 pXML_Sep_Style_Enum
) )
274 nStyle
= (sal_Int8
)nStyleVal
;
281 XMLTextColumnSepContext_Impl::~XMLTextColumnSepContext_Impl()
285 // --------------------------------------------------------------------------
287 class XMLTextColumnsArray_Impl
: public std::vector
<XMLTextColumnContext_Impl
*> {};
289 TYPEINIT1( XMLTextColumnsContext
, XMLElementPropertyContext
);
291 XMLTextColumnsContext::XMLTextColumnsContext(
292 SvXMLImport
& rImport
, sal_uInt16 nPrfx
,
293 const OUString
& rLName
,
294 const Reference
< xml::sax::XAttributeList
>&
296 const XMLPropertyState
& rProp
,
297 ::std::vector
< XMLPropertyState
> &rProps
)
298 : XMLElementPropertyContext( rImport
, nPrfx
, rLName
, rProp
, rProps
)
299 , sSeparatorLineIsOn(RTL_CONSTASCII_USTRINGPARAM("SeparatorLineIsOn"))
300 , sSeparatorLineWidth(RTL_CONSTASCII_USTRINGPARAM("SeparatorLineWidth"))
301 , sSeparatorLineColor(RTL_CONSTASCII_USTRINGPARAM("SeparatorLineColor"))
302 , sSeparatorLineRelativeHeight(RTL_CONSTASCII_USTRINGPARAM("SeparatorLineRelativeHeight"))
303 , sSeparatorLineVerticalAlignment(RTL_CONSTASCII_USTRINGPARAM("SeparatorLineVerticalAlignment"))
304 , sIsAutomatic(RTL_CONSTASCII_USTRINGPARAM("IsAutomatic"))
305 , sAutomaticDistance(RTL_CONSTASCII_USTRINGPARAM("AutomaticDistance"))
306 , sSeparatorLineStyle(RTL_CONSTASCII_USTRINGPARAM("SeparatorLineStyle"))
309 , pColumnAttrTokenMap( new SvXMLTokenMap(aColAttrTokenMap
) )
310 , pColumnSepAttrTokenMap( new SvXMLTokenMap(aColSepAttrTokenMap
) )
312 , bAutomatic( sal_False
)
313 , nAutomaticDistance( 0 )
315 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
317 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
319 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
322 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
324 const OUString
& rValue
= xAttrList
->getValueByIndex( i
);
325 if( XML_NAMESPACE_FO
== nPrefix
)
327 if( IsXMLToken( aLocalName
, XML_COLUMN_COUNT
) &&
328 ::sax::Converter::convertNumber( nVal
, rValue
, 0, SHRT_MAX
))
330 nCount
= (sal_Int16
)nVal
;
332 else if( IsXMLToken( aLocalName
, XML_COLUMN_GAP
) )
334 bAutomatic
= GetImport().GetMM100UnitConverter().
335 convertMeasureToCore( nAutomaticDistance
, rValue
);
341 XMLTextColumnsContext::~XMLTextColumnsContext()
345 for (XMLTextColumnsArray_Impl::iterator it
= pColumns
->begin();
346 it
!= pColumns
->end(); ++it
)
352 pColumnSep
->ReleaseRef();
355 delete pColumnAttrTokenMap
;
356 delete pColumnSepAttrTokenMap
;
359 SvXMLImportContext
*XMLTextColumnsContext::CreateChildContext(
361 const OUString
& rLocalName
,
362 const uno::Reference
< xml::sax::XAttributeList
> & xAttrList
)
364 SvXMLImportContext
*pContext
= 0;
366 if( XML_NAMESPACE_STYLE
== nPrefix
&&
367 IsXMLToken( rLocalName
, XML_COLUMN
) )
369 XMLTextColumnContext_Impl
*pColumn
=
370 new XMLTextColumnContext_Impl( GetImport(), nPrefix
, rLocalName
,
371 xAttrList
, *pColumnAttrTokenMap
);
373 // add new tabstop to array of tabstops
375 pColumns
= new XMLTextColumnsArray_Impl
;
377 pColumns
->push_back( pColumn
);
382 else if( XML_NAMESPACE_STYLE
== nPrefix
&&
383 IsXMLToken( rLocalName
, XML_COLUMN_SEP
) )
386 new XMLTextColumnSepContext_Impl( GetImport(), nPrefix
, rLocalName
,
387 xAttrList
, *pColumnSepAttrTokenMap
);
388 pColumnSep
->AddRef();
390 pContext
= pColumnSep
;
394 pContext
= new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
400 void XMLTextColumnsContext::EndElement( )
402 Reference
<XMultiServiceFactory
> xFactory(GetImport().GetModel(),UNO_QUERY
);
406 Reference
<XInterface
> xIfc
= xFactory
->createInstance(
407 OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextColumns")));
411 Reference
< XTextColumns
> xColumns( xIfc
, UNO_QUERY
);
414 // zero columns = no columns -> 1 column
415 xColumns
->setColumnCount( 1 );
417 else if( !bAutomatic
&& pColumns
&&
418 pColumns
->size() == (sal_uInt16
)nCount
)
420 // if we have column descriptions, one per column, and we don't use
421 // automatic width, then set the column widths
423 sal_Int32 nRelWidth
= 0;
424 sal_uInt16 nColumnsWithWidth
= 0;
427 for( i
= 0; i
< nCount
; i
++ )
429 const TextColumn
& rColumn
=
430 (*pColumns
)[(sal_uInt16
)i
]->getTextColumn();
431 if( rColumn
.Width
> 0 )
433 nRelWidth
+= rColumn
.Width
;
437 if( nColumnsWithWidth
< nCount
)
439 sal_Int32 nColWidth
= 0==nRelWidth
441 : nRelWidth
/ nColumnsWithWidth
;
443 for( i
=0; i
< nCount
; i
++ )
445 TextColumn
& rColumn
=
446 (*pColumns
)[(sal_uInt16
)i
]->getTextColumn();
447 if( rColumn
.Width
== 0 )
449 rColumn
.Width
= nColWidth
;
450 nRelWidth
+= rColumn
.Width
;
451 if( 0 == --nColumnsWithWidth
)
457 Sequence
< TextColumn
> aColumns( (sal_Int32
)nCount
);
458 TextColumn
*pTextColumns
= aColumns
.getArray();
459 for( i
=0; i
< nCount
; i
++ )
460 *pTextColumns
++ = (*pColumns
)[(sal_uInt16
)i
]->getTextColumn();
462 xColumns
->setColumns( aColumns
);
466 // only set column count (and let the columns be distributed
469 xColumns
->setColumnCount( nCount
);
472 Reference
< XPropertySet
> xPropSet( xColumns
, UNO_QUERY
);
476 sal_Bool bOn
= pColumnSep
!= 0;
478 aAny
.setValue( &bOn
, ::getBooleanCppuType() );
479 xPropSet
->setPropertyValue( sSeparatorLineIsOn
, aAny
);
483 if( pColumnSep
->GetWidth() )
485 aAny
<<= pColumnSep
->GetWidth();
486 xPropSet
->setPropertyValue( sSeparatorLineWidth
, aAny
);
488 if( pColumnSep
->GetHeight() )
490 aAny
<<= pColumnSep
->GetHeight();
491 xPropSet
->setPropertyValue( sSeparatorLineRelativeHeight
,
494 if ( pColumnSep
->GetStyle() )
496 aAny
<<= pColumnSep
->GetStyle();
497 xPropSet
->setPropertyValue( sSeparatorLineStyle
, aAny
);
501 aAny
<<= pColumnSep
->GetColor();
502 xPropSet
->setPropertyValue( sSeparatorLineColor
, aAny
);
505 aAny
<<= pColumnSep
->GetVertAlign();
506 xPropSet
->setPropertyValue( sSeparatorLineVerticalAlignment
, aAny
);
509 // handle 'automatic columns': column distance
512 aAny
<<= nAutomaticDistance
;
513 xPropSet
->setPropertyValue( sAutomaticDistance
, aAny
);
517 aProp
.maValue
<<= xColumns
;
519 SetInsert( sal_True
);
520 XMLElementPropertyContext::EndElement();
524 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */