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/XCellRange.hpp>
28 #include <com/sun/star/text/HoriOrientation.hpp>
29 #include <com/sun/star/text/RelOrientation.hpp>
30 #include <com/sun/star/text/SizeType.hpp>
31 #include <com/sun/star/text/VertOrientation.hpp>
32 #include <com/sun/star/text/XTextRangeCompare.hpp>
33 #include <com/sun/star/style/ParagraphAdjust.hpp>
34 #include <dmapperLoggers.hxx>
35 #include <TablePositionHandler.hxx>
36 #include <ConversionHelper.hxx>
38 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
39 #include <PropertyMapHelper.hxx>
40 #include <rtl/ustring.hxx>
43 namespace writerfilter
{
46 using namespace ::com::sun::star
;
47 using namespace ::std
;
49 #define DEF_BORDER_DIST 190 //0,19cm
51 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
52 static void lcl_printProperties( PropertyMapPtr pProps
)
56 dmapper_logger
->startElement("properties");
58 PropertyMap::const_iterator aMapIter
= pProps
->begin();
59 PropertyMap::const_iterator aEndIter
= pProps
->end();
60 PropertyNameSupplier
& rPropSupplier
= PropertyNameSupplier::GetPropertyNameSupplier();
61 for( ; aMapIter
!= aEndIter
; ++aMapIter
)
63 SAL_INFO("writerfilter", rPropSupplier
.GetName(aMapIter
->first
));
65 table::BorderLine2 aLine
;
67 if ( aMapIter
->second
.getValue() >>= aLine
)
69 dmapper_logger
->startElement("borderline");
70 dmapper_logger
->attribute("color", aLine
.Color
);
71 dmapper_logger
->attribute("inner", aLine
.InnerLineWidth
);
72 dmapper_logger
->attribute("outer", aLine
.OuterLineWidth
);
73 dmapper_logger
->endElement();
75 else if ( aMapIter
->second
.getValue() >>= nColor
)
77 dmapper_logger
->startElement("color");
78 dmapper_logger
->attribute("number", nColor
);
79 dmapper_logger
->endElement();
83 dmapper_logger
->endElement();
88 DomainMapperTableHandler::DomainMapperTableHandler(TextReference_t xText
, DomainMapper_Impl
& rDMapper_Impl
)
90 m_rDMapper_Impl( rDMapper_Impl
),
96 DomainMapperTableHandler::~DomainMapperTableHandler()
100 void DomainMapperTableHandler::startTable(unsigned int nRows
,
101 unsigned int /*nDepth*/,
102 TablePropertyMapPtr pProps
)
104 m_aTableProperties
= pProps
;
105 m_pTableSeq
= TableSequencePointer_t(new TableSequence_t(nRows
));
108 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
109 dmapper_logger
->startElement("tablehandler.table");
110 dmapper_logger
->attribute("rows", nRows
);
112 if (pProps
.get() != NULL
)
113 pProps
->dumpXml( dmapper_logger
);
119 PropertyMapPtr
lcl_SearchParentStyleSheetAndMergeProperties(const StyleSheetEntryPtr pStyleSheet
, StyleSheetTablePtr pStyleSheetTable
)
126 if(!pStyleSheet
->sBaseStyleIdentifier
.isEmpty())
128 const StyleSheetEntryPtr pParentStyleSheet
= pStyleSheetTable
->FindStyleSheetByISTD( pStyleSheet
->sBaseStyleIdentifier
);
129 //a loop in the style hierarchy, bail out
130 if (pParentStyleSheet
== pStyleSheet
)
133 pRet
= lcl_SearchParentStyleSheetAndMergeProperties( pParentStyleSheet
, pStyleSheetTable
);
137 pRet
.reset( new PropertyMap
);
142 pRet
->InsertProps(pStyleSheet
->pProperties
);
148 void lcl_mergeBorder( PropertyIds nId
, PropertyMapPtr pOrig
, PropertyMapPtr pDest
)
150 PropertyMap::iterator pOrigIt
= pOrig
->find(nId
);
152 if ( pOrigIt
!= pOrig
->end( ) )
154 pDest
->Insert( nId
, pOrigIt
->second
.getValue(), false );
158 void lcl_computeCellBorders( PropertyMapPtr pTableBorders
, PropertyMapPtr pCellProps
,
159 sal_Int32 nCell
, sal_Int32 nRow
, bool bIsEndCol
, bool bIsEndRow
)
161 PropertyMap::iterator aVerticalIter
= pCellProps
->find(META_PROP_VERTICAL_BORDER
);
162 PropertyMap::iterator aHorizontalIter
= pCellProps
->find(META_PROP_HORIZONTAL_BORDER
);
164 // Handle the vertical and horizontal borders
165 bool bHasVert
= ( aVerticalIter
!= pCellProps
->end( ) );
169 aVerticalIter
= pTableBorders
->find(META_PROP_VERTICAL_BORDER
);
170 bHasVert
= ( aVerticalIter
!= pTableBorders
->end( ) );
172 aVertProp
= aVerticalIter
->second
.getValue();
176 aVertProp
= aVerticalIter
->second
.getValue();
177 pCellProps
->erase( aVerticalIter
);
180 bool bHasHoriz
= ( aHorizontalIter
!= pCellProps
->end( ) );
184 aHorizontalIter
= pTableBorders
->find(META_PROP_HORIZONTAL_BORDER
);
185 bHasHoriz
= ( aHorizontalIter
!= pTableBorders
->end( ) );
187 aHorizProp
= aHorizontalIter
->second
.getValue();
191 aHorizProp
= aHorizontalIter
->second
.getValue();
192 pCellProps
->erase( aHorizontalIter
);
197 lcl_mergeBorder( PROP_LEFT_BORDER
, pTableBorders
, pCellProps
);
199 pCellProps
->Insert( PROP_RIGHT_BORDER
, aVertProp
, false );
204 lcl_mergeBorder( PROP_RIGHT_BORDER
, pTableBorders
, pCellProps
);
206 pCellProps
->Insert( PROP_LEFT_BORDER
, aVertProp
, false );
209 if ( nCell
> 0 && !bIsEndCol
)
213 pCellProps
->Insert( PROP_RIGHT_BORDER
, aVertProp
, false );
214 pCellProps
->Insert( PROP_LEFT_BORDER
, aVertProp
, false );
220 lcl_mergeBorder( PROP_TOP_BORDER
, pTableBorders
, pCellProps
);
222 pCellProps
->Insert( PROP_BOTTOM_BORDER
, aHorizProp
, false );
227 lcl_mergeBorder( PROP_BOTTOM_BORDER
, pTableBorders
, pCellProps
);
229 pCellProps
->Insert( PROP_TOP_BORDER
, aHorizProp
, false );
232 if ( nRow
> 0 && !bIsEndRow
)
236 pCellProps
->Insert( PROP_TOP_BORDER
, aHorizProp
, false );
237 pCellProps
->Insert( PROP_BOTTOM_BORDER
, aHorizProp
, false );
242 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
244 void lcl_debug_BorderLine(table::BorderLine
& rLine
)
246 dmapper_logger
->startElement("BorderLine");
247 dmapper_logger
->attribute("Color", rLine
.Color
);
248 dmapper_logger
->attribute("InnerLineWidth", rLine
.InnerLineWidth
);
249 dmapper_logger
->attribute("OuterLineWidth", rLine
.OuterLineWidth
);
250 dmapper_logger
->attribute("LineDistance", rLine
.LineDistance
);
251 dmapper_logger
->endElement();
254 void lcl_debug_TableBorder(table::TableBorder
& rBorder
)
256 dmapper_logger
->startElement("TableBorder");
257 lcl_debug_BorderLine(rBorder
.TopLine
);
258 dmapper_logger
->attribute("IsTopLineValid", rBorder
.IsTopLineValid
);
259 lcl_debug_BorderLine(rBorder
.BottomLine
);
260 dmapper_logger
->attribute("IsBottomLineValid", rBorder
.IsBottomLineValid
);
261 lcl_debug_BorderLine(rBorder
.LeftLine
);
262 dmapper_logger
->attribute("IsLeftLineValid", rBorder
.IsLeftLineValid
);
263 lcl_debug_BorderLine(rBorder
.RightLine
);
264 dmapper_logger
->attribute("IsRightLineValid", rBorder
.IsRightLineValid
);
265 lcl_debug_BorderLine(rBorder
.VerticalLine
);
266 dmapper_logger
->attribute("IsVerticalLineValid", rBorder
.IsVerticalLineValid
);
267 lcl_debug_BorderLine(rBorder
.HorizontalLine
);
268 dmapper_logger
->attribute("IsHorizontalLineValid", rBorder
.IsHorizontalLineValid
);
269 dmapper_logger
->attribute("Distance", rBorder
.Distance
);
270 dmapper_logger
->attribute("IsDistanceValid", rBorder
.IsDistanceValid
);
271 dmapper_logger
->endElement();
277 sal_Int32 nLeftBorderDistance
;
278 sal_Int32 nRightBorderDistance
;
279 sal_Int32 nTopBorderDistance
;
280 sal_Int32 nBottomBorderDistance
;
282 sal_Int32 nNestLevel
;
283 PropertyMapPtr pTableDefaults
;
284 PropertyMapPtr pTableBorders
;
285 TableStyleSheetEntry
* pTableStyle
;
286 TablePropertyValues_t aTableProperties
;
289 : nLeftBorderDistance(DEF_BORDER_DIST
)
290 , nRightBorderDistance(DEF_BORDER_DIST
)
291 , nTopBorderDistance(0)
292 , nBottomBorderDistance(0)
295 , pTableDefaults(new PropertyMap
)
296 , pTableBorders(new PropertyMap
)
306 bool lcl_extractTableBorderProperty(PropertyMapPtr pTableProperties
, const PropertyIds nId
, TableInfo
& rInfo
, table::BorderLine2
& rLine
)
308 if (!pTableProperties
)
311 PropertyMap::iterator aTblBorderIter
= pTableProperties
->find(nId
);
312 if( aTblBorderIter
!= pTableProperties
->end() )
314 OSL_VERIFY(aTblBorderIter
->second
.getValue() >>= rLine
);
316 rInfo
.pTableBorders
->Insert( nId
, uno::makeAny( rLine
) );
317 PropertyMap::iterator pIt
= rInfo
.pTableDefaults
->find(nId
);
318 if ( pIt
!= rInfo
.pTableDefaults
->end( ) )
319 rInfo
.pTableDefaults
->erase( pIt
);
329 bool lcl_extractHoriOrient(uno::Sequence
<beans::PropertyValue
>& rFrameProperties
, sal_Int32
& nHoriOrient
)
331 // Shifts the frame left by the given value.
332 for (sal_Int32 i
= 0; i
< rFrameProperties
.getLength(); ++i
)
334 if (rFrameProperties
[i
].Name
== "HoriOrient")
336 nHoriOrient
= rFrameProperties
[i
].Value
.get
<sal_Int32
>();
343 void lcl_DecrementHoriOrientPosition(uno::Sequence
<beans::PropertyValue
>& rFrameProperties
, sal_Int32 nAmount
)
345 // Shifts the frame left by the given value.
346 for (sal_Int32 i
= 0; i
< rFrameProperties
.getLength(); ++i
)
348 beans::PropertyValue
& rPropertyValue
= rFrameProperties
[i
];
349 if (rPropertyValue
.Name
== "HoriOrientPosition")
351 sal_Int32 nValue
= rPropertyValue
.Value
.get
<sal_Int32
>();
353 rPropertyValue
.Value
<<= nValue
;
359 TableStyleSheetEntry
* DomainMapperTableHandler::endTableGetTableStyle(TableInfo
& rInfo
, uno::Sequence
<beans::PropertyValue
>& rFrameProperties
)
361 // will receive the table style if any
362 TableStyleSheetEntry
* pTableStyle
= NULL
;
364 if( m_aTableProperties
.get() )
366 //create properties from the table attributes
367 //...pPropMap->Insert( PROP_LEFT_MARGIN, uno::makeAny( m_nLeftMargin - m_nGapHalf ));
368 //pPropMap->Insert( PROP_HORI_ORIENT, uno::makeAny( text::HoriOrientation::RIGHT ));
369 sal_Int32 nGapHalf
= 0;
370 sal_Int32 nLeftMargin
= 0;
371 sal_Int32 nTableWidth
= 0;
372 sal_Int32 nTableWidthType
= text::SizeType::FIX
;
374 PropertyMap::iterator aTableStyleIter
=
375 m_aTableProperties
->find(META_PROP_TABLE_STYLE_NAME
);
376 uno::Sequence
< beans::PropertyValue
> aGrabBag( 6 );
377 sal_Int32 nGrabBagSize
= 0;
379 if (0 != m_rDMapper_Impl
.getTableManager().getCurrentTableRealPosition())
381 TablePositionHandler
*pTablePositions
= m_rDMapper_Impl
.getTableManager().getCurrentTableRealPosition();
383 uno::Sequence
< beans::PropertyValue
> aGrabBagTS( 10 );
385 aGrabBagTS
[0].Name
= "bottomFromText";
386 aGrabBagTS
[0].Value
= uno::makeAny(pTablePositions
->getBottomFromText() );
388 aGrabBagTS
[1].Name
= "horzAnchor";
389 aGrabBagTS
[1].Value
= uno::makeAny( pTablePositions
->getHorzAnchor() );
391 aGrabBagTS
[2].Name
= "leftFromText";
392 aGrabBagTS
[2].Value
= uno::makeAny( pTablePositions
->getLeftFromText() );
394 aGrabBagTS
[3].Name
= "rightFromText";
395 aGrabBagTS
[3].Value
= uno::makeAny( pTablePositions
->getRightFromText() );
397 aGrabBagTS
[4].Name
= "tblpX";
398 aGrabBagTS
[4].Value
= uno::makeAny( pTablePositions
->getX() );
400 aGrabBagTS
[5].Name
= "tblpXSpec";
401 aGrabBagTS
[5].Value
= uno::makeAny( pTablePositions
->getXSpec() );
403 aGrabBagTS
[6].Name
= "tblpY";
404 aGrabBagTS
[6].Value
= uno::makeAny( pTablePositions
->getY() );
406 aGrabBagTS
[7].Name
= "tblpYSpec";
407 aGrabBagTS
[7].Value
= uno::makeAny( pTablePositions
->getYSpec() );
409 aGrabBagTS
[8].Name
= "topFromText";
410 aGrabBagTS
[8].Value
= uno::makeAny( pTablePositions
->getTopFromText() );
412 aGrabBagTS
[9].Name
= "vertAnchor";
413 aGrabBagTS
[9].Value
= uno::makeAny( pTablePositions
->getVertAnchor() );
415 aGrabBag
[nGrabBagSize
].Name
= "TablePosition";
416 aGrabBag
[nGrabBagSize
].Value
= uno::makeAny( aGrabBagTS
);
420 if(aTableStyleIter
!= m_aTableProperties
->end())
422 // Apply table style properties recursively
423 OUString sTableStyleName
;
424 aTableStyleIter
->second
.getValue() >>= sTableStyleName
;
425 StyleSheetTablePtr pStyleSheetTable
= m_rDMapper_Impl
.GetStyleSheetTable();
426 const StyleSheetEntryPtr pStyleSheet
= pStyleSheetTable
->FindStyleSheetByISTD( sTableStyleName
);
427 pTableStyle
= dynamic_cast<TableStyleSheetEntry
*>( pStyleSheet
.get( ) );
428 m_aTableProperties
->erase( aTableStyleIter
);
430 aGrabBag
[nGrabBagSize
].Name
= "TableStyleName";
431 aGrabBag
[nGrabBagSize
].Value
= uno::makeAny( sTableStyleName
);
436 // First get the style properties, then the table ones
437 PropertyMapPtr
pTableProps( m_aTableProperties
);
438 TablePropertyMapPtr
pEmptyProps( new TablePropertyMap
);
440 m_aTableProperties
= pEmptyProps
;
442 PropertyMapPtr pMergedProperties
= lcl_SearchParentStyleSheetAndMergeProperties(pStyleSheet
, pStyleSheetTable
);
444 table::BorderLine2 aBorderLine
;
445 TableInfo rStyleInfo
;
446 if (lcl_extractTableBorderProperty(pMergedProperties
, PROP_TOP_BORDER
, rStyleInfo
, aBorderLine
))
448 aGrabBag
[nGrabBagSize
].Name
= "TableStyleTopBorder";
449 aGrabBag
[nGrabBagSize
].Value
= uno::makeAny( aBorderLine
);
452 if (lcl_extractTableBorderProperty(pMergedProperties
, PROP_BOTTOM_BORDER
, rStyleInfo
, aBorderLine
))
454 aGrabBag
[nGrabBagSize
].Name
= "TableStyleBottomBorder";
455 aGrabBag
[nGrabBagSize
].Value
= uno::makeAny( aBorderLine
);
458 if (lcl_extractTableBorderProperty(pMergedProperties
, PROP_LEFT_BORDER
, rStyleInfo
, aBorderLine
))
460 aGrabBag
[nGrabBagSize
].Name
= "TableStyleLeftBorder";
461 aGrabBag
[nGrabBagSize
].Value
= uno::makeAny( aBorderLine
);
464 if (lcl_extractTableBorderProperty(pMergedProperties
, PROP_RIGHT_BORDER
, rStyleInfo
, aBorderLine
))
466 aGrabBag
[nGrabBagSize
].Name
= "TableStyleRightBorder";
467 aGrabBag
[nGrabBagSize
].Value
= uno::makeAny( aBorderLine
);
471 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
472 dmapper_logger
->startElement("mergedProps");
473 pMergedProperties
->dumpXml( dmapper_logger
);
474 dmapper_logger
->endElement();
477 m_aTableProperties
->InsertProps(pMergedProperties
);
478 m_aTableProperties
->InsertProps(pTableProps
);
480 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
481 dmapper_logger
->startElement("TableProperties");
482 m_aTableProperties
->dumpXml( dmapper_logger
);
483 dmapper_logger
->endElement();
488 PropertyMap::iterator
const aTblLookIter
=
489 m_aTableProperties
->find(PROP_TBL_LOOK
);
490 if(aTblLookIter
!= m_aTableProperties
->end())
492 aTblLookIter
->second
.getValue() >>= rInfo
.nTblLook
;
493 m_aTableProperties
->erase( aTblLookIter
);
496 // Set the table default attributes for the cells
497 rInfo
.pTableDefaults
->InsertProps(m_aTableProperties
);
499 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
500 dmapper_logger
->startElement("TableDefaults");
501 rInfo
.pTableDefaults
->dumpXml( dmapper_logger
);
502 dmapper_logger
->endElement();
505 if( nGrabBagSize
> 0 )
507 aGrabBag
.realloc( nGrabBagSize
);
508 m_aTableProperties
->Insert( PROP_TABLE_INTEROP_GRAB_BAG
, uno::makeAny( aGrabBag
) );
511 m_aTableProperties
->getValue( TablePropertyMap::GAP_HALF
, nGapHalf
);
512 m_aTableProperties
->getValue( TablePropertyMap::LEFT_MARGIN
, nLeftMargin
);
514 m_aTableProperties
->getValue( TablePropertyMap::CELL_MAR_LEFT
,
515 rInfo
.nLeftBorderDistance
);
516 m_aTableProperties
->getValue( TablePropertyMap::CELL_MAR_RIGHT
,
517 rInfo
.nRightBorderDistance
);
518 m_aTableProperties
->getValue( TablePropertyMap::CELL_MAR_TOP
,
519 rInfo
.nTopBorderDistance
);
520 m_aTableProperties
->getValue( TablePropertyMap::CELL_MAR_BOTTOM
,
521 rInfo
.nBottomBorderDistance
);
523 table::TableBorderDistances aDistances
;
524 aDistances
.IsTopDistanceValid
=
525 aDistances
.IsBottomDistanceValid
=
526 aDistances
.IsLeftDistanceValid
=
527 aDistances
.IsRightDistanceValid
= sal_True
;
528 aDistances
.TopDistance
= static_cast<sal_Int16
>( rInfo
.nTopBorderDistance
);
529 aDistances
.BottomDistance
= static_cast<sal_Int16
>( rInfo
.nBottomBorderDistance
);
530 aDistances
.LeftDistance
= static_cast<sal_Int16
>( rInfo
.nLeftBorderDistance
);
531 aDistances
.RightDistance
= static_cast<sal_Int16
>( rInfo
.nRightBorderDistance
);
533 m_aTableProperties
->Insert( PROP_TABLE_BORDER_DISTANCES
, uno::makeAny( aDistances
) );
535 if (rFrameProperties
.hasElements())
536 lcl_DecrementHoriOrientPosition(rFrameProperties
, rInfo
.nLeftBorderDistance
);
538 // Set table above/bottom spacing to 0.
539 m_aTableProperties
->Insert( PROP_TOP_MARGIN
, uno::makeAny( sal_Int32( 0 ) ) );
540 m_aTableProperties
->Insert( PROP_BOTTOM_MARGIN
, uno::makeAny( sal_Int32( 0 ) ) );
542 //table border settings
543 table::TableBorder aTableBorder
;
544 table::BorderLine2 aBorderLine
, aLeftBorder
;
546 if (lcl_extractTableBorderProperty(m_aTableProperties
, PROP_TOP_BORDER
, rInfo
, aBorderLine
))
548 aTableBorder
.TopLine
= aBorderLine
;
549 aTableBorder
.IsTopLineValid
= sal_True
;
551 if (lcl_extractTableBorderProperty(m_aTableProperties
, PROP_BOTTOM_BORDER
, rInfo
, aBorderLine
))
553 aTableBorder
.BottomLine
= aBorderLine
;
554 aTableBorder
.IsBottomLineValid
= sal_True
;
556 if (lcl_extractTableBorderProperty(m_aTableProperties
, PROP_LEFT_BORDER
, rInfo
, aLeftBorder
))
558 aTableBorder
.LeftLine
= aLeftBorder
;
559 aTableBorder
.IsLeftLineValid
= sal_True
;
560 // Only top level table position depends on border width
561 if (rInfo
.nNestLevel
== 1)
563 if (!rFrameProperties
.hasElements())
564 rInfo
.nLeftBorderDistance
+= aLeftBorder
.LineWidth
* 0.5;
566 lcl_DecrementHoriOrientPosition(rFrameProperties
, aLeftBorder
.LineWidth
* 0.5);
569 if (lcl_extractTableBorderProperty(m_aTableProperties
, PROP_RIGHT_BORDER
, rInfo
, aBorderLine
))
571 aTableBorder
.RightLine
= aBorderLine
;
572 aTableBorder
.IsRightLineValid
= sal_True
;
574 if (lcl_extractTableBorderProperty(m_aTableProperties
, META_PROP_HORIZONTAL_BORDER
, rInfo
, aBorderLine
))
576 aTableBorder
.HorizontalLine
= aBorderLine
;
577 aTableBorder
.IsHorizontalLineValid
= sal_True
;
579 if (lcl_extractTableBorderProperty(m_aTableProperties
, META_PROP_VERTICAL_BORDER
, rInfo
, aBorderLine
))
581 aTableBorder
.VerticalLine
= aBorderLine
;
582 aTableBorder
.IsVerticalLineValid
= sal_True
;
585 aTableBorder
.Distance
= 0;
586 aTableBorder
.IsDistanceValid
= sal_False
;
588 m_aTableProperties
->Insert( PROP_TABLE_BORDER
, uno::makeAny( aTableBorder
) );
590 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
591 lcl_debug_TableBorder(aTableBorder
);
594 // Table position in Office is computed in 2 different ways :
595 // - top level tables: the goal is to have in-cell text starting at table indent pos (tblInd),
596 // so table's position depends on table's cells margin
597 // - nested tables: the goal is to have left-most border starting at table_indent pos
598 if (rInfo
.nNestLevel
> 1)
600 m_aTableProperties
->Insert( PROP_LEFT_MARGIN
, uno::makeAny( nLeftMargin
- nGapHalf
));
604 m_aTableProperties
->Insert( PROP_LEFT_MARGIN
, uno::makeAny( nLeftMargin
- nGapHalf
- rInfo
.nLeftBorderDistance
));
607 m_aTableProperties
->getValue( TablePropertyMap::TABLE_WIDTH
, nTableWidth
);
608 m_aTableProperties
->getValue( TablePropertyMap::TABLE_WIDTH_TYPE
, nTableWidthType
);
609 if( nTableWidthType
== text::SizeType::FIX
)
611 if( nTableWidth
> 0 )
612 m_aTableProperties
->Insert( PROP_WIDTH
, uno::makeAny( nTableWidth
));
616 m_aTableProperties
->Insert( PROP_RELATIVE_WIDTH
, uno::makeAny( sal_Int16( nTableWidth
) ) );
617 m_aTableProperties
->Insert( PROP_IS_WIDTH_RELATIVE
, uno::makeAny( true ) );
620 sal_Int32 nHoriOrient
= text::HoriOrientation::LEFT_AND_WIDTH
;
621 // Fetch Horizontal Orientation in rFrameProperties if not set in m_aTableProperties
622 if ( !m_aTableProperties
->getValue( TablePropertyMap::HORI_ORIENT
, nHoriOrient
) )
623 lcl_extractHoriOrient( rFrameProperties
, nHoriOrient
);
624 m_aTableProperties
->Insert( PROP_HORI_ORIENT
, uno::makeAny( sal_Int16(nHoriOrient
) ) );
625 //fill default value - if not available
626 const PropertyMap::const_iterator aRepeatIter
=
627 m_aTableProperties
->find(PROP_HEADER_ROW_COUNT
);
628 if( aRepeatIter
== m_aTableProperties
->end() )
629 m_aTableProperties
->Insert( PROP_HEADER_ROW_COUNT
, uno::makeAny( (sal_Int32
)0 ));
631 rInfo
.aTableProperties
= m_aTableProperties
->GetPropertyValues();
633 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
634 dmapper_logger
->startElement("debug.tableprops");
635 m_aTableProperties
->dumpXml( dmapper_logger
);
636 dmapper_logger
->endElement();
644 #define CNF_FIRST_ROW 0x800
645 #define CNF_LAST_ROW 0x400
646 #define CNF_FIRST_COLUMN 0x200
647 #define CNF_LAST_COLUMN 0x100
648 #define CNF_ODD_VBAND 0x080
649 #define CNF_EVEN_VBAND 0x040
650 #define CNF_ODD_HBAND 0x020
651 #define CNF_EVEN_HBAND 0x010
652 #define CNF_FIRST_ROW_LAST_COLUMN 0x008
653 #define CNF_FIRST_ROW_FIRST_COLUMN 0x004
654 #define CNF_LAST_ROW_LAST_COLUMN 0x002
655 #define CNF_LAST_ROW_FIRST_COLUMN 0x001
657 CellPropertyValuesSeq_t
DomainMapperTableHandler::endTableGetCellProperties(TableInfo
& rInfo
, std::vector
<HorizontallyMergedCell
>& rMerges
)
659 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
660 dmapper_logger
->startElement("getCellProperties");
663 CellPropertyValuesSeq_t
aCellProperties( m_aCellProperties
.size() );
665 if ( !m_aCellProperties
.size() )
667 #ifdef DEBUG_DOMAINMAPPER
668 dmapper_logger
->endElement();
670 return aCellProperties
;
672 // std::vector< std::vector<PropertyMapPtr> > m_aCellProperties
673 PropertyMapVector2::const_iterator aRowOfCellsIterator
= m_aCellProperties
.begin();
674 PropertyMapVector2::const_iterator aRowOfCellsIteratorEnd
= m_aCellProperties
.end();
675 PropertyMapVector2::const_iterator aLastRowIterator
= m_aCellProperties
.end() - 1;
678 //it's a uno::Sequence< beans::PropertyValues >*
679 RowPropertyValuesSeq_t
* pCellProperties
= aCellProperties
.getArray();
680 PropertyMapVector1::const_iterator aRowIter
= m_aRowProperties
.begin();
681 while( aRowOfCellsIterator
!= aRowOfCellsIteratorEnd
)
683 //aRowOfCellsIterator points to a vector of PropertyMapPtr
684 PropertyMapVector1::const_iterator aCellIterator
= aRowOfCellsIterator
->begin();
685 PropertyMapVector1::const_iterator aCellIteratorEnd
= aRowOfCellsIterator
->end();
687 sal_Int32 nRowStyleMask
= 0;
689 if (aRowOfCellsIterator
==m_aCellProperties
.begin())
691 if(rInfo
.nTblLook
&0x20)
692 nRowStyleMask
|= CNF_FIRST_ROW
; // first row style used
694 else if (aRowOfCellsIterator
==aLastRowIterator
)
696 if(rInfo
.nTblLook
&0x40)
697 nRowStyleMask
|= CNF_LAST_ROW
; // last row style used
699 else if (aRowIter
->get() && aRowIter
->get()->find(PROP_TBL_HEADER
) != aRowIter
->get()->end())
700 nRowStyleMask
|= CNF_FIRST_ROW
; // table header implies first row
701 if(!nRowStyleMask
) // if no row style used yet
703 // banding used only if not first and or last row style used
704 if(!(rInfo
.nTblLook
&0x200))
707 if(rInfo
.nTblLook
&0x20)
710 nRowStyleMask
= CNF_ODD_HBAND
;
712 nRowStyleMask
= CNF_EVEN_HBAND
;
717 pCellProperties
[nRow
].realloc( aRowOfCellsIterator
->size() );
718 beans::PropertyValues
* pSingleCellProperties
= pCellProperties
[nRow
].getArray();
719 while( aCellIterator
!= aCellIteratorEnd
)
721 PropertyMapPtr
pAllCellProps( new PropertyMap
);
723 PropertyMapVector1::const_iterator aLastCellIterator
= aRowOfCellsIterator
->end() - 1;
724 bool bIsEndCol
= aCellIterator
== aLastCellIterator
;
725 bool bIsEndRow
= aRowOfCellsIterator
== aLastRowIterator
;
727 //aCellIterator points to a PropertyMapPtr;
728 if( aCellIterator
->get() )
730 if ( rInfo
.pTableDefaults
->size( ) )
731 pAllCellProps
->InsertProps(rInfo
.pTableDefaults
);
733 sal_Int32 nCellStyleMask
= 0;
734 if (aCellIterator
==aRowOfCellsIterator
->begin())
736 if(rInfo
.nTblLook
&0x80)
737 nCellStyleMask
= CNF_FIRST_COLUMN
; // first col style used
741 if(rInfo
.nTblLook
&0x100)
742 nCellStyleMask
= CNF_LAST_COLUMN
; // last col style used
744 if(!nCellStyleMask
) // if no cell style is used yet
746 if(!(rInfo
.nTblLook
&0x400))
749 if(rInfo
.nTblLook
&0x80)
752 nCellStyleMask
= CNF_ODD_VBAND
;
754 nCellStyleMask
= CNF_EVEN_VBAND
;
757 sal_Int32 nCnfStyleMask
= nCellStyleMask
+ nRowStyleMask
;
758 if(nCnfStyleMask
== CNF_FIRST_COLUMN
+ CNF_FIRST_ROW
)
759 nCnfStyleMask
|= CNF_FIRST_ROW_FIRST_COLUMN
;
760 else if(nCnfStyleMask
== CNF_FIRST_COLUMN
+ CNF_LAST_ROW
)
761 nCnfStyleMask
|= CNF_LAST_ROW_FIRST_COLUMN
;
762 else if(nCnfStyleMask
== CNF_LAST_COLUMN
+ CNF_FIRST_ROW
)
763 nCnfStyleMask
|= CNF_FIRST_ROW_LAST_COLUMN
;
764 else if(nCnfStyleMask
== CNF_LAST_COLUMN
+ CNF_LAST_ROW
)
765 nCnfStyleMask
|= CNF_LAST_ROW_LAST_COLUMN
;
767 if ( rInfo
.pTableStyle
)
769 PropertyMapPtr pStyleProps
= rInfo
.pTableStyle
->GetProperties( nCnfStyleMask
);
770 pAllCellProps
->InsertProps( pStyleProps
);
773 // Remove properties from style/row that aren't allowed in cells
774 PropertyMap::iterator aDefaultRepeatIt
= pAllCellProps
->find(PROP_HEADER_ROW_COUNT
);
775 if ( aDefaultRepeatIt
!= pAllCellProps
->end( ) )
776 pAllCellProps
->erase( aDefaultRepeatIt
);
778 if( m_rDMapper_Impl
.GetIsTableHasDirectFormatting() )
780 // Bug#78883 : direct formatting is applied for table cell data
781 // so we can erase para line spacing property from style.xml
782 aDefaultRepeatIt
= pAllCellProps
->find(PROP_PARA_LINE_SPACING
);
783 if ( aDefaultRepeatIt
!= pAllCellProps
->end( ) )
784 pAllCellProps
->erase( aDefaultRepeatIt
);
785 m_rDMapper_Impl
.SetIsTableHasDirectFormatting(false);
788 aDefaultRepeatIt
= pAllCellProps
->find(PROP_TBL_HEADER
);
789 if ( aDefaultRepeatIt
!= pAllCellProps
->end( ) )
790 pAllCellProps
->erase( aDefaultRepeatIt
);
792 // Then add the cell properties
793 pAllCellProps
->InsertProps(*aCellIterator
);
794 aCellIterator
->get( )->swap( *pAllCellProps
.get( ) );
796 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
797 dmapper_logger
->startElement("cell");
798 dmapper_logger
->attribute("cell", nCell
);
799 dmapper_logger
->attribute("row", nRow
);
802 lcl_computeCellBorders( rInfo
.pTableBorders
, *aCellIterator
, nCell
, nRow
, bIsEndCol
, bIsEndRow
);
804 //now set the default left+right border distance TODO: there's an sprm containing the default distance!
805 const PropertyMap::const_iterator aLeftDistanceIter
=
806 aCellIterator
->get()->find(PROP_LEFT_BORDER_DISTANCE
);
807 if( aLeftDistanceIter
== aCellIterator
->get()->end() )
808 aCellIterator
->get()->Insert( PROP_LEFT_BORDER_DISTANCE
,
809 uno::makeAny(rInfo
.nLeftBorderDistance
) );
810 const PropertyMap::const_iterator aRightDistanceIter
=
811 aCellIterator
->get()->find(PROP_RIGHT_BORDER_DISTANCE
);
812 if( aRightDistanceIter
== aCellIterator
->get()->end() )
813 aCellIterator
->get()->Insert( PROP_RIGHT_BORDER_DISTANCE
,
814 uno::makeAny((sal_Int32
) rInfo
.nRightBorderDistance
) );
816 const PropertyMap::const_iterator aTopDistanceIter
=
817 aCellIterator
->get()->find(PROP_TOP_BORDER_DISTANCE
);
818 if( aTopDistanceIter
== aCellIterator
->get()->end() )
819 aCellIterator
->get()->Insert( PROP_TOP_BORDER_DISTANCE
,
820 uno::makeAny((sal_Int32
) rInfo
.nTopBorderDistance
) );
822 const PropertyMap::const_iterator aBottomDistanceIter
=
823 aCellIterator
->get()->find(PROP_BOTTOM_BORDER_DISTANCE
);
824 if( aBottomDistanceIter
== aCellIterator
->get()->end() )
825 aCellIterator
->get()->Insert( PROP_BOTTOM_BORDER_DISTANCE
,
826 uno::makeAny((sal_Int32
) rInfo
.nBottomBorderDistance
) );
828 // Horizontal merge is not an UNO property, extract that info here to rMerges, and then remove it from the map.
829 const PropertyMap::const_iterator aHorizontalMergeIter
= aCellIterator
->get()->find(PROP_HORIZONTAL_MERGE
);
830 if (aHorizontalMergeIter
!= aCellIterator
->get()->end())
832 if (aHorizontalMergeIter
->second
.getValue().get
<sal_Bool
>())
834 // first cell in a merge
835 HorizontallyMergedCell
aMerge(nRow
, nCell
);
836 rMerges
.push_back(aMerge
);
838 else if (!rMerges
.empty())
840 // resuming an earlier merge
841 HorizontallyMergedCell
& rMerge
= rMerges
.back();
842 rMerge
.m_nLastRow
= nRow
;
843 rMerge
.m_nLastCol
= nCell
;
845 aCellIterator
->get()->erase(PROP_HORIZONTAL_MERGE
);
848 // Cell direction is not an UNO Property, either.
849 const PropertyMap::const_iterator aCellDirectionIter
= aCellIterator
->get()->find(PROP_CELL_DIRECTION
);
850 if (aCellDirectionIter
!= aCellIterator
->get()->end())
852 if (aCellDirectionIter
->second
.getValue().get
<sal_Int32
>() == 3)
854 // btLr, so map ParagraphAdjust_CENTER to VertOrientation::CENTER.
855 uno::Reference
<beans::XPropertySet
> xPropertySet((*m_pTableSeq
)[nRow
][nCell
][0], uno::UNO_QUERY
);
856 if (xPropertySet
->getPropertyValue("ParaAdjust").get
<sal_Int16
>() == style::ParagraphAdjust_CENTER
)
857 aCellIterator
->get()->Insert(PROP_VERT_ORIENT
, uno::makeAny(text::VertOrientation::CENTER
));
859 aCellIterator
->get()->erase(PROP_CELL_DIRECTION
);
862 pSingleCellProperties
[nCell
] = aCellIterator
->get()->GetPropertyValues();
863 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
864 dmapper_logger
->endElement();
870 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
871 //-->debug cell properties
874 const uno::Sequence
< beans::PropertyValues
> aDebugCurrentRow
= aCellProperties
[nRow
];
875 sal_Int32 nDebugCells
= aDebugCurrentRow
.getLength();
877 for( sal_Int32 nDebugCell
= 0; nDebugCell
< nDebugCells
; ++nDebugCell
)
879 const uno::Sequence
< beans::PropertyValue
>& aDebugCellProperties
= aDebugCurrentRow
[nDebugCell
];
880 sal_Int32 nDebugCellProperties
= aDebugCellProperties
.getLength();
881 for( sal_Int32 nDebugProperty
= 0; nDebugProperty
< nDebugCellProperties
; ++nDebugProperty
)
883 const OUString sName
= aDebugCellProperties
[nDebugProperty
].Name
;
885 sNames
+= OUString('-');
887 sNames
+= OUString('\n');
894 ++aRowOfCellsIterator
;
898 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
899 dmapper_logger
->endElement();
902 return aCellProperties
;
905 /// Do all cells in this row have a CellHideMark property?
906 bool lcl_hideMarks(PropertyMapVector1
& rCellProperties
)
908 for (size_t nCell
= 0; nCell
< rCellProperties
.size(); ++nCell
)
909 if (rCellProperties
[nCell
]->find(PROP_CELL_HIDE_MARK
) == rCellProperties
[nCell
]->end())
914 /// Are all cells in this row empty?
915 bool lcl_emptyRow(TableSequence_t
& rTableSeq
, sal_Int32 nRow
)
917 if (nRow
>= rTableSeq
.getLength())
919 SAL_WARN("writerfilter", "m_aCellProperties not in sync with m_pTableSeq?");
923 RowSequence_t rRowSeq
= rTableSeq
[nRow
];
924 if (rRowSeq
.getLength() == 0)
926 SAL_WARN("writerfilter", "m_aCellProperties not in sync with m_pTableSeq?");
930 uno::Reference
<text::XTextRangeCompare
> xTextRangeCompare(rRowSeq
[0][0]->getText(), uno::UNO_QUERY
);
933 for (sal_Int32 nCell
= 0; nCell
< rRowSeq
.getLength(); ++nCell
)
934 // See SwXText::Impl::ConvertCell(), we need to compare the start of
935 // the start and the end of the end. However for our text ranges, only
936 // the starts are set, so compareRegionStarts() does what we need.
937 if (xTextRangeCompare
->compareRegionStarts(rRowSeq
[nCell
][0], rRowSeq
[nCell
][1]) != 0)
940 catch (const lang::IllegalArgumentException
& e
)
942 SAL_WARN("writerfilter", "compareRegionStarts() failed: " << e
.Message
);
948 RowPropertyValuesSeq_t
DomainMapperTableHandler::endTableGetRowProperties()
950 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
951 dmapper_logger
->startElement("getRowProperties");
954 static const int MINLAY
= 23; // sw/inc/swtypes.hxx, minimal possible size of frames.
955 RowPropertyValuesSeq_t
aRowProperties( m_aRowProperties
.size() );
956 PropertyMapVector1::const_iterator aRowIter
= m_aRowProperties
.begin();
957 PropertyMapVector1::const_iterator aRowIterEnd
= m_aRowProperties
.end();
959 while( aRowIter
!= aRowIterEnd
)
961 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
962 dmapper_logger
->startElement("rowProps.row");
964 if( aRowIter
->get() )
966 //set default to 'break across pages"
967 if( aRowIter
->get()->find(PROP_IS_SPLIT_ALLOWED
) == aRowIter
->get()->end())
968 aRowIter
->get()->Insert( PROP_IS_SPLIT_ALLOWED
, uno::makeAny(sal_True
) );
969 // tblHeader is only our property, remove before the property map hits UNO
970 PropertyMap::iterator
const aIter
= aRowIter
->get()->find(PROP_TBL_HEADER
);
971 if (aIter
!= aRowIter
->get()->end())
972 aRowIter
->get()->erase(aIter
);
974 if (lcl_hideMarks(m_aCellProperties
[nRow
]) && lcl_emptyRow(*m_pTableSeq
, nRow
))
976 // We have CellHideMark on all cells, and also all cells are empty:
977 // Set the row height to minimal as Word does.
978 (*aRowIter
)->Insert(PROP_SIZE_TYPE
, uno::makeAny(text::SizeType::FIX
));
979 (*aRowIter
)->Insert(PROP_HEIGHT
, uno::makeAny(static_cast<sal_Int32
>(ConversionHelper::convertTwipToMM100(MINLAY
))));
982 aRowProperties
[nRow
] = (*aRowIter
)->GetPropertyValues();
983 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
984 ((*aRowIter
)->dumpXml( dmapper_logger
));
985 lcl_DumpPropertyValues(dmapper_logger
, aRowProperties
[nRow
]);
990 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
991 dmapper_logger
->endElement();
995 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
996 dmapper_logger
->endElement();
999 return aRowProperties
;
1002 // Apply paragraph property to each paragraph within a cell.
1003 static void lcl_ApplyCellParaProps(uno::Reference
<table::XCell
> xCell
, uno::Any aBottomMargin
)
1005 uno::Reference
<container::XEnumerationAccess
> xEnumerationAccess(xCell
, uno::UNO_QUERY
);
1006 uno::Reference
<container::XEnumeration
> xEnumeration
= xEnumerationAccess
->createEnumeration();
1007 while (xEnumeration
->hasMoreElements())
1009 uno::Reference
<beans::XPropertySet
> xParagraph(xEnumeration
->nextElement(), uno::UNO_QUERY
);
1010 uno::Reference
<beans::XPropertyState
> xPropertyState(xParagraph
, uno::UNO_QUERY
);
1011 // Don't apply in case direct formatting is already present.
1012 // TODO: probably paragraph style has priority over table style here.
1013 if (xPropertyState
.is() && xPropertyState
->getPropertyState("ParaBottomMargin") == beans::PropertyState_DEFAULT_VALUE
)
1014 xParagraph
->setPropertyValue("ParaBottomMargin", aBottomMargin
);
1018 void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel
)
1020 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1021 dmapper_logger
->startElement("tablehandler.endTable");
1024 // If we want to make this table a floating one.
1025 uno::Sequence
<beans::PropertyValue
> aFrameProperties
= m_rDMapper_Impl
.getTableManager().getCurrentTablePosition();
1026 TableInfo aTableInfo
;
1027 aTableInfo
.nNestLevel
= nestedTableLevel
;
1028 aTableInfo
.pTableStyle
= endTableGetTableStyle(aTableInfo
, aFrameProperties
);
1029 // expands to uno::Sequence< Sequence< beans::PropertyValues > >
1031 std::vector
<HorizontallyMergedCell
> aMerges
;
1032 CellPropertyValuesSeq_t aCellProperties
= endTableGetCellProperties(aTableInfo
, aMerges
);
1034 RowPropertyValuesSeq_t aRowProperties
= endTableGetRowProperties();
1036 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1037 lcl_DumpPropertyValueSeq(dmapper_logger
, aRowProperties
);
1040 if (m_pTableSeq
->getLength() > 0)
1042 uno::Reference
<text::XTextRange
> xStart
;
1043 uno::Reference
<text::XTextRange
> xEnd
;
1045 bool bFloating
= aFrameProperties
.hasElements();
1046 // Additional checks: if we can do this.
1047 if (bFloating
&& (*m_pTableSeq
)[0].getLength() > 0 && (*m_pTableSeq
)[0][0].getLength() > 0)
1049 xStart
= (*m_pTableSeq
)[0][0][0];
1050 uno::Sequence
< uno::Sequence
< uno::Reference
<text::XTextRange
> > >& rLastRow
= (*m_pTableSeq
)[m_pTableSeq
->getLength() - 1];
1051 uno::Sequence
< uno::Reference
<text::XTextRange
> >& rLastCell
= rLastRow
[rLastRow
.getLength() - 1];
1052 xEnd
= rLastCell
[1];
1054 uno::Reference
<text::XTextTable
> xTable
;
1059 xTable
= m_xText
->convertToTable(*m_pTableSeq
,
1062 aTableInfo
.aTableProperties
);
1066 m_xTableRange
= xTable
->getAnchor( );
1068 if (!aMerges
.empty())
1070 // Perform horizontal merges in reverse order, so the fact that merging changes the position of cells won't cause a problem for us.
1071 for (std::vector
<HorizontallyMergedCell
>::reverse_iterator it
= aMerges
.rbegin(); it
!= aMerges
.rend(); ++it
)
1073 uno::Reference
<table::XCellRange
> xCellRange(xTable
, uno::UNO_QUERY_THROW
);
1074 uno::Reference
<beans::XPropertySet
> xCell(xCellRange
->getCellByPosition(it
->m_nFirstCol
, it
->m_nFirstRow
), uno::UNO_QUERY_THROW
);
1075 OUString aFirst
= xCell
->getPropertyValue("CellName").get
<OUString
>();
1076 xCell
.set(xCellRange
->getCellByPosition(it
->m_nLastCol
, it
->m_nLastRow
), uno::UNO_QUERY_THROW
);
1077 OUString aLast
= xCell
->getPropertyValue("CellName").get
<OUString
>();
1079 uno::Reference
<text::XTextTableCursor
> xCursor
= xTable
->createCursorByCellName(aFirst
);
1080 xCursor
->gotoCellByName(aLast
, true);
1081 xCursor
->mergeRange();
1086 // OOXML table style may container paragraph properties, apply these now.
1087 for (int i
= 0; i
< aTableInfo
.aTableProperties
.getLength(); ++i
)
1089 if (aTableInfo
.aTableProperties
[i
].Name
== "ParaBottomMargin")
1091 uno::Reference
<table::XCellRange
> xCellRange(xTable
, uno::UNO_QUERY
);
1092 uno::Any aBottomMargin
= aTableInfo
.aTableProperties
[i
].Value
;
1093 sal_Int32 nRows
= aCellProperties
.getLength();
1094 for (sal_Int32 nRow
= 0; nRow
< nRows
; ++nRow
)
1096 const uno::Sequence
< beans::PropertyValues
> aCurrentRow
= aCellProperties
[nRow
];
1097 sal_Int32 nCells
= aCurrentRow
.getLength();
1098 for (sal_Int32 nCell
= 0; nCell
< nCells
; ++nCell
)
1099 lcl_ApplyCellParaProps(xCellRange
->getCellByPosition(nCell
, nRow
), aBottomMargin
);
1106 catch ( const lang::IllegalArgumentException
&e
)
1108 SAL_INFO("writerfilter.dmapper",
1109 "Conversion to table error: " << e
.Message
);
1110 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1111 dmapper_logger
->chars(std::string("failed to import table!"));
1114 catch ( const uno::Exception
&e
)
1116 SAL_INFO("writerfilter.dmapper",
1117 "Exception during table creation: " << e
.Message
);
1120 // If we have a table with a start and an end position, we should make it a floating one.
1121 if (xTable
.is() && xStart
.is() && xEnd
.is())
1123 uno::Reference
<beans::XPropertySet
> xTableProperties(xTable
, uno::UNO_QUERY
);
1124 bool bIsRelative
= false;
1125 xTableProperties
->getPropertyValue("IsWidthRelative") >>= bIsRelative
;
1128 aFrameProperties
.realloc(aFrameProperties
.getLength() + 1);
1129 aFrameProperties
[aFrameProperties
.getLength() - 1].Name
= "Width";
1130 aFrameProperties
[aFrameProperties
.getLength() - 1].Value
= xTableProperties
->getPropertyValue("Width");
1134 aFrameProperties
.realloc(aFrameProperties
.getLength() + 1);
1135 aFrameProperties
[aFrameProperties
.getLength() - 1].Name
= "FrameWidthPercent";
1136 aFrameProperties
[aFrameProperties
.getLength() - 1].Value
= xTableProperties
->getPropertyValue("RelativeWidth");
1138 // Applying the relative width to the frame, needs to have the table width to be 100% of the frame width
1139 xTableProperties
->setPropertyValue("RelativeWidth", uno::makeAny(sal_Int16(100)));
1142 // A non-zero left margin would move the table out of the frame, move the frame itself instead.
1143 xTableProperties
->setPropertyValue("LeftMargin", uno::makeAny(sal_Int32(0)));
1145 // In case the document ends with a table, we're called after
1146 // SectionPropertyMap::CloseSectionGroup(), so we'll have no idea
1147 // about the text area width, nor can fix this by delaying the text
1148 // frame conversion: just do it here.
1149 // Also, when the anchor is within a table, then do it here as well,
1150 // as xStart/xEnd would not point to the start/end at conversion
1152 sal_Int32 nTableWidth
= 0;
1153 m_aTableProperties
->getValue(TablePropertyMap::TABLE_WIDTH
, nTableWidth
);
1154 if (m_rDMapper_Impl
.GetSectionContext() && nestedTableLevel
<= 1)
1155 m_rDMapper_Impl
.m_aPendingFloatingTables
.push_back(FloatingTableInfo(xStart
, xEnd
, aFrameProperties
, nTableWidth
));
1157 m_xText
->convertToTextFrame(xStart
, xEnd
, aFrameProperties
);
1161 m_aTableProperties
.reset();
1162 m_aCellProperties
.clear();
1163 m_aRowProperties
.clear();
1165 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1166 dmapper_logger
->endElement();
1167 dmapper_logger
->endElement();
1171 void DomainMapperTableHandler::startRow(unsigned int nCells
,
1172 TablePropertyMapPtr pProps
)
1174 m_aRowProperties
.push_back( pProps
);
1175 m_aCellProperties
.push_back( PropertyMapVector1() );
1177 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1178 dmapper_logger
->startElement("table.row");
1179 dmapper_logger
->attribute("cells", nCells
);
1181 pProps
->dumpXml(dmapper_logger
);
1184 m_pRowSeq
= RowSequencePointer_t(new RowSequence_t(nCells
));
1188 void DomainMapperTableHandler::endRow()
1190 (*m_pTableSeq
)[m_nRowIndex
] = *m_pRowSeq
;
1193 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1194 dmapper_logger
->endElement();
1198 void DomainMapperTableHandler::startCell(const Handle_t
& start
,
1199 TablePropertyMapPtr pProps
)
1201 sal_uInt32 nRow
= m_aRowProperties
.size();
1202 if ( pProps
.get( ) )
1203 m_aCellProperties
[nRow
- 1].push_back( pProps
);
1206 // Adding an empty cell properties map to be able to get
1207 // the table defaults properties
1208 TablePropertyMapPtr
pEmptyProps( new TablePropertyMap( ) );
1209 m_aCellProperties
[nRow
- 1].push_back( pEmptyProps
);
1212 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1213 dmapper_logger
->startElement("table.cell");
1214 dmapper_logger
->startElement("table.cell.start");
1215 dmapper_logger
->chars(toString(start
));
1216 dmapper_logger
->endElement();
1217 lcl_printProperties( pProps
);
1220 //add a new 'row' of properties
1221 m_pCellSeq
= CellSequencePointer_t(new CellSequence_t(2));
1224 (*m_pCellSeq
)[0] = start
->getStart();
1227 void DomainMapperTableHandler::endCell(const Handle_t
& end
)
1229 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1230 dmapper_logger
->startElement("table.cell.end");
1231 dmapper_logger
->chars(toString(end
));
1232 dmapper_logger
->endElement();
1233 dmapper_logger
->endElement();
1238 (*m_pCellSeq
)[1] = end
->getEnd();
1239 (*m_pRowSeq
)[m_nCellIndex
] = *m_pCellSeq
;
1245 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */