Bump version to 4.3-4
[LibreOffice.git] / writerfilter / source / dmapper / DomainMapperTableHandler.cxx
blobfdf292de3f6375a201dbeaeee049742d2e710ee9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
41 #endif
43 namespace writerfilter {
44 namespace dmapper {
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 )
54 if( pProps.get() )
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;
66 sal_Int32 nColor;
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();
86 #endif
88 DomainMapperTableHandler::DomainMapperTableHandler(TextReference_t xText, DomainMapper_Impl& rDMapper_Impl)
89 : m_xText(xText),
90 m_rDMapper_Impl( rDMapper_Impl ),
91 m_nCellIndex(0),
92 m_nRowIndex(0)
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));
106 m_nRowIndex = 0;
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 );
114 #endif
119 PropertyMapPtr lcl_SearchParentStyleSheetAndMergeProperties(const StyleSheetEntryPtr pStyleSheet, StyleSheetTablePtr pStyleSheetTable)
121 PropertyMapPtr pRet;
123 if (!pStyleSheet)
124 return pRet;
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)
131 return pRet;
133 pRet = lcl_SearchParentStyleSheetAndMergeProperties( pParentStyleSheet, pStyleSheetTable );
135 else
137 pRet.reset( new PropertyMap );
140 if (pRet)
142 pRet->InsertProps(pStyleSheet->pProperties);
145 return pRet;
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( ) );
166 uno::Any aVertProp;
167 if ( !bHasVert )
169 aVerticalIter = pTableBorders->find(META_PROP_VERTICAL_BORDER);
170 bHasVert = ( aVerticalIter != pTableBorders->end( ) );
171 if ( bHasVert )
172 aVertProp = aVerticalIter->second.getValue();
174 else
176 aVertProp = aVerticalIter->second.getValue();
177 pCellProps->erase( aVerticalIter );
180 bool bHasHoriz = ( aHorizontalIter != pCellProps->end( ) );
181 uno::Any aHorizProp;
182 if ( !bHasHoriz )
184 aHorizontalIter = pTableBorders->find(META_PROP_HORIZONTAL_BORDER);
185 bHasHoriz = ( aHorizontalIter != pTableBorders->end( ) );
186 if ( bHasHoriz )
187 aHorizProp = aHorizontalIter->second.getValue();
189 else
191 aHorizProp = aHorizontalIter->second.getValue();
192 pCellProps->erase( aHorizontalIter );
195 if ( nCell == 0 )
197 lcl_mergeBorder( PROP_LEFT_BORDER, pTableBorders, pCellProps );
198 if ( bHasVert )
199 pCellProps->Insert( PROP_RIGHT_BORDER, aVertProp, false );
202 if ( bIsEndCol )
204 lcl_mergeBorder( PROP_RIGHT_BORDER, pTableBorders, pCellProps );
205 if ( bHasVert )
206 pCellProps->Insert( PROP_LEFT_BORDER, aVertProp, false );
209 if ( nCell > 0 && !bIsEndCol )
211 if ( bHasVert )
213 pCellProps->Insert( PROP_RIGHT_BORDER, aVertProp, false );
214 pCellProps->Insert( PROP_LEFT_BORDER, aVertProp, false );
218 if ( nRow == 0 )
220 lcl_mergeBorder( PROP_TOP_BORDER, pTableBorders, pCellProps );
221 if ( bHasHoriz )
222 pCellProps->Insert( PROP_BOTTOM_BORDER, aHorizProp, false );
225 if ( bIsEndRow )
227 lcl_mergeBorder( PROP_BOTTOM_BORDER, pTableBorders, pCellProps );
228 if ( bHasHoriz )
229 pCellProps->Insert( PROP_TOP_BORDER, aHorizProp, false );
232 if ( nRow > 0 && !bIsEndRow )
234 if ( bHasHoriz )
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();
273 #endif
275 struct TableInfo
277 sal_Int32 nLeftBorderDistance;
278 sal_Int32 nRightBorderDistance;
279 sal_Int32 nTopBorderDistance;
280 sal_Int32 nBottomBorderDistance;
281 sal_Int32 nTblLook;
282 sal_Int32 nNestLevel;
283 PropertyMapPtr pTableDefaults;
284 PropertyMapPtr pTableBorders;
285 TableStyleSheetEntry* pTableStyle;
286 TablePropertyValues_t aTableProperties;
288 TableInfo()
289 : nLeftBorderDistance(DEF_BORDER_DIST)
290 , nRightBorderDistance(DEF_BORDER_DIST)
291 , nTopBorderDistance(0)
292 , nBottomBorderDistance(0)
293 , nTblLook(0x4a0)
294 , nNestLevel(0)
295 , pTableDefaults(new PropertyMap)
296 , pTableBorders(new PropertyMap)
297 , pTableStyle(NULL)
303 namespace
306 bool lcl_extractTableBorderProperty(PropertyMapPtr pTableProperties, const PropertyIds nId, TableInfo& rInfo, table::BorderLine2& rLine)
308 if (!pTableProperties)
309 return false;
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 );
321 return true;
324 return false;
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>();
337 return true;
340 return false;
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>();
352 nValue -= nAmount;
353 rPropertyValue.Value <<= nValue;
354 return;
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 );
417 nGrabBagSize++;
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 );
432 nGrabBagSize++;
434 if( pStyleSheet )
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 );
450 nGrabBagSize++;
452 if (lcl_extractTableBorderProperty(pMergedProperties, PROP_BOTTOM_BORDER, rStyleInfo, aBorderLine))
454 aGrabBag[nGrabBagSize].Name = "TableStyleBottomBorder";
455 aGrabBag[nGrabBagSize].Value = uno::makeAny( aBorderLine );
456 nGrabBagSize++;
458 if (lcl_extractTableBorderProperty(pMergedProperties, PROP_LEFT_BORDER, rStyleInfo, aBorderLine))
460 aGrabBag[nGrabBagSize].Name = "TableStyleLeftBorder";
461 aGrabBag[nGrabBagSize].Value = uno::makeAny( aBorderLine );
462 nGrabBagSize++;
464 if (lcl_extractTableBorderProperty(pMergedProperties, PROP_RIGHT_BORDER, rStyleInfo, aBorderLine))
466 aGrabBag[nGrabBagSize].Name = "TableStyleRightBorder";
467 aGrabBag[nGrabBagSize].Value = uno::makeAny( aBorderLine );
468 nGrabBagSize++;
471 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
472 dmapper_logger->startElement("mergedProps");
473 pMergedProperties->dumpXml( dmapper_logger );
474 dmapper_logger->endElement();
475 #endif
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();
484 #endif
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();
503 #endif
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;
565 else
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);
592 #endif
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 ));
602 else
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 ));
614 else
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();
637 #endif
641 return pTableStyle;
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");
661 #endif
663 CellPropertyValuesSeq_t aCellProperties( m_aCellProperties.size() );
665 if ( !m_aCellProperties.size() )
667 #ifdef DEBUG_DOMAINMAPPER
668 dmapper_logger->endElement();
669 #endif
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;
676 sal_Int32 nRow = 0;
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))
705 { // hbanding used
706 int n = nRow + 1;
707 if(rInfo.nTblLook&0x20)
708 n++;
709 if(n & 1)
710 nRowStyleMask = CNF_ODD_HBAND;
711 else
712 nRowStyleMask = CNF_EVEN_HBAND;
716 sal_Int32 nCell = 0;
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
739 else if (bIsEndCol)
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))
747 { // vbanding used
748 int n = nCell + 1;
749 if(rInfo.nTblLook&0x80)
750 n++;
751 if(n & 1)
752 nCellStyleMask = CNF_ODD_VBAND;
753 else
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);
800 #endif
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();
865 #endif
867 ++nCell;
868 ++aCellIterator;
870 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
871 //-->debug cell properties
873 OUString sNames;
874 const uno::Sequence< beans::PropertyValues > aDebugCurrentRow = aCellProperties[nRow];
875 sal_Int32 nDebugCells = aDebugCurrentRow.getLength();
876 (void) nDebugCells;
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;
884 sNames += sName;
885 sNames += OUString('-');
887 sNames += OUString('\n');
889 (void)sNames;
891 //--<
892 #endif
893 ++nRow;
894 ++aRowOfCellsIterator;
895 ++aRowIter;
898 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
899 dmapper_logger->endElement();
900 #endif
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())
910 return false;
911 return true;
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?");
920 return false;
923 RowSequence_t rRowSeq = rTableSeq[nRow];
924 if (rRowSeq.getLength() == 0)
926 SAL_WARN("writerfilter", "m_aCellProperties not in sync with m_pTableSeq?");
927 return false;
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)
938 return false;
940 catch (const lang::IllegalArgumentException& e)
942 SAL_WARN("writerfilter", "compareRegionStarts() failed: " << e.Message);
943 return false;
945 return true;
948 RowPropertyValuesSeq_t DomainMapperTableHandler::endTableGetRowProperties()
950 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
951 dmapper_logger->startElement("getRowProperties");
952 #endif
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();
958 sal_Int32 nRow = 0;
959 while( aRowIter != aRowIterEnd )
961 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
962 dmapper_logger->startElement("rowProps.row");
963 #endif
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]);
986 #endif
988 ++nRow;
989 ++aRowIter;
990 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
991 dmapper_logger->endElement();
992 #endif
995 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
996 dmapper_logger->endElement();
997 #endif
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");
1022 #endif
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);
1038 #endif
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;
1057 if (m_xText.is())
1059 xTable = m_xText->convertToTable(*m_pTableSeq,
1060 aCellProperties,
1061 aRowProperties,
1062 aTableInfo.aTableProperties);
1064 if (xTable.is())
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);
1101 break;
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!"));
1112 #endif
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;
1126 if (!bIsRelative)
1128 aFrameProperties.realloc(aFrameProperties.getLength() + 1);
1129 aFrameProperties[aFrameProperties.getLength() - 1].Name = "Width";
1130 aFrameProperties[aFrameProperties.getLength() - 1].Value = xTableProperties->getPropertyValue("Width");
1132 else
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
1151 // time anyway.
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));
1156 else
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();
1168 #endif
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);
1180 if (pProps != NULL)
1181 pProps->dumpXml(dmapper_logger);
1182 #endif
1184 m_pRowSeq = RowSequencePointer_t(new RowSequence_t(nCells));
1185 m_nCellIndex = 0;
1188 void DomainMapperTableHandler::endRow()
1190 (*m_pTableSeq)[m_nRowIndex] = *m_pRowSeq;
1191 ++m_nRowIndex;
1192 m_nCellIndex = 0;
1193 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1194 dmapper_logger->endElement();
1195 #endif
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 );
1204 else
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 );
1218 #endif
1220 //add a new 'row' of properties
1221 m_pCellSeq = CellSequencePointer_t(new CellSequence_t(2));
1222 if (!start.get())
1223 return;
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();
1234 #endif
1236 if (!end.get())
1237 return;
1238 (*m_pCellSeq)[1] = end->getEnd();
1239 (*m_pRowSeq)[m_nCellIndex] = *m_pCellSeq;
1240 ++m_nCellIndex;
1245 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */