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 .
19 #include <DomainMapperTableHandler.hxx>
20 #include <DomainMapper_Impl.hxx>
21 #include <StyleSheetTable.hxx>
22 #include <com/sun/star/beans/XPropertyState.hpp>
23 #include <com/sun/star/container/XEnumerationAccess.hpp>
24 #include <com/sun/star/table/TableBorderDistances.hpp>
25 #include <com/sun/star/table/TableBorder.hpp>
26 #include <com/sun/star/table/BorderLine2.hpp>
27 #include <com/sun/star/table/BorderLineStyle.hpp>
28 #include <com/sun/star/table/XCellRange.hpp>
29 #include <com/sun/star/text/HoriOrientation.hpp>
30 #include <com/sun/star/text/RelOrientation.hpp>
31 #include <com/sun/star/text/SizeType.hpp>
32 #include <com/sun/star/text/VertOrientation.hpp>
33 #include <com/sun/star/text/XTextRangeCompare.hpp>
34 #include <com/sun/star/style/ParagraphAdjust.hpp>
35 #include <TablePositionHandler.hxx>
36 #include <ConversionHelper.hxx>
38 #include <osl/diagnose.h>
39 #include <comphelper/sequence.hxx>
41 #ifdef DEBUG_WRITERFILTER
42 #include <PropertyMapHelper.hxx>
43 #include <rtl/ustring.hxx>
46 namespace writerfilter
{
49 using namespace ::com::sun::star
;
50 using namespace ::std
;
52 #define DEF_BORDER_DIST 190 //0,19cm
54 DomainMapperTableHandler::DomainMapperTableHandler(TextReference_t
const& xText
,
55 DomainMapper_Impl
& rDMapper_Impl
)
57 m_rDMapper_Impl( rDMapper_Impl
),
60 m_bHadFootOrEndnote(false)
64 DomainMapperTableHandler::~DomainMapperTableHandler()
68 void DomainMapperTableHandler::startTable(unsigned int nRows
,
69 unsigned int /*nDepth*/,
70 TablePropertyMapPtr pProps
)
72 m_aTableProperties
= pProps
;
73 m_pTableSeq
= TableSequencePointer_t(new TableSequence_t(nRows
));
76 #ifdef DEBUG_WRITERFILTER
77 TagLogger::getInstance().startElement("tablehandler.table");
78 TagLogger::getInstance().attribute("rows", nRows
);
80 if (pProps
.get() != nullptr)
87 PropertyMapPtr
lcl_SearchParentStyleSheetAndMergeProperties(const StyleSheetEntryPtr
& rStyleSheet
, StyleSheetTablePtr pStyleSheetTable
)
94 if(!rStyleSheet
->sBaseStyleIdentifier
.isEmpty())
96 const StyleSheetEntryPtr pParentStyleSheet
= pStyleSheetTable
->FindStyleSheetByISTD(rStyleSheet
->sBaseStyleIdentifier
);
97 //a loop in the style hierarchy, bail out
98 if (pParentStyleSheet
== rStyleSheet
)
101 pRet
= lcl_SearchParentStyleSheetAndMergeProperties( pParentStyleSheet
, pStyleSheetTable
);
105 pRet
.reset( new PropertyMap
);
110 pRet
->InsertProps(rStyleSheet
->pProperties
);
116 void lcl_mergeBorder( PropertyIds nId
, PropertyMapPtr pOrig
, PropertyMapPtr pDest
)
118 boost::optional
<PropertyMap::Property
> pOrigVal
= pOrig
->getProperty(nId
);
122 pDest
->Insert( nId
, pOrigVal
->second
, false );
126 void lcl_computeCellBorders( PropertyMapPtr pTableBorders
, PropertyMapPtr pCellProps
,
127 sal_Int32 nCell
, sal_Int32 nRow
, bool bIsEndCol
, bool bIsEndRow
)
129 boost::optional
<PropertyMap::Property
> pVerticalVal
= pCellProps
->getProperty(META_PROP_VERTICAL_BORDER
);
130 boost::optional
<PropertyMap::Property
> pHorizontalVal
= pCellProps
->getProperty(META_PROP_HORIZONTAL_BORDER
);
132 // Handle the vertical and horizontal borders
136 pVerticalVal
= pTableBorders
->getProperty(META_PROP_VERTICAL_BORDER
);
138 aVertProp
= pVerticalVal
->second
;
142 aVertProp
= pVerticalVal
->second
;
143 pCellProps
->Erase( pVerticalVal
->first
);
147 if ( !pHorizontalVal
)
149 pHorizontalVal
= pTableBorders
->getProperty(META_PROP_HORIZONTAL_BORDER
);
150 if ( pHorizontalVal
)
151 aHorizProp
= pHorizontalVal
->second
;
155 aHorizProp
= pHorizontalVal
->second
;
156 pCellProps
->Erase( pHorizontalVal
->first
);
161 lcl_mergeBorder( PROP_LEFT_BORDER
, pTableBorders
, pCellProps
);
163 pCellProps
->Insert( PROP_RIGHT_BORDER
, aVertProp
, false );
168 lcl_mergeBorder( PROP_RIGHT_BORDER
, pTableBorders
, pCellProps
);
170 pCellProps
->Insert( PROP_LEFT_BORDER
, aVertProp
, false );
173 if ( nCell
> 0 && !bIsEndCol
)
177 pCellProps
->Insert( PROP_RIGHT_BORDER
, aVertProp
, false );
178 pCellProps
->Insert( PROP_LEFT_BORDER
, aVertProp
, false );
184 lcl_mergeBorder( PROP_TOP_BORDER
, pTableBorders
, pCellProps
);
185 if ( pHorizontalVal
)
186 pCellProps
->Insert( PROP_BOTTOM_BORDER
, aHorizProp
, false );
191 lcl_mergeBorder( PROP_BOTTOM_BORDER
, pTableBorders
, pCellProps
);
192 if ( pHorizontalVal
)
193 pCellProps
->Insert( PROP_TOP_BORDER
, aHorizProp
, false );
196 if ( nRow
> 0 && !bIsEndRow
)
198 if ( pHorizontalVal
)
200 pCellProps
->Insert( PROP_TOP_BORDER
, aHorizProp
, false );
201 pCellProps
->Insert( PROP_BOTTOM_BORDER
, aHorizProp
, false );
206 #ifdef DEBUG_WRITERFILTER
208 void lcl_debug_BorderLine(table::BorderLine
& rLine
)
210 TagLogger::getInstance().startElement("BorderLine");
211 TagLogger::getInstance().attribute("Color", rLine
.Color
);
212 TagLogger::getInstance().attribute("InnerLineWidth", rLine
.InnerLineWidth
);
213 TagLogger::getInstance().attribute("OuterLineWidth", rLine
.OuterLineWidth
);
214 TagLogger::getInstance().attribute("LineDistance", rLine
.LineDistance
);
215 TagLogger::getInstance().endElement();
218 void lcl_debug_TableBorder(table::TableBorder
& rBorder
)
220 TagLogger::getInstance().startElement("TableBorder");
221 lcl_debug_BorderLine(rBorder
.TopLine
);
222 TagLogger::getInstance().attribute("IsTopLineValid", sal_uInt32(rBorder
.IsTopLineValid
));
223 lcl_debug_BorderLine(rBorder
.BottomLine
);
224 TagLogger::getInstance().attribute("IsBottomLineValid", sal_uInt32(rBorder
.IsBottomLineValid
));
225 lcl_debug_BorderLine(rBorder
.LeftLine
);
226 TagLogger::getInstance().attribute("IsLeftLineValid", sal_uInt32(rBorder
.IsLeftLineValid
));
227 lcl_debug_BorderLine(rBorder
.RightLine
);
228 TagLogger::getInstance().attribute("IsRightLineValid", sal_uInt32(rBorder
.IsRightLineValid
));
229 lcl_debug_BorderLine(rBorder
.VerticalLine
);
230 TagLogger::getInstance().attribute("IsVerticalLineValid", sal_uInt32(rBorder
.IsVerticalLineValid
));
231 lcl_debug_BorderLine(rBorder
.HorizontalLine
);
232 TagLogger::getInstance().attribute("IsHorizontalLineValid", sal_uInt32(rBorder
.IsHorizontalLineValid
));
233 TagLogger::getInstance().attribute("Distance", rBorder
.Distance
);
234 TagLogger::getInstance().attribute("IsDistanceValid", sal_uInt32(rBorder
.IsDistanceValid
));
235 TagLogger::getInstance().endElement();
241 sal_Int32 nLeftBorderDistance
;
242 sal_Int32 nRightBorderDistance
;
243 sal_Int32 nTopBorderDistance
;
244 sal_Int32 nBottomBorderDistance
;
246 sal_Int32 nNestLevel
;
247 PropertyMapPtr pTableDefaults
;
248 PropertyMapPtr pTableBorders
;
249 TableStyleSheetEntry
* pTableStyle
;
250 TablePropertyValues_t aTableProperties
;
253 : nLeftBorderDistance(DEF_BORDER_DIST
)
254 , nRightBorderDistance(DEF_BORDER_DIST
)
255 , nTopBorderDistance(0)
256 , nBottomBorderDistance(0)
259 , pTableDefaults(new PropertyMap
)
260 , pTableBorders(new PropertyMap
)
261 , pTableStyle(nullptr)
270 bool lcl_extractTableBorderProperty(PropertyMapPtr pTableProperties
, const PropertyIds nId
, TableInfo
& rInfo
, table::BorderLine2
& rLine
)
272 if (!pTableProperties
)
275 const boost::optional
<PropertyMap::Property
> aTblBorder
= pTableProperties
->getProperty(nId
);
278 OSL_VERIFY(aTblBorder
->second
>>= rLine
);
280 rInfo
.pTableBorders
->Insert( nId
, uno::makeAny( rLine
) );
281 rInfo
.pTableDefaults
->Erase( nId
);
291 bool lcl_extractHoriOrient(std::vector
<beans::PropertyValue
>& rFrameProperties
, sal_Int32
& nHoriOrient
)
293 // Shifts the frame left by the given value.
294 for (size_t i
= 0; i
< rFrameProperties
.size(); ++i
)
296 if (rFrameProperties
[i
].Name
== "HoriOrient")
298 nHoriOrient
= rFrameProperties
[i
].Value
.get
<sal_Int32
>();
305 void lcl_DecrementHoriOrientPosition(std::vector
<beans::PropertyValue
>& rFrameProperties
, sal_Int32 nAmount
)
307 // Shifts the frame left by the given value.
308 for (size_t i
= 0; i
< rFrameProperties
.size(); ++i
)
310 beans::PropertyValue
& rPropertyValue
= rFrameProperties
[i
];
311 if (rPropertyValue
.Name
== "HoriOrientPosition")
313 sal_Int32 nValue
= rPropertyValue
.Value
.get
<sal_Int32
>();
315 rPropertyValue
.Value
<<= nValue
;
321 TableStyleSheetEntry
* DomainMapperTableHandler::endTableGetTableStyle(TableInfo
& rInfo
, std::vector
<beans::PropertyValue
>& rFrameProperties
)
323 // will receive the table style if any
324 TableStyleSheetEntry
* pTableStyle
= nullptr;
326 if( m_aTableProperties
.get() )
328 //create properties from the table attributes
329 //...pPropMap->Insert( PROP_LEFT_MARGIN, uno::makeAny( m_nLeftMargin - m_nGapHalf ));
330 //pPropMap->Insert( PROP_HORI_ORIENT, uno::makeAny( text::HoriOrientation::RIGHT ));
331 sal_Int32 nGapHalf
= 0;
332 sal_Int32 nLeftMargin
= 0;
333 sal_Int32 nTableWidth
= 0;
334 sal_Int32 nTableWidthType
= text::SizeType::FIX
;
336 comphelper::SequenceAsHashMap aGrabBag
;
338 if (nullptr != m_rDMapper_Impl
.getTableManager().getCurrentTableRealPosition())
340 TablePositionHandler
*pTablePositions
= m_rDMapper_Impl
.getTableManager().getCurrentTableRealPosition();
342 uno::Sequence
< beans::PropertyValue
> aGrabBagTS( 10 );
344 aGrabBagTS
[0].Name
= "bottomFromText";
345 aGrabBagTS
[0].Value
= uno::makeAny(pTablePositions
->getBottomFromText() );
347 aGrabBagTS
[1].Name
= "horzAnchor";
348 aGrabBagTS
[1].Value
= uno::makeAny( pTablePositions
->getHorzAnchor() );
350 aGrabBagTS
[2].Name
= "leftFromText";
351 aGrabBagTS
[2].Value
= uno::makeAny( pTablePositions
->getLeftFromText() );
353 aGrabBagTS
[3].Name
= "rightFromText";
354 aGrabBagTS
[3].Value
= uno::makeAny( pTablePositions
->getRightFromText() );
356 aGrabBagTS
[4].Name
= "tblpX";
357 aGrabBagTS
[4].Value
= uno::makeAny( pTablePositions
->getX() );
359 aGrabBagTS
[5].Name
= "tblpXSpec";
360 aGrabBagTS
[5].Value
= uno::makeAny( pTablePositions
->getXSpec() );
362 aGrabBagTS
[6].Name
= "tblpY";
363 aGrabBagTS
[6].Value
= uno::makeAny( pTablePositions
->getY() );
365 aGrabBagTS
[7].Name
= "tblpYSpec";
366 aGrabBagTS
[7].Value
= uno::makeAny( pTablePositions
->getYSpec() );
368 aGrabBagTS
[8].Name
= "topFromText";
369 aGrabBagTS
[8].Value
= uno::makeAny( pTablePositions
->getTopFromText() );
371 aGrabBagTS
[9].Name
= "vertAnchor";
372 aGrabBagTS
[9].Value
= uno::makeAny( pTablePositions
->getVertAnchor() );
374 aGrabBag
["TablePosition"] = uno::makeAny( aGrabBagTS
);
377 boost::optional
<PropertyMap::Property
> aTableStyleVal
= m_aTableProperties
->getProperty(META_PROP_TABLE_STYLE_NAME
);
380 // Apply table style properties recursively
381 OUString sTableStyleName
;
382 aTableStyleVal
->second
>>= sTableStyleName
;
383 StyleSheetTablePtr pStyleSheetTable
= m_rDMapper_Impl
.GetStyleSheetTable();
384 const StyleSheetEntryPtr pStyleSheet
= pStyleSheetTable
->FindStyleSheetByISTD( sTableStyleName
);
385 pTableStyle
= dynamic_cast<TableStyleSheetEntry
*>( pStyleSheet
.get( ) );
386 m_aTableProperties
->Erase( aTableStyleVal
->first
);
388 aGrabBag
["TableStyleName"] = uno::makeAny( sTableStyleName
);
392 // First get the style properties, then the table ones
393 PropertyMapPtr
pTableProps( m_aTableProperties
);
394 TablePropertyMapPtr
pEmptyProps( new TablePropertyMap
);
396 m_aTableProperties
= pEmptyProps
;
398 PropertyMapPtr pMergedProperties
= lcl_SearchParentStyleSheetAndMergeProperties(pStyleSheet
, pStyleSheetTable
);
400 table::BorderLine2 aBorderLine
;
401 TableInfo rStyleInfo
;
402 if (lcl_extractTableBorderProperty(pMergedProperties
, PROP_TOP_BORDER
, rStyleInfo
, aBorderLine
))
404 aGrabBag
["TableStyleTopBorder"] = uno::makeAny( aBorderLine
);
406 if (lcl_extractTableBorderProperty(pMergedProperties
, PROP_BOTTOM_BORDER
, rStyleInfo
, aBorderLine
))
408 aGrabBag
["TableStyleBottomBorder"] = uno::makeAny( aBorderLine
);
410 if (lcl_extractTableBorderProperty(pMergedProperties
, PROP_LEFT_BORDER
, rStyleInfo
, aBorderLine
))
412 aGrabBag
["TableStyleLeftBorder"] = uno::makeAny( aBorderLine
);
414 if (lcl_extractTableBorderProperty(pMergedProperties
, PROP_RIGHT_BORDER
, rStyleInfo
, aBorderLine
))
416 aGrabBag
["TableStyleRightBorder"] = uno::makeAny( aBorderLine
);
419 #ifdef DEBUG_WRITERFILTER
420 TagLogger::getInstance().startElement("mergedProps");
421 if (pMergedProperties
)
422 pMergedProperties
->dumpXml();
423 TagLogger::getInstance().endElement();
426 m_aTableProperties
->InsertProps(pMergedProperties
);
427 m_aTableProperties
->InsertProps(pTableProps
);
429 #ifdef DEBUG_WRITERFILTER
430 TagLogger::getInstance().startElement("TableProperties");
431 m_aTableProperties
->dumpXml();
432 TagLogger::getInstance().endElement();
437 // This is the one preserving just all the table look attributes.
438 boost::optional
<PropertyMap::Property
> oTableLook
= m_aTableProperties
->getProperty(META_PROP_TABLE_LOOK
);
441 aGrabBag
["TableStyleLook"] = oTableLook
->second
;
442 m_aTableProperties
->Erase(oTableLook
->first
);
445 // This is just the "val" attribute's numeric value.
446 const boost::optional
<PropertyMap::Property
> aTblLook
= m_aTableProperties
->getProperty(PROP_TBL_LOOK
);
449 aTblLook
->second
>>= rInfo
.nTblLook
;
450 m_aTableProperties
->Erase( aTblLook
->first
);
453 // Set the table default attributes for the cells
454 rInfo
.pTableDefaults
->InsertProps(m_aTableProperties
);
456 #ifdef DEBUG_WRITERFILTER
457 TagLogger::getInstance().startElement("TableDefaults");
458 rInfo
.pTableDefaults
->dumpXml();
459 TagLogger::getInstance().endElement();
462 if (!aGrabBag
.empty())
464 m_aTableProperties
->Insert( PROP_TABLE_INTEROP_GRAB_BAG
, uno::makeAny( aGrabBag
.getAsConstPropertyValueList() ) );
467 m_aTableProperties
->getValue( TablePropertyMap::GAP_HALF
, nGapHalf
);
468 m_aTableProperties
->getValue( TablePropertyMap::LEFT_MARGIN
, nLeftMargin
);
470 m_aTableProperties
->getValue( TablePropertyMap::CELL_MAR_LEFT
,
471 rInfo
.nLeftBorderDistance
);
472 m_aTableProperties
->getValue( TablePropertyMap::CELL_MAR_RIGHT
,
473 rInfo
.nRightBorderDistance
);
474 m_aTableProperties
->getValue( TablePropertyMap::CELL_MAR_TOP
,
475 rInfo
.nTopBorderDistance
);
476 m_aTableProperties
->getValue( TablePropertyMap::CELL_MAR_BOTTOM
,
477 rInfo
.nBottomBorderDistance
);
479 table::TableBorderDistances aDistances
;
480 aDistances
.IsTopDistanceValid
=
481 aDistances
.IsBottomDistanceValid
=
482 aDistances
.IsLeftDistanceValid
=
483 aDistances
.IsRightDistanceValid
= sal_True
;
484 aDistances
.TopDistance
= static_cast<sal_Int16
>( rInfo
.nTopBorderDistance
);
485 aDistances
.BottomDistance
= static_cast<sal_Int16
>( rInfo
.nBottomBorderDistance
);
486 aDistances
.LeftDistance
= static_cast<sal_Int16
>( rInfo
.nLeftBorderDistance
);
487 aDistances
.RightDistance
= static_cast<sal_Int16
>( rInfo
.nRightBorderDistance
);
489 m_aTableProperties
->Insert( PROP_TABLE_BORDER_DISTANCES
, uno::makeAny( aDistances
) );
491 if (!rFrameProperties
.empty())
492 lcl_DecrementHoriOrientPosition(rFrameProperties
, rInfo
.nLeftBorderDistance
);
494 // Set table above/bottom spacing to 0.
495 m_aTableProperties
->Insert( PROP_TOP_MARGIN
, uno::makeAny( sal_Int32( 0 ) ) );
496 m_aTableProperties
->Insert( PROP_BOTTOM_MARGIN
, uno::makeAny( sal_Int32( 0 ) ) );
498 //table border settings
499 table::TableBorder aTableBorder
;
500 table::BorderLine2 aBorderLine
, aLeftBorder
;
502 if (lcl_extractTableBorderProperty(m_aTableProperties
, PROP_TOP_BORDER
, rInfo
, aBorderLine
))
504 aTableBorder
.TopLine
= aBorderLine
;
505 aTableBorder
.IsTopLineValid
= sal_True
;
507 if (lcl_extractTableBorderProperty(m_aTableProperties
, PROP_BOTTOM_BORDER
, rInfo
, aBorderLine
))
509 aTableBorder
.BottomLine
= aBorderLine
;
510 aTableBorder
.IsBottomLineValid
= sal_True
;
512 if (lcl_extractTableBorderProperty(m_aTableProperties
, PROP_LEFT_BORDER
, rInfo
, aLeftBorder
))
514 aTableBorder
.LeftLine
= aLeftBorder
;
515 aTableBorder
.IsLeftLineValid
= sal_True
;
516 // Only top level table position depends on border width
517 if (rInfo
.nNestLevel
== 1)
519 if (rFrameProperties
.empty())
520 rInfo
.nLeftBorderDistance
+= aLeftBorder
.LineWidth
* 0.5;
522 lcl_DecrementHoriOrientPosition(rFrameProperties
, aLeftBorder
.LineWidth
* 0.5);
525 if (lcl_extractTableBorderProperty(m_aTableProperties
, PROP_RIGHT_BORDER
, rInfo
, aBorderLine
))
527 aTableBorder
.RightLine
= aBorderLine
;
528 aTableBorder
.IsRightLineValid
= sal_True
;
530 if (lcl_extractTableBorderProperty(m_aTableProperties
, META_PROP_HORIZONTAL_BORDER
, rInfo
, aBorderLine
))
532 aTableBorder
.HorizontalLine
= aBorderLine
;
533 aTableBorder
.IsHorizontalLineValid
= sal_True
;
535 if (lcl_extractTableBorderProperty(m_aTableProperties
, META_PROP_VERTICAL_BORDER
, rInfo
, aBorderLine
))
537 aTableBorder
.VerticalLine
= aBorderLine
;
538 aTableBorder
.IsVerticalLineValid
= sal_True
;
541 aTableBorder
.Distance
= 0;
542 aTableBorder
.IsDistanceValid
= sal_False
;
544 m_aTableProperties
->Insert( PROP_TABLE_BORDER
, uno::makeAny( aTableBorder
) );
546 #ifdef DEBUG_WRITERFILTER
547 lcl_debug_TableBorder(aTableBorder
);
550 // Table position in Office is computed in 2 different ways :
551 // - top level tables: the goal is to have in-cell text starting at table indent pos (tblInd),
552 // so table's position depends on table's cells margin
553 // - nested tables: the goal is to have left-most border starting at table_indent pos
554 if (rInfo
.nNestLevel
> 1)
556 m_aTableProperties
->Insert( PROP_LEFT_MARGIN
, uno::makeAny( nLeftMargin
- nGapHalf
));
560 m_aTableProperties
->Insert( PROP_LEFT_MARGIN
, uno::makeAny( nLeftMargin
- nGapHalf
- rInfo
.nLeftBorderDistance
));
563 m_aTableProperties
->getValue( TablePropertyMap::TABLE_WIDTH
, nTableWidth
);
564 m_aTableProperties
->getValue( TablePropertyMap::TABLE_WIDTH_TYPE
, nTableWidthType
);
565 if( nTableWidthType
== text::SizeType::FIX
)
567 if( nTableWidth
> 0 )
568 m_aTableProperties
->Insert( PROP_WIDTH
, uno::makeAny( nTableWidth
));
572 m_aTableProperties
->Insert( PROP_RELATIVE_WIDTH
, uno::makeAny( sal_Int16( nTableWidth
) ) );
573 m_aTableProperties
->Insert( PROP_IS_WIDTH_RELATIVE
, uno::makeAny( true ) );
576 sal_Int32 nHoriOrient
= text::HoriOrientation::LEFT_AND_WIDTH
;
577 // Fetch Horizontal Orientation in rFrameProperties if not set in m_aTableProperties
578 if ( !m_aTableProperties
->getValue( TablePropertyMap::HORI_ORIENT
, nHoriOrient
) )
579 lcl_extractHoriOrient( rFrameProperties
, nHoriOrient
);
580 m_aTableProperties
->Insert( PROP_HORI_ORIENT
, uno::makeAny( sal_Int16(nHoriOrient
) ) );
581 //fill default value - if not available
582 m_aTableProperties
->Insert( PROP_HEADER_ROW_COUNT
, uno::makeAny( (sal_Int32
)0), false);
584 rInfo
.aTableProperties
= m_aTableProperties
->GetPropertyValues();
586 #ifdef DEBUG_WRITERFILTER
587 TagLogger::getInstance().startElement("debug.tableprops");
588 m_aTableProperties
->dumpXml();
589 TagLogger::getInstance().endElement();
597 #define CNF_FIRST_ROW 0x800
598 #define CNF_LAST_ROW 0x400
599 #define CNF_FIRST_COLUMN 0x200
600 #define CNF_LAST_COLUMN 0x100
601 #define CNF_ODD_VBAND 0x080
602 #define CNF_EVEN_VBAND 0x040
603 #define CNF_ODD_HBAND 0x020
604 #define CNF_EVEN_HBAND 0x010
605 #define CNF_FIRST_ROW_LAST_COLUMN 0x008
606 #define CNF_FIRST_ROW_FIRST_COLUMN 0x004
607 #define CNF_LAST_ROW_LAST_COLUMN 0x002
608 #define CNF_LAST_ROW_FIRST_COLUMN 0x001
610 CellPropertyValuesSeq_t
DomainMapperTableHandler::endTableGetCellProperties(TableInfo
& rInfo
, std::vector
<HorizontallyMergedCell
>& rMerges
)
612 #ifdef DEBUG_WRITERFILTER
613 TagLogger::getInstance().startElement("getCellProperties");
616 CellPropertyValuesSeq_t
aCellProperties( m_aCellProperties
.size() );
618 if ( !m_aCellProperties
.size() )
620 #ifdef DEBUG_WRITERFILTER
621 TagLogger::getInstance().endElement();
623 return aCellProperties
;
625 // std::vector< std::vector<PropertyMapPtr> > m_aCellProperties
626 PropertyMapVector2::const_iterator aRowOfCellsIterator
= m_aCellProperties
.begin();
627 PropertyMapVector2::const_iterator aRowOfCellsIteratorEnd
= m_aCellProperties
.end();
628 PropertyMapVector2::const_iterator aLastRowIterator
= m_aCellProperties
.end() - 1;
631 //it's a uno::Sequence< beans::PropertyValues >*
632 RowPropertyValuesSeq_t
* pCellProperties
= aCellProperties
.getArray();
633 PropertyMapVector1::const_iterator aRowIter
= m_aRowProperties
.begin();
634 while( aRowOfCellsIterator
!= aRowOfCellsIteratorEnd
)
636 //aRowOfCellsIterator points to a vector of PropertyMapPtr
637 PropertyMapVector1::const_iterator aCellIterator
= aRowOfCellsIterator
->begin();
638 PropertyMapVector1::const_iterator aCellIteratorEnd
= aRowOfCellsIterator
->end();
640 sal_Int32 nRowStyleMask
= 0;
642 if (aRowOfCellsIterator
==m_aCellProperties
.begin())
644 if(rInfo
.nTblLook
&0x20)
645 nRowStyleMask
|= CNF_FIRST_ROW
; // first row style used
647 else if (aRowOfCellsIterator
==aLastRowIterator
)
649 if(rInfo
.nTblLook
&0x40)
650 nRowStyleMask
|= CNF_LAST_ROW
; // last row style used
652 else if (*aRowIter
&& (*aRowIter
)->isSet(PROP_TBL_HEADER
))
653 nRowStyleMask
|= CNF_FIRST_ROW
; // table header implies first row
654 if(!nRowStyleMask
) // if no row style used yet
656 // banding used only if not first and or last row style used
657 if(!(rInfo
.nTblLook
&0x200))
660 if(rInfo
.nTblLook
&0x20)
663 nRowStyleMask
= CNF_ODD_HBAND
;
665 nRowStyleMask
= CNF_EVEN_HBAND
;
670 pCellProperties
[nRow
].realloc( aRowOfCellsIterator
->size() );
671 beans::PropertyValues
* pSingleCellProperties
= pCellProperties
[nRow
].getArray();
672 while( aCellIterator
!= aCellIteratorEnd
)
674 PropertyMapPtr
pAllCellProps( new PropertyMap
);
676 PropertyMapVector1::const_iterator aLastCellIterator
= aRowOfCellsIterator
->end() - 1;
677 bool bIsEndCol
= aCellIterator
== aLastCellIterator
;
678 bool bIsEndRow
= aRowOfCellsIterator
== aLastRowIterator
;
680 //aCellIterator points to a PropertyMapPtr;
683 pAllCellProps
->InsertProps(rInfo
.pTableDefaults
);
685 sal_Int32 nCellStyleMask
= 0;
686 if (aCellIterator
==aRowOfCellsIterator
->begin())
688 if(rInfo
.nTblLook
&0x80)
689 nCellStyleMask
= CNF_FIRST_COLUMN
; // first col style used
693 if(rInfo
.nTblLook
&0x100)
694 nCellStyleMask
= CNF_LAST_COLUMN
; // last col style used
696 if(!nCellStyleMask
) // if no cell style is used yet
698 if(!(rInfo
.nTblLook
&0x400))
701 if(rInfo
.nTblLook
&0x80)
704 nCellStyleMask
= CNF_ODD_VBAND
;
706 nCellStyleMask
= CNF_EVEN_VBAND
;
709 sal_Int32 nCnfStyleMask
= nCellStyleMask
+ nRowStyleMask
;
710 if(nCnfStyleMask
== CNF_FIRST_COLUMN
+ CNF_FIRST_ROW
)
711 nCnfStyleMask
|= CNF_FIRST_ROW_FIRST_COLUMN
;
712 else if(nCnfStyleMask
== CNF_FIRST_COLUMN
+ CNF_LAST_ROW
)
713 nCnfStyleMask
|= CNF_LAST_ROW_FIRST_COLUMN
;
714 else if(nCnfStyleMask
== CNF_LAST_COLUMN
+ CNF_FIRST_ROW
)
715 nCnfStyleMask
|= CNF_FIRST_ROW_LAST_COLUMN
;
716 else if(nCnfStyleMask
== CNF_LAST_COLUMN
+ CNF_LAST_ROW
)
717 nCnfStyleMask
|= CNF_LAST_ROW_LAST_COLUMN
;
719 if ( rInfo
.pTableStyle
)
721 PropertyMapPtr pStyleProps
= rInfo
.pTableStyle
->GetProperties( nCnfStyleMask
);
723 // Check if we need to clean up some empty border definitions to match what Word does.
724 static const PropertyIds pBorders
[] =
726 PROP_TOP_BORDER
, PROP_LEFT_BORDER
, PROP_BOTTOM_BORDER
, PROP_RIGHT_BORDER
728 for (size_t i
= 0; i
< SAL_N_ELEMENTS(pBorders
); ++i
)
730 boost::optional
<PropertyMap::Property
> oStyleCellBorder
= pStyleProps
->getProperty(pBorders
[i
]);
731 boost::optional
<PropertyMap::Property
> oDirectCellBorder
= (*aCellIterator
)->getProperty(pBorders
[i
]);
732 if (oStyleCellBorder
&& oDirectCellBorder
)
734 // We have a cell border from the table style and as direct formatting as well.
735 table::BorderLine2 aStyleCellBorder
= oStyleCellBorder
->second
.get
<table::BorderLine2
>();
736 table::BorderLine2 aDirectCellBorder
= oDirectCellBorder
->second
.get
<table::BorderLine2
>();
737 if (aStyleCellBorder
.LineStyle
!= table::BorderLineStyle::NONE
&& aDirectCellBorder
.LineStyle
== table::BorderLineStyle::NONE
)
739 // The style one would be visible, but then cleared away as direct formatting.
740 // Delete both, so that table formatting can become visible.
741 pStyleProps
->Erase(pBorders
[i
]);
742 (*aCellIterator
)->Erase(pBorders
[i
]);
746 boost::optional
<PropertyMap::Property
> oTableBorder
= rInfo
.pTableBorders
->getProperty(pBorders
[i
]);
749 table::BorderLine2 aTableBorder
= oTableBorder
->second
.get
<table::BorderLine2
>();
750 // Both style and direct formatting says that the cell has no border.
751 bool bNoCellBorder
= aStyleCellBorder
.LineStyle
== table::BorderLineStyle::NONE
&& aDirectCellBorder
.LineStyle
== table::BorderLineStyle::NONE
;
752 if (aTableBorder
.LineStyle
!= table::BorderLineStyle::NONE
&& bNoCellBorder
)
754 // But at a table-level, there is a border, then again delete both cell properties.
755 pStyleProps
->Erase(pBorders
[i
]);
756 (*aCellIterator
)->Erase(pBorders
[i
]);
763 pAllCellProps
->InsertProps( pStyleProps
);
766 // Remove properties from style/row that aren't allowed in cells
767 pAllCellProps
->Erase( PROP_HEADER_ROW_COUNT
);
768 pAllCellProps
->Erase( PROP_TBL_HEADER
);
770 // Then add the cell properties
771 pAllCellProps
->InsertProps(*aCellIterator
);
772 std::swap(*(*aCellIterator
), *pAllCellProps
);
774 #ifdef DEBUG_WRITERFILTER
775 TagLogger::getInstance().startElement("cell");
776 TagLogger::getInstance().attribute("cell", nCell
);
777 TagLogger::getInstance().attribute("row", nRow
);
780 lcl_computeCellBorders( rInfo
.pTableBorders
, *aCellIterator
, nCell
, nRow
, bIsEndCol
, bIsEndRow
);
782 //now set the default left+right border distance TODO: there's an sprm containing the default distance!
783 aCellIterator
->get()->Insert( PROP_LEFT_BORDER_DISTANCE
,
784 uno::makeAny(rInfo
.nLeftBorderDistance
), false);
785 aCellIterator
->get()->Insert( PROP_RIGHT_BORDER_DISTANCE
,
786 uno::makeAny((sal_Int32
) rInfo
.nRightBorderDistance
), false);
787 aCellIterator
->get()->Insert( PROP_TOP_BORDER_DISTANCE
,
788 uno::makeAny((sal_Int32
) rInfo
.nTopBorderDistance
), false);
789 aCellIterator
->get()->Insert( PROP_BOTTOM_BORDER_DISTANCE
,
790 uno::makeAny((sal_Int32
) rInfo
.nBottomBorderDistance
), false);
792 // Horizontal merge is not an UNO property, extract that info here to rMerges, and then remove it from the map.
793 const boost::optional
<PropertyMap::Property
> aHorizontalMergeVal
= (*aCellIterator
)->getProperty(PROP_HORIZONTAL_MERGE
);
794 if (aHorizontalMergeVal
)
796 if (aHorizontalMergeVal
->second
.get
<sal_Bool
>())
798 // first cell in a merge
799 HorizontallyMergedCell
aMerge(nRow
, nCell
);
800 rMerges
.push_back(aMerge
);
802 else if (!rMerges
.empty())
804 // resuming an earlier merge
805 HorizontallyMergedCell
& rMerge
= rMerges
.back();
806 rMerge
.m_nLastRow
= nRow
;
807 rMerge
.m_nLastCol
= nCell
;
809 (*aCellIterator
)->Erase(PROP_HORIZONTAL_MERGE
);
812 // Cell direction is not an UNO Property, either.
813 const boost::optional
<PropertyMap::Property
> aCellDirectionVal
= (*aCellIterator
)->getProperty(PROP_CELL_DIRECTION
);
814 if (aCellDirectionVal
)
816 if (aCellDirectionVal
->second
.get
<sal_Int32
>() == static_cast<sal_Int32
>(NS_ooxml::LN_Value_ST_TextDirection_btLr
))
818 // btLr, so map ParagraphAdjust_CENTER to VertOrientation::CENTER.
819 uno::Reference
<beans::XPropertySet
> xPropertySet((*m_pTableSeq
)[nRow
][nCell
][0], uno::UNO_QUERY
);
820 if (xPropertySet
->getPropertyValue("ParaAdjust").get
<sal_Int16
>() == style::ParagraphAdjust_CENTER
)
821 (*aCellIterator
)->Insert(PROP_VERT_ORIENT
, uno::makeAny(text::VertOrientation::CENTER
));
823 (*aCellIterator
)->Erase(PROP_CELL_DIRECTION
);
826 pSingleCellProperties
[nCell
] = (*aCellIterator
)->GetPropertyValues();
827 #ifdef DEBUG_WRITERFILTER
828 TagLogger::getInstance().endElement();
834 #ifdef DEBUG_WRITERFILTER
835 //-->debug cell properties
838 const uno::Sequence
< beans::PropertyValues
> aDebugCurrentRow
= aCellProperties
[nRow
];
839 sal_Int32 nDebugCells
= aDebugCurrentRow
.getLength();
841 for( sal_Int32 nDebugCell
= 0; nDebugCell
< nDebugCells
; ++nDebugCell
)
843 const uno::Sequence
< beans::PropertyValue
>& aDebugCellProperties
= aDebugCurrentRow
[nDebugCell
];
844 sal_Int32 nDebugCellProperties
= aDebugCellProperties
.getLength();
845 for( sal_Int32 nDebugProperty
= 0; nDebugProperty
< nDebugCellProperties
; ++nDebugProperty
)
847 const OUString sName
= aDebugCellProperties
[nDebugProperty
].Name
;
849 sNames
+= OUString('-');
851 sNames
+= OUString('\n');
858 ++aRowOfCellsIterator
;
862 #ifdef DEBUG_WRITERFILTER
863 TagLogger::getInstance().endElement();
866 return aCellProperties
;
869 /// Do all cells in this row have a CellHideMark property?
870 bool lcl_hideMarks(PropertyMapVector1
& rCellProperties
)
872 for (size_t nCell
= 0; nCell
< rCellProperties
.size(); ++nCell
)
873 if (!rCellProperties
[nCell
]->isSet(PROP_CELL_HIDE_MARK
))
878 /// Are all cells in this row empty?
879 bool lcl_emptyRow(TableSequence_t
& rTableSeq
, sal_Int32 nRow
)
881 if (nRow
>= rTableSeq
.getLength())
883 SAL_WARN("writerfilter", "m_aCellProperties not in sync with m_pTableSeq?");
887 RowSequence_t rRowSeq
= rTableSeq
[nRow
];
888 if (rRowSeq
.getLength() == 0)
890 SAL_WARN("writerfilter", "m_aCellProperties not in sync with m_pTableSeq?");
894 uno::Reference
<text::XTextRangeCompare
> xTextRangeCompare(rRowSeq
[0][0]->getText(), uno::UNO_QUERY
);
897 for (sal_Int32 nCell
= 0; nCell
< rRowSeq
.getLength(); ++nCell
)
898 // See SwXText::Impl::ConvertCell(), we need to compare the start of
899 // the start and the end of the end. However for our text ranges, only
900 // the starts are set, so compareRegionStarts() does what we need.
901 if (xTextRangeCompare
->compareRegionStarts(rRowSeq
[nCell
][0], rRowSeq
[nCell
][1]) != 0)
904 catch (const lang::IllegalArgumentException
& e
)
906 SAL_WARN("writerfilter", "compareRegionStarts() failed: " << e
.Message
);
912 RowPropertyValuesSeq_t
DomainMapperTableHandler::endTableGetRowProperties()
914 #ifdef DEBUG_WRITERFILTER
915 TagLogger::getInstance().startElement("getRowProperties");
918 static const int MINLAY
= 23; // sw/inc/swtypes.hxx, minimal possible size of frames.
919 RowPropertyValuesSeq_t
aRowProperties( m_aRowProperties
.size() );
920 PropertyMapVector1::const_iterator aRowIter
= m_aRowProperties
.begin();
921 PropertyMapVector1::const_iterator aRowIterEnd
= m_aRowProperties
.end();
923 while( aRowIter
!= aRowIterEnd
)
925 #ifdef DEBUG_WRITERFILTER
926 TagLogger::getInstance().startElement("rowProps.row");
928 if( aRowIter
->get() )
930 //set default to 'break across pages"
931 (*aRowIter
)->Insert( PROP_IS_SPLIT_ALLOWED
, uno::makeAny(sal_True
), false );
932 // tblHeader is only our property, remove before the property map hits UNO
933 (*aRowIter
)->Erase(PROP_TBL_HEADER
);
935 if (lcl_hideMarks(m_aCellProperties
[nRow
]) && lcl_emptyRow(*m_pTableSeq
, nRow
))
937 // We have CellHideMark on all cells, and also all cells are empty:
938 // Set the row height to minimal as Word does.
939 (*aRowIter
)->Insert(PROP_SIZE_TYPE
, uno::makeAny(text::SizeType::FIX
));
940 (*aRowIter
)->Insert(PROP_HEIGHT
, uno::makeAny(static_cast<sal_Int32
>(ConversionHelper::convertTwipToMM100(MINLAY
))));
943 aRowProperties
[nRow
] = (*aRowIter
)->GetPropertyValues();
944 #ifdef DEBUG_WRITERFILTER
945 (*aRowIter
)->dumpXml();
946 lcl_DumpPropertyValues(aRowProperties
[nRow
]);
951 #ifdef DEBUG_WRITERFILTER
952 TagLogger::getInstance().endElement();
956 #ifdef DEBUG_WRITERFILTER
957 TagLogger::getInstance().endElement();
960 return aRowProperties
;
963 // Apply paragraph property to each paragraph within a cell.
964 static void lcl_ApplyCellParaProps(uno::Reference
<table::XCell
> const& xCell
,
965 const uno::Any
& rBottomMargin
)
967 uno::Reference
<container::XEnumerationAccess
> xEnumerationAccess(xCell
, uno::UNO_QUERY
);
968 uno::Reference
<container::XEnumeration
> xEnumeration
= xEnumerationAccess
->createEnumeration();
969 while (xEnumeration
->hasMoreElements())
971 uno::Reference
<beans::XPropertySet
> xParagraph(xEnumeration
->nextElement(), uno::UNO_QUERY
);
972 uno::Reference
<beans::XPropertyState
> xPropertyState(xParagraph
, uno::UNO_QUERY
);
973 // Don't apply in case direct formatting is already present.
974 // TODO: probably paragraph style has priority over table style here.
975 if (xPropertyState
.is() && xPropertyState
->getPropertyState("ParaBottomMargin") == beans::PropertyState_DEFAULT_VALUE
)
976 xParagraph
->setPropertyValue("ParaBottomMargin", rBottomMargin
);
980 void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel
)
982 #ifdef DEBUG_WRITERFILTER
983 TagLogger::getInstance().startElement("tablehandler.endTable");
986 // If we want to make this table a floating one.
987 std::vector
<beans::PropertyValue
> aFrameProperties
= comphelper::sequenceToContainer
<std::vector
<beans::PropertyValue
> >
988 (m_rDMapper_Impl
.getTableManager().getCurrentTablePosition());
989 TableInfo aTableInfo
;
990 aTableInfo
.nNestLevel
= nestedTableLevel
;
991 aTableInfo
.pTableStyle
= endTableGetTableStyle(aTableInfo
, aFrameProperties
);
992 // expands to uno::Sequence< Sequence< beans::PropertyValues > >
994 std::vector
<HorizontallyMergedCell
> aMerges
;
995 CellPropertyValuesSeq_t aCellProperties
= endTableGetCellProperties(aTableInfo
, aMerges
);
997 RowPropertyValuesSeq_t aRowProperties
= endTableGetRowProperties();
999 #ifdef DEBUG_WRITERFILTER
1000 lcl_DumpPropertyValueSeq(aRowProperties
);
1003 if (m_pTableSeq
->getLength() > 0)
1005 uno::Reference
<text::XTextRange
> xStart
;
1006 uno::Reference
<text::XTextRange
> xEnd
;
1008 bool bFloating
= !aFrameProperties
.empty();
1009 // Additional checks: if we can do this.
1010 if (bFloating
&& (*m_pTableSeq
)[0].getLength() > 0 && (*m_pTableSeq
)[0][0].getLength() > 0)
1012 xStart
= (*m_pTableSeq
)[0][0][0];
1013 uno::Sequence
< uno::Sequence
< uno::Reference
<text::XTextRange
> > >& rLastRow
= (*m_pTableSeq
)[m_pTableSeq
->getLength() - 1];
1014 uno::Sequence
< uno::Reference
<text::XTextRange
> >& rLastCell
= rLastRow
[rLastRow
.getLength() - 1];
1015 xEnd
= rLastCell
[1];
1017 uno::Reference
<text::XTextTable
> xTable
;
1022 xTable
= m_xText
->convertToTable(*m_pTableSeq
,
1025 aTableInfo
.aTableProperties
);
1029 m_xTableRange
= xTable
->getAnchor( );
1031 if (!aMerges
.empty())
1033 // Perform horizontal merges in reverse order, so the fact that merging changes the position of cells won't cause a problem for us.
1034 for (std::vector
<HorizontallyMergedCell
>::reverse_iterator it
= aMerges
.rbegin(); it
!= aMerges
.rend(); ++it
)
1036 uno::Reference
<table::XCellRange
> xCellRange(xTable
, uno::UNO_QUERY_THROW
);
1037 uno::Reference
<beans::XPropertySet
> xCell(xCellRange
->getCellByPosition(it
->m_nFirstCol
, it
->m_nFirstRow
), uno::UNO_QUERY_THROW
);
1038 OUString aFirst
= xCell
->getPropertyValue("CellName").get
<OUString
>();
1039 xCell
.set(xCellRange
->getCellByPosition(it
->m_nLastCol
, it
->m_nLastRow
), uno::UNO_QUERY_THROW
);
1040 OUString aLast
= xCell
->getPropertyValue("CellName").get
<OUString
>();
1042 uno::Reference
<text::XTextTableCursor
> xCursor
= xTable
->createCursorByCellName(aFirst
);
1043 xCursor
->gotoCellByName(aLast
, true);
1044 xCursor
->mergeRange();
1049 // OOXML table style may container paragraph properties, apply these now.
1050 for (int i
= 0; i
< aTableInfo
.aTableProperties
.getLength(); ++i
)
1052 if (aTableInfo
.aTableProperties
[i
].Name
== "ParaBottomMargin")
1054 uno::Reference
<table::XCellRange
> xCellRange(xTable
, uno::UNO_QUERY
);
1055 uno::Any aBottomMargin
= aTableInfo
.aTableProperties
[i
].Value
;
1056 sal_Int32 nRows
= aCellProperties
.getLength();
1057 for (sal_Int32 nRow
= 0; nRow
< nRows
; ++nRow
)
1059 const uno::Sequence
< beans::PropertyValues
> aCurrentRow
= aCellProperties
[nRow
];
1060 sal_Int32 nCells
= aCurrentRow
.getLength();
1061 for (sal_Int32 nCell
= 0; nCell
< nCells
; ++nCell
)
1062 lcl_ApplyCellParaProps(xCellRange
->getCellByPosition(nCell
, nRow
), aBottomMargin
);
1069 catch ( const lang::IllegalArgumentException
&e
)
1071 SAL_INFO("writerfilter.dmapper",
1072 "Conversion to table error: " << e
.Message
);
1073 #ifdef DEBUG_WRITERFILTER
1074 TagLogger::getInstance().chars(std::string("failed to import table!"));
1077 catch ( const uno::Exception
&e
)
1079 SAL_INFO("writerfilter.dmapper",
1080 "Exception during table creation: " << e
.Message
);
1083 // If we have a table with a start and an end position, we should make it a floating one.
1084 // Unless the table had a foot or endnote, as Writer doesn't support those in TextFrames.
1085 if (xTable
.is() && xStart
.is() && xEnd
.is() && !m_bHadFootOrEndnote
)
1087 uno::Reference
<beans::XPropertySet
> xTableProperties(xTable
, uno::UNO_QUERY
);
1088 bool bIsRelative
= false;
1089 xTableProperties
->getPropertyValue("IsWidthRelative") >>= bIsRelative
;
1092 beans::PropertyValue aValue
;
1093 aValue
.Name
= "Width";
1094 aValue
.Value
= xTableProperties
->getPropertyValue("Width");
1095 aFrameProperties
.push_back(aValue
);
1099 beans::PropertyValue aValue
;
1100 aValue
.Name
= "FrameWidthPercent";
1101 aValue
.Value
= xTableProperties
->getPropertyValue("RelativeWidth");
1102 aFrameProperties
.push_back(aValue
);
1104 // Applying the relative width to the frame, needs to have the table width to be 100% of the frame width
1105 xTableProperties
->setPropertyValue("RelativeWidth", uno::makeAny(sal_Int16(100)));
1108 // A non-zero left margin would move the table out of the frame, move the frame itself instead.
1109 xTableProperties
->setPropertyValue("LeftMargin", uno::makeAny(sal_Int32(0)));
1111 // In case the document ends with a table, we're called after
1112 // SectionPropertyMap::CloseSectionGroup(), so we'll have no idea
1113 // about the text area width, nor can fix this by delaying the text
1114 // frame conversion: just do it here.
1115 // Also, when the anchor is within a table, then do it here as well,
1116 // as xStart/xEnd would not point to the start/end at conversion
1118 // Next exception: it's pointless to delay the conversion if the
1119 // table is not in the body text.
1120 sal_Int32 nTableWidth
= 0;
1121 m_aTableProperties
->getValue(TablePropertyMap::TABLE_WIDTH
, nTableWidth
);
1122 if (m_rDMapper_Impl
.GetSectionContext() && nestedTableLevel
<= 1 && !m_rDMapper_Impl
.IsInHeaderFooter())
1123 m_rDMapper_Impl
.m_aPendingFloatingTables
.push_back(FloatingTableInfo(xStart
, xEnd
, comphelper::containerToSequence(aFrameProperties
), nTableWidth
));
1126 // m_xText points to the body text, get to current xText from m_rDMapper_Impl, in case e.g. we would be in a header.
1127 uno::Reference
<text::XTextAppendAndConvert
> xTextAppendAndConvert(m_rDMapper_Impl
.GetTopTextAppend(), uno::UNO_QUERY
);
1128 if (xTextAppendAndConvert
.is())
1129 xTextAppendAndConvert
->convertToTextFrame(xStart
, xEnd
, comphelper::containerToSequence(aFrameProperties
));
1134 m_aTableProperties
.reset();
1135 m_aCellProperties
.clear();
1136 m_aRowProperties
.clear();
1137 m_bHadFootOrEndnote
= false;
1139 #ifdef DEBUG_WRITERFILTER
1140 TagLogger::getInstance().endElement();
1141 TagLogger::getInstance().endElement();
1145 void DomainMapperTableHandler::startRow(unsigned int nCells
,
1146 TablePropertyMapPtr pProps
)
1148 m_aRowProperties
.push_back( pProps
);
1149 m_aCellProperties
.push_back( PropertyMapVector1() );
1151 #ifdef DEBUG_WRITERFILTER
1152 TagLogger::getInstance().startElement("table.row");
1153 TagLogger::getInstance().attribute("cells", nCells
);
1154 if (pProps
!= nullptr)
1158 m_pRowSeq
= RowSequencePointer_t(new RowSequence_t(nCells
));
1162 void DomainMapperTableHandler::endRow()
1164 (*m_pTableSeq
)[m_nRowIndex
] = *m_pRowSeq
;
1167 #ifdef DEBUG_WRITERFILTER
1168 TagLogger::getInstance().endElement();
1172 void DomainMapperTableHandler::startCell(const Handle_t
& start
,
1173 TablePropertyMapPtr pProps
)
1175 sal_uInt32 nRow
= m_aRowProperties
.size();
1176 if ( pProps
.get( ) )
1177 m_aCellProperties
[nRow
- 1].push_back( pProps
);
1180 // Adding an empty cell properties map to be able to get
1181 // the table defaults properties
1182 TablePropertyMapPtr
pEmptyProps( new TablePropertyMap( ) );
1183 m_aCellProperties
[nRow
- 1].push_back( pEmptyProps
);
1186 #ifdef DEBUG_WRITERFILTER
1187 TagLogger::getInstance().startElement("table.cell");
1188 TagLogger::getInstance().startElement("table.cell.start");
1189 TagLogger::getInstance().chars(XTextRangeToString(start
));
1190 TagLogger::getInstance().endElement();
1192 pProps
->printProperties();
1195 //add a new 'row' of properties
1196 m_pCellSeq
= CellSequencePointer_t(new CellSequence_t(2));
1199 (*m_pCellSeq
)[0] = start
->getStart();
1202 void DomainMapperTableHandler::endCell(const Handle_t
& end
)
1204 #ifdef DEBUG_WRITERFILTER
1205 TagLogger::getInstance().startElement("table.cell.end");
1206 TagLogger::getInstance().chars(XTextRangeToString(end
));
1207 TagLogger::getInstance().endElement();
1208 TagLogger::getInstance().endElement();
1213 (*m_pCellSeq
)[1] = end
->getEnd();
1214 (*m_pRowSeq
)[m_nCellIndex
] = *m_pCellSeq
;
1218 void DomainMapperTableHandler::setHadFootOrEndnote(bool bHadFootOrEndnote
)
1220 m_bHadFootOrEndnote
= bHadFootOrEndnote
;
1225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */