Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
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 <dmapperLoggers.hxx>
32 :
33 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
34 : #include <PropertyMapHelper.hxx>
35 : #include <rtl/ustring.hxx>
36 : #endif
37 :
38 : namespace writerfilter {
39 : namespace dmapper {
40 :
41 : using namespace ::com::sun::star;
42 : using namespace ::std;
43 :
44 : #define DEF_BORDER_DIST 190 //0,19cm
45 :
46 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
47 : static void lcl_printProperties( PropertyMapPtr pProps )
48 : {
49 : if( pProps.get() )
50 : {
51 : dmapper_logger->startElement("properties");
52 :
53 : PropertyMap::const_iterator aMapIter = pProps->begin();
54 : PropertyMap::const_iterator aEndIter = pProps->end();
55 : PropertyNameSupplier& rPropSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
56 : for( ; aMapIter != aEndIter; ++aMapIter )
57 : {
58 : SAL_INFO("writerfilter", rPropSupplier.GetName(aMapIter->first));
59 :
60 : table::BorderLine2 aLine;
61 : sal_Int32 nColor;
62 : if ( aMapIter->second.getValue() >>= aLine )
63 : {
64 : dmapper_logger->startElement("borderline");
65 : dmapper_logger->attribute("color", aLine.Color);
66 : dmapper_logger->attribute("inner", aLine.InnerLineWidth);
67 : dmapper_logger->attribute("outer", aLine.OuterLineWidth);
68 : dmapper_logger->endElement();
69 : }
70 : else if ( aMapIter->second.getValue() >>= nColor )
71 : {
72 : dmapper_logger->startElement("color");
73 : dmapper_logger->attribute("number", nColor);
74 : dmapper_logger->endElement();
75 : }
76 : }
77 :
78 : dmapper_logger->endElement();
79 : }
80 : }
81 : #endif
82 :
83 1191 : DomainMapperTableHandler::DomainMapperTableHandler(TextReference_t xText, DomainMapper_Impl& rDMapper_Impl)
84 : : m_xText(xText),
85 : m_rDMapper_Impl( rDMapper_Impl ),
86 : m_nCellIndex(0),
87 1191 : m_nRowIndex(0)
88 : {
89 1191 : }
90 :
91 2382 : DomainMapperTableHandler::~DomainMapperTableHandler()
92 : {
93 2382 : }
94 :
95 3394 : void DomainMapperTableHandler::startTable(unsigned int nRows,
96 : unsigned int /*nDepth*/,
97 : TablePropertyMapPtr pProps)
98 : {
99 3394 : m_aTableProperties = pProps;
100 3394 : m_pTableSeq = TableSequencePointer_t(new TableSequence_t(nRows));
101 3394 : m_nRowIndex = 0;
102 :
103 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
104 : dmapper_logger->startElement("tablehandler.table");
105 : dmapper_logger->attribute("rows", nRows);
106 :
107 : if (pProps.get() != NULL)
108 : pProps->dumpXml( dmapper_logger );
109 : #endif
110 3394 : }
111 :
112 :
113 :
114 274 : PropertyMapPtr lcl_SearchParentStyleSheetAndMergeProperties(const StyleSheetEntryPtr pStyleSheet, StyleSheetTablePtr pStyleSheetTable)
115 : {
116 274 : PropertyMapPtr pRet;
117 274 : if(!pStyleSheet->sBaseStyleIdentifier.isEmpty())
118 : {
119 137 : const StyleSheetEntryPtr pParentStyleSheet = pStyleSheetTable->FindStyleSheetByISTD( pStyleSheet->sBaseStyleIdentifier );
120 137 : pRet = lcl_SearchParentStyleSheetAndMergeProperties( pParentStyleSheet, pStyleSheetTable );
121 : }
122 : else
123 : {
124 137 : pRet.reset( new PropertyMap );
125 : }
126 :
127 274 : pRet->InsertProps(pStyleSheet->pProperties);
128 :
129 274 : return pRet;
130 : }
131 :
132 6450 : void lcl_mergeBorder( PropertyIds nId, PropertyMapPtr pOrig, PropertyMapPtr pDest )
133 : {
134 6450 : PropertyMap::iterator pOrigIt = pOrig->find(nId);
135 :
136 6450 : if ( pOrigIt != pOrig->end( ) )
137 : {
138 4519 : pDest->Insert( nId, pOrigIt->second.getValue(), false );
139 : }
140 6450 : }
141 :
142 6720 : void lcl_computeCellBorders( PropertyMapPtr pTableBorders, PropertyMapPtr pCellProps,
143 : sal_Int32 nCell, sal_Int32 nRow, bool bIsEndCol, bool bIsEndRow )
144 : {
145 6720 : PropertyMap::iterator aVerticalIter = pCellProps->find(META_PROP_VERTICAL_BORDER);
146 6720 : PropertyMap::iterator aHorizontalIter = pCellProps->find(META_PROP_HORIZONTAL_BORDER);
147 :
148 : // Handle the vertical and horizontal borders
149 6720 : bool bHasVert = ( aVerticalIter != pCellProps->end( ) );
150 6720 : uno::Any aVertProp;
151 6720 : if ( !bHasVert )
152 : {
153 5247 : aVerticalIter = pTableBorders->find(META_PROP_VERTICAL_BORDER);
154 5247 : bHasVert = ( aVerticalIter != pTableBorders->end( ) );
155 5247 : if ( bHasVert )
156 3436 : aVertProp = aVerticalIter->second.getValue();
157 : }
158 : else
159 : {
160 1473 : aVertProp = aVerticalIter->second.getValue();
161 1473 : pCellProps->erase( aVerticalIter );
162 : }
163 :
164 6720 : bool bHasHoriz = ( aHorizontalIter != pCellProps->end( ) );
165 13440 : uno::Any aHorizProp;
166 6720 : if ( !bHasHoriz )
167 : {
168 5216 : aHorizontalIter = pTableBorders->find(META_PROP_HORIZONTAL_BORDER);
169 5216 : bHasHoriz = ( aHorizontalIter != pTableBorders->end( ) );
170 5216 : if ( bHasHoriz )
171 3328 : aHorizProp = aHorizontalIter->second.getValue();
172 : }
173 : else
174 : {
175 1504 : aHorizProp = aHorizontalIter->second.getValue();
176 1504 : pCellProps->erase( aHorizontalIter );
177 : }
178 :
179 6720 : if ( nCell == 0 )
180 : {
181 2188 : lcl_mergeBorder( PROP_LEFT_BORDER, pTableBorders, pCellProps );
182 2188 : if ( bHasVert )
183 1602 : pCellProps->Insert( PROP_RIGHT_BORDER, aVertProp, false );
184 : }
185 :
186 6720 : if ( bIsEndCol )
187 : {
188 2188 : lcl_mergeBorder( PROP_RIGHT_BORDER, pTableBorders, pCellProps );
189 2188 : if ( bHasVert )
190 1606 : pCellProps->Insert( PROP_LEFT_BORDER, aVertProp, false );
191 : }
192 :
193 6720 : if ( nCell > 0 && !bIsEndCol )
194 : {
195 2660 : if ( bHasVert )
196 : {
197 1882 : pCellProps->Insert( PROP_RIGHT_BORDER, aVertProp, false );
198 1882 : pCellProps->Insert( PROP_LEFT_BORDER, aVertProp, false );
199 : }
200 : }
201 :
202 6720 : if ( nRow == 0 )
203 : {
204 998 : lcl_mergeBorder( PROP_TOP_BORDER, pTableBorders, pCellProps );
205 998 : if ( bHasHoriz )
206 535 : pCellProps->Insert( PROP_BOTTOM_BORDER, aHorizProp, false );
207 : }
208 :
209 6720 : if ( bIsEndRow )
210 : {
211 1076 : lcl_mergeBorder( PROP_BOTTOM_BORDER, pTableBorders, pCellProps );
212 1076 : if ( bHasHoriz )
213 616 : pCellProps->Insert( PROP_TOP_BORDER, aHorizProp, false );
214 : }
215 :
216 6720 : if ( nRow > 0 && !bIsEndRow )
217 : {
218 5054 : if ( bHasHoriz )
219 : {
220 3841 : pCellProps->Insert( PROP_TOP_BORDER, aHorizProp, false );
221 3841 : pCellProps->Insert( PROP_BOTTOM_BORDER, aHorizProp, false );
222 : }
223 6720 : }
224 6720 : }
225 :
226 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
227 :
228 : void lcl_debug_BorderLine(table::BorderLine & rLine)
229 : {
230 : dmapper_logger->startElement("BorderLine");
231 : dmapper_logger->attribute("Color", rLine.Color);
232 : dmapper_logger->attribute("InnerLineWidth", rLine.InnerLineWidth);
233 : dmapper_logger->attribute("OuterLineWidth", rLine.OuterLineWidth);
234 : dmapper_logger->attribute("LineDistance", rLine.LineDistance);
235 : dmapper_logger->endElement();
236 : }
237 :
238 : void lcl_debug_TableBorder(table::TableBorder & rBorder)
239 : {
240 : dmapper_logger->startElement("TableBorder");
241 : lcl_debug_BorderLine(rBorder.TopLine);
242 : dmapper_logger->attribute("IsTopLineValid", rBorder.IsTopLineValid);
243 : lcl_debug_BorderLine(rBorder.BottomLine);
244 : dmapper_logger->attribute("IsBottomLineValid", rBorder.IsBottomLineValid);
245 : lcl_debug_BorderLine(rBorder.LeftLine);
246 : dmapper_logger->attribute("IsLeftLineValid", rBorder.IsLeftLineValid);
247 : lcl_debug_BorderLine(rBorder.RightLine);
248 : dmapper_logger->attribute("IsRightLineValid", rBorder.IsRightLineValid);
249 : lcl_debug_BorderLine(rBorder.VerticalLine);
250 : dmapper_logger->attribute("IsVerticalLineValid", rBorder.IsVerticalLineValid);
251 : lcl_debug_BorderLine(rBorder.HorizontalLine);
252 : dmapper_logger->attribute("IsHorizontalLineValid", rBorder.IsHorizontalLineValid);
253 : dmapper_logger->attribute("Distance", rBorder.Distance);
254 : dmapper_logger->attribute("IsDistanceValid", rBorder.IsDistanceValid);
255 : dmapper_logger->endElement();
256 : }
257 : #endif
258 :
259 3531 : struct TableInfo
260 : {
261 : sal_Int32 nLeftBorderDistance;
262 : sal_Int32 nRightBorderDistance;
263 : sal_Int32 nTopBorderDistance;
264 : sal_Int32 nBottomBorderDistance;
265 : sal_Int32 nTblLook;
266 : sal_Int32 nNestLevel;
267 : PropertyMapPtr pTableDefaults;
268 : PropertyMapPtr pTableBorders;
269 : TableStyleSheetEntry* pTableStyle;
270 : TablePropertyValues_t aTableProperties;
271 :
272 3531 : TableInfo()
273 : : nLeftBorderDistance(DEF_BORDER_DIST)
274 : , nRightBorderDistance(DEF_BORDER_DIST)
275 : , nTopBorderDistance(0)
276 : , nBottomBorderDistance(0)
277 : , nTblLook(0x4a0)
278 : , nNestLevel(0)
279 3531 : , pTableDefaults(new PropertyMap)
280 3531 : , pTableBorders(new PropertyMap)
281 10593 : , pTableStyle(NULL)
282 : {
283 3531 : }
284 :
285 : };
286 :
287 : namespace
288 : {
289 :
290 2924 : bool lcl_extractTableBorderProperty(PropertyMapPtr pTableProperties, const PropertyIds nId, TableInfo& rInfo, table::BorderLine2& rLine)
291 : {
292 2924 : PropertyMap::iterator aTblBorderIter = pTableProperties->find(nId);
293 2924 : if( aTblBorderIter != pTableProperties->end() )
294 : {
295 1719 : OSL_VERIFY(aTblBorderIter->second.getValue() >>= rLine);
296 :
297 1719 : rInfo.pTableBorders->Insert( nId, uno::makeAny( rLine ) );
298 1719 : PropertyMap::iterator pIt = rInfo.pTableDefaults->find(nId);
299 1719 : if ( pIt != rInfo.pTableDefaults->end( ) )
300 1219 : rInfo.pTableDefaults->erase( pIt );
301 :
302 1719 : return true;
303 : }
304 :
305 1205 : return false;
306 : }
307 :
308 : }
309 :
310 53 : void lcl_DecrementHoriOrientPosition(uno::Sequence<beans::PropertyValue>& rFrameProperties, sal_Int32 nAmount)
311 : {
312 : // Shifts the frame left by the given value.
313 795 : for (sal_Int32 i = 0; i < rFrameProperties.getLength(); ++i)
314 : {
315 795 : beans::PropertyValue& rPropertyValue = rFrameProperties[i];
316 795 : if (rPropertyValue.Name == "HoriOrientPosition")
317 : {
318 53 : sal_Int32 nValue = rPropertyValue.Value.get<sal_Int32>();
319 53 : nValue -= nAmount;
320 53 : rPropertyValue.Value <<= nValue;
321 106 : return;
322 : }
323 : }
324 : }
325 :
326 3394 : TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo & rInfo, uno::Sequence<beans::PropertyValue>& rFrameProperties)
327 : {
328 : // will receive the table style if any
329 3394 : TableStyleSheetEntry* pTableStyle = NULL;
330 :
331 3394 : if( m_aTableProperties.get() )
332 : {
333 : //create properties from the table attributes
334 : //...pPropMap->Insert( PROP_LEFT_MARGIN, uno::makeAny( m_nLeftMargin - m_nGapHalf ));
335 : //pPropMap->Insert( PROP_HORI_ORIENT, uno::makeAny( text::HoriOrientation::RIGHT ));
336 396 : sal_Int32 nGapHalf = 0;
337 396 : sal_Int32 nLeftMargin = 0;
338 396 : sal_Int32 nTableWidth = 0;
339 396 : sal_Int32 nTableWidthType = text::SizeType::FIX;
340 :
341 : PropertyMap::iterator aTableStyleIter =
342 396 : m_aTableProperties->find(META_PROP_TABLE_STYLE_NAME);
343 396 : uno::Sequence< beans::PropertyValue > aGrabBag( 5 );
344 396 : sal_Int32 nGrabBagSize = 0;
345 396 : if(aTableStyleIter != m_aTableProperties->end())
346 : {
347 : // Apply table style properties recursively
348 140 : OUString sTableStyleName;
349 140 : aTableStyleIter->second.getValue() >>= sTableStyleName;
350 280 : StyleSheetTablePtr pStyleSheetTable = m_rDMapper_Impl.GetStyleSheetTable();
351 280 : const StyleSheetEntryPtr pStyleSheet = pStyleSheetTable->FindStyleSheetByISTD( sTableStyleName );
352 140 : pTableStyle = dynamic_cast<TableStyleSheetEntry*>( pStyleSheet.get( ) );
353 140 : m_aTableProperties->erase( aTableStyleIter );
354 :
355 140 : aGrabBag[0].Name = "TableStyleName";
356 140 : aGrabBag[0].Value = uno::makeAny( sTableStyleName );
357 140 : nGrabBagSize++;
358 :
359 140 : if( pStyleSheet )
360 : {
361 : // First get the style properties, then the table ones
362 137 : PropertyMapPtr pTableProps( m_aTableProperties );
363 274 : TablePropertyMapPtr pEmptyProps( new TablePropertyMap );
364 :
365 137 : m_aTableProperties = pEmptyProps;
366 :
367 274 : PropertyMapPtr pMergedProperties = lcl_SearchParentStyleSheetAndMergeProperties(pStyleSheet, pStyleSheetTable);
368 :
369 137 : table::BorderLine2 aBorderLine;
370 274 : TableInfo rStyleInfo;
371 137 : if (lcl_extractTableBorderProperty(pMergedProperties, PROP_TOP_BORDER, rStyleInfo, aBorderLine))
372 : {
373 128 : aGrabBag[1].Name = "TableStyleTopBorder";
374 128 : aGrabBag[1].Value = uno::makeAny( aBorderLine );
375 128 : nGrabBagSize++;
376 : }
377 137 : if (lcl_extractTableBorderProperty(pMergedProperties, PROP_BOTTOM_BORDER, rStyleInfo, aBorderLine))
378 : {
379 128 : aGrabBag[2].Name = "TableStyleBottomBorder";
380 128 : aGrabBag[2].Value = uno::makeAny( aBorderLine );
381 128 : nGrabBagSize++;
382 : }
383 137 : if (lcl_extractTableBorderProperty(pMergedProperties, PROP_LEFT_BORDER, rStyleInfo, aBorderLine))
384 : {
385 122 : aGrabBag[3].Name = "TableStyleLeftBorder";
386 122 : aGrabBag[3].Value = uno::makeAny( aBorderLine );
387 122 : nGrabBagSize++;
388 : }
389 137 : if (lcl_extractTableBorderProperty(pMergedProperties, PROP_RIGHT_BORDER, rStyleInfo, aBorderLine))
390 : {
391 122 : aGrabBag[4].Name = "TableStyleRightBorder";
392 122 : aGrabBag[4].Value = uno::makeAny( aBorderLine );
393 122 : nGrabBagSize++;
394 : }
395 :
396 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
397 : dmapper_logger->startElement("mergedProps");
398 : pMergedProperties->dumpXml( dmapper_logger );
399 : dmapper_logger->endElement();
400 : #endif
401 :
402 137 : m_aTableProperties->InsertProps(pMergedProperties);
403 274 : m_aTableProperties->InsertProps(pTableProps);
404 :
405 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
406 : dmapper_logger->startElement("TableProperties");
407 : m_aTableProperties->dumpXml( dmapper_logger );
408 : dmapper_logger->endElement();
409 : #endif
410 140 : }
411 : }
412 :
413 : PropertyMap::iterator const aTblLookIter =
414 396 : m_aTableProperties->find(PROP_TBL_LOOK);
415 396 : if(aTblLookIter != m_aTableProperties->end())
416 : {
417 236 : aTblLookIter->second.getValue() >>= rInfo.nTblLook;
418 236 : m_aTableProperties->erase( aTblLookIter );
419 : }
420 :
421 : // Set the table default attributes for the cells
422 396 : rInfo.pTableDefaults->InsertProps(m_aTableProperties);
423 :
424 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
425 : dmapper_logger->startElement("TableDefaults");
426 : rInfo.pTableDefaults->dumpXml( dmapper_logger );
427 : dmapper_logger->endElement();
428 : #endif
429 :
430 396 : if( nGrabBagSize > 0 )
431 : {
432 140 : aGrabBag.realloc( nGrabBagSize );
433 140 : m_aTableProperties->Insert( PROP_TABLE_INTEROP_GRAB_BAG, uno::makeAny( aGrabBag ) );
434 : }
435 :
436 396 : m_aTableProperties->getValue( TablePropertyMap::GAP_HALF, nGapHalf );
437 396 : m_aTableProperties->getValue( TablePropertyMap::LEFT_MARGIN, nLeftMargin );
438 :
439 : m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_LEFT,
440 396 : rInfo.nLeftBorderDistance );
441 : m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_RIGHT,
442 396 : rInfo.nRightBorderDistance );
443 : m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_TOP,
444 396 : rInfo.nTopBorderDistance );
445 : m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_BOTTOM,
446 396 : rInfo.nBottomBorderDistance );
447 :
448 396 : table::TableBorderDistances aDistances;
449 : aDistances.IsTopDistanceValid =
450 : aDistances.IsBottomDistanceValid =
451 : aDistances.IsLeftDistanceValid =
452 396 : aDistances.IsRightDistanceValid = sal_True;
453 396 : aDistances.TopDistance = static_cast<sal_Int16>( rInfo.nTopBorderDistance );
454 396 : aDistances.BottomDistance = static_cast<sal_Int16>( rInfo.nBottomBorderDistance );
455 396 : aDistances.LeftDistance = static_cast<sal_Int16>( rInfo.nLeftBorderDistance );
456 396 : aDistances.RightDistance = static_cast<sal_Int16>( rInfo.nRightBorderDistance );
457 :
458 396 : m_aTableProperties->Insert( PROP_TABLE_BORDER_DISTANCES, uno::makeAny( aDistances ) );
459 :
460 396 : if (rFrameProperties.hasElements())
461 31 : lcl_DecrementHoriOrientPosition(rFrameProperties, rInfo.nLeftBorderDistance);
462 :
463 : // Set table above/bottom spacing to 0.
464 396 : m_aTableProperties->Insert( PROP_TOP_MARGIN, uno::makeAny( sal_Int32( 0 ) ) );
465 396 : m_aTableProperties->Insert( PROP_BOTTOM_MARGIN, uno::makeAny( sal_Int32( 0 ) ) );
466 :
467 : //table border settings
468 396 : table::TableBorder aTableBorder;
469 396 : table::BorderLine2 aBorderLine, aLeftBorder;
470 :
471 396 : if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_TOP_BORDER, rInfo, aBorderLine))
472 : {
473 211 : aTableBorder.TopLine = aBorderLine;
474 211 : aTableBorder.IsTopLineValid = sal_True;
475 : }
476 396 : if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_BOTTOM_BORDER, rInfo, aBorderLine))
477 : {
478 209 : aTableBorder.BottomLine = aBorderLine;
479 209 : aTableBorder.IsBottomLineValid = sal_True;
480 : }
481 396 : if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_LEFT_BORDER, rInfo, aLeftBorder))
482 : {
483 205 : aTableBorder.LeftLine = aLeftBorder;
484 205 : aTableBorder.IsLeftLineValid = sal_True;
485 : // Only top level table position depends on border width
486 205 : if (rInfo.nNestLevel == 1)
487 : {
488 194 : if (!rFrameProperties.hasElements())
489 172 : rInfo.nLeftBorderDistance += aLeftBorder.LineWidth * 0.5;
490 : else
491 22 : lcl_DecrementHoriOrientPosition(rFrameProperties, aLeftBorder.LineWidth * 0.5);
492 : }
493 : }
494 396 : if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_RIGHT_BORDER, rInfo, aBorderLine))
495 : {
496 202 : aTableBorder.RightLine = aBorderLine;
497 202 : aTableBorder.IsRightLineValid = sal_True;
498 : }
499 396 : if (lcl_extractTableBorderProperty(m_aTableProperties, META_PROP_HORIZONTAL_BORDER, rInfo, aBorderLine))
500 : {
501 194 : aTableBorder.HorizontalLine = aBorderLine;
502 194 : aTableBorder.IsHorizontalLineValid = sal_True;
503 : }
504 396 : if (lcl_extractTableBorderProperty(m_aTableProperties, META_PROP_VERTICAL_BORDER, rInfo, aBorderLine))
505 : {
506 198 : aTableBorder.VerticalLine = aBorderLine;
507 198 : aTableBorder.IsVerticalLineValid = sal_True;
508 : }
509 :
510 396 : aTableBorder.Distance = 0;
511 396 : aTableBorder.IsDistanceValid = sal_False;
512 :
513 396 : m_aTableProperties->Insert( PROP_TABLE_BORDER, uno::makeAny( aTableBorder ) );
514 :
515 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
516 : lcl_debug_TableBorder(aTableBorder);
517 : #endif
518 :
519 : // Table position in Office is computed in 2 different ways :
520 : // - top level tables: the goal is to have in-cell text starting at table indent pos (tblInd),
521 : // so table's position depends on table's cells margin
522 : // - nested tables: the goal is to have left-most border starting at table_indent pos
523 396 : if (rInfo.nNestLevel > 1)
524 : {
525 32 : m_aTableProperties->Insert( PROP_LEFT_MARGIN, uno::makeAny( nLeftMargin - nGapHalf ));
526 : }
527 : else
528 : {
529 364 : m_aTableProperties->Insert( PROP_LEFT_MARGIN, uno::makeAny( nLeftMargin - nGapHalf - rInfo.nLeftBorderDistance ));
530 : }
531 :
532 396 : m_aTableProperties->getValue( TablePropertyMap::TABLE_WIDTH, nTableWidth );
533 396 : m_aTableProperties->getValue( TablePropertyMap::TABLE_WIDTH_TYPE, nTableWidthType );
534 396 : if( nTableWidthType == text::SizeType::FIX )
535 : {
536 370 : if( nTableWidth > 0 )
537 362 : m_aTableProperties->Insert( PROP_WIDTH, uno::makeAny( nTableWidth ));
538 : }
539 : else
540 : {
541 26 : m_aTableProperties->Insert( PROP_RELATIVE_WIDTH, uno::makeAny( sal_Int16( nTableWidth ) ) );
542 26 : m_aTableProperties->Insert( PROP_IS_WIDTH_RELATIVE, uno::makeAny( sal_Bool( sal_True ) ) );
543 : }
544 :
545 396 : sal_Int32 nHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH;
546 396 : m_aTableProperties->getValue( TablePropertyMap::HORI_ORIENT, nHoriOrient ) ;
547 396 : m_aTableProperties->Insert( PROP_HORI_ORIENT, uno::makeAny( sal_Int16(nHoriOrient) ) );
548 :
549 : //fill default value - if not available
550 : const PropertyMap::const_iterator aRepeatIter =
551 396 : m_aTableProperties->find(PROP_HEADER_ROW_COUNT);
552 396 : if( aRepeatIter == m_aTableProperties->end() )
553 390 : m_aTableProperties->Insert( PROP_HEADER_ROW_COUNT, uno::makeAny( (sal_Int32)0 ));
554 :
555 396 : rInfo.aTableProperties = m_aTableProperties->GetPropertyValues();
556 :
557 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
558 : dmapper_logger->startElement("debug.tableprops");
559 : m_aTableProperties->dumpXml( dmapper_logger );
560 : dmapper_logger->endElement();
561 : #endif
562 :
563 : }
564 :
565 3394 : return pTableStyle;
566 : }
567 :
568 : #define CNF_FIRST_ROW 0x800
569 : #define CNF_LAST_ROW 0x400
570 : #define CNF_FIRST_COLUMN 0x200
571 : #define CNF_LAST_COLUMN 0x100
572 : #define CNF_ODD_VBAND 0x080
573 : #define CNF_EVEN_VBAND 0x040
574 : #define CNF_ODD_HBAND 0x020
575 : #define CNF_EVEN_HBAND 0x010
576 : #define CNF_FIRST_ROW_LAST_COLUMN 0x008
577 : #define CNF_FIRST_ROW_FIRST_COLUMN 0x004
578 : #define CNF_LAST_ROW_LAST_COLUMN 0x002
579 : #define CNF_LAST_ROW_FIRST_COLUMN 0x001
580 :
581 3394 : CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(TableInfo & rInfo, std::vector<HorizontallyMergedCell>& rMerges)
582 : {
583 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
584 : dmapper_logger->startElement("getCellProperties");
585 : #endif
586 :
587 3394 : CellPropertyValuesSeq_t aCellProperties( m_aCellProperties.size() );
588 :
589 3394 : if ( !m_aCellProperties.size() )
590 : {
591 : #ifdef DEBUG_DOMAINMAPPER
592 : dmapper_logger->endElement();
593 : #endif
594 2998 : return aCellProperties;
595 : }
596 : // std::vector< std::vector<PropertyMapPtr> > m_aCellProperties
597 396 : PropertyMapVector2::const_iterator aRowOfCellsIterator = m_aCellProperties.begin();
598 396 : PropertyMapVector2::const_iterator aRowOfCellsIteratorEnd = m_aCellProperties.end();
599 396 : PropertyMapVector2::const_iterator aLastRowIterator = m_aCellProperties.end() - 1;
600 396 : sal_Int32 nRow = 0;
601 :
602 : //it's a uno::Sequence< beans::PropertyValues >*
603 396 : RowPropertyValuesSeq_t* pCellProperties = aCellProperties.getArray();
604 396 : PropertyMapVector1::const_iterator aRowIter = m_aRowProperties.begin();
605 2987 : while( aRowOfCellsIterator != aRowOfCellsIteratorEnd )
606 : {
607 : //aRowOfCellsIterator points to a vector of PropertyMapPtr
608 2195 : PropertyMapVector1::const_iterator aCellIterator = aRowOfCellsIterator->begin();
609 2195 : PropertyMapVector1::const_iterator aCellIteratorEnd = aRowOfCellsIterator->end();
610 :
611 2195 : sal_Int32 nRowStyleMask = 0;
612 :
613 2195 : if (aRowOfCellsIterator==m_aCellProperties.begin())
614 : {
615 396 : if(rInfo.nTblLook&0x20)
616 332 : nRowStyleMask |= CNF_FIRST_ROW; // first row style used
617 : }
618 1799 : else if (aRowOfCellsIterator==aLastRowIterator)
619 : {
620 217 : if(rInfo.nTblLook&0x40)
621 2 : nRowStyleMask |= CNF_LAST_ROW; // last row style used
622 : }
623 1582 : else if (aRowIter->get() && aRowIter->get()->find(PROP_TBL_HEADER) != aRowIter->get()->end())
624 40 : nRowStyleMask |= CNF_FIRST_ROW; // table header implies first row
625 2195 : if(!nRowStyleMask) // if no row style used yet
626 : {
627 : // banding used only if not first and or last row style used
628 1821 : if(!(rInfo.nTblLook&0x200))
629 : { // hbanding used
630 1821 : int n = nRow + 1;
631 1821 : if(rInfo.nTblLook&0x20)
632 1460 : n++;
633 1821 : if(n & 1)
634 989 : nRowStyleMask = CNF_ODD_HBAND;
635 : else
636 832 : nRowStyleMask = CNF_EVEN_HBAND;
637 : }
638 : }
639 :
640 2195 : sal_Int32 nCell = 0;
641 2195 : pCellProperties[nRow].realloc( aRowOfCellsIterator->size() );
642 2195 : beans::PropertyValues* pSingleCellProperties = pCellProperties[nRow].getArray();
643 11110 : while( aCellIterator != aCellIteratorEnd )
644 : {
645 6720 : PropertyMapPtr pAllCellProps( new PropertyMap );
646 :
647 6720 : PropertyMapVector1::const_iterator aLastCellIterator = aRowOfCellsIterator->end() - 1;
648 6720 : bool bIsEndCol = aCellIterator == aLastCellIterator;
649 6720 : bool bIsEndRow = aRowOfCellsIterator == aLastRowIterator;
650 :
651 : //aCellIterator points to a PropertyMapPtr;
652 6720 : if( aCellIterator->get() )
653 : {
654 6720 : if ( rInfo.pTableDefaults->size( ) )
655 3692 : pAllCellProps->InsertProps(rInfo.pTableDefaults);
656 :
657 6720 : sal_Int32 nCellStyleMask = 0;
658 6720 : if (aCellIterator==aRowOfCellsIterator->begin())
659 : {
660 2188 : if(rInfo.nTblLook&0x80)
661 1819 : nCellStyleMask = CNF_FIRST_COLUMN; // first col style used
662 : }
663 4532 : else if (bIsEndCol)
664 : {
665 1872 : if(rInfo.nTblLook&0x100)
666 13 : nCellStyleMask = CNF_LAST_COLUMN; // last col style used
667 : }
668 6720 : if(!nCellStyleMask) // if no cell style is used yet
669 : {
670 4888 : if(!(rInfo.nTblLook&0x400))
671 : { // vbanding used
672 1335 : int n = nCell + 1;
673 1335 : if(rInfo.nTblLook&0x80)
674 40 : n++;
675 1335 : if(n & 1)
676 731 : nCellStyleMask = CNF_ODD_VBAND;
677 : else
678 604 : nCellStyleMask = CNF_EVEN_VBAND;
679 : }
680 : }
681 6720 : sal_Int32 nCnfStyleMask = nCellStyleMask + nRowStyleMask;
682 6720 : if(nCnfStyleMask == CNF_FIRST_COLUMN + CNF_FIRST_ROW)
683 364 : nCnfStyleMask |= CNF_FIRST_ROW_FIRST_COLUMN;
684 6356 : else if(nCnfStyleMask == CNF_FIRST_COLUMN + CNF_LAST_ROW)
685 2 : nCnfStyleMask |= CNF_LAST_ROW_FIRST_COLUMN;
686 6354 : else if(nCnfStyleMask == CNF_LAST_COLUMN + CNF_FIRST_ROW)
687 6 : nCnfStyleMask |= CNF_FIRST_ROW_LAST_COLUMN;
688 6348 : else if(nCnfStyleMask == CNF_LAST_COLUMN + CNF_LAST_ROW)
689 2 : nCnfStyleMask |= CNF_LAST_ROW_LAST_COLUMN;
690 :
691 6720 : if ( rInfo.pTableStyle )
692 : {
693 3755 : PropertyMapPtr pStyleProps = rInfo.pTableStyle->GetProperties( nCnfStyleMask );
694 3755 : pAllCellProps->InsertProps( pStyleProps );
695 : }
696 :
697 : // Remove properties from style/row that aren't allowed in cells
698 6720 : const PropertyMap::iterator aDefaultRepeatIt = pAllCellProps->find(PROP_HEADER_ROW_COUNT);
699 6720 : if ( aDefaultRepeatIt != pAllCellProps->end( ) )
700 355 : pAllCellProps->erase( aDefaultRepeatIt );
701 6720 : const PropertyMap::iterator aDefaultRepeatIt2 = pAllCellProps->find(PROP_PARA_LINE_SPACING);
702 6720 : if ( aDefaultRepeatIt2 != pAllCellProps->end( ) )
703 2629 : pAllCellProps->erase( aDefaultRepeatIt2 );
704 :
705 : // Then add the cell properties
706 6720 : pAllCellProps->InsertProps(*aCellIterator);
707 6720 : aCellIterator->get( )->swap( *pAllCellProps.get( ) );
708 :
709 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
710 : dmapper_logger->startElement("cell");
711 : dmapper_logger->attribute("cell", nCell);
712 : dmapper_logger->attribute("row", nRow);
713 : #endif
714 :
715 6720 : lcl_computeCellBorders( rInfo.pTableBorders, *aCellIterator, nCell, nRow, bIsEndCol, bIsEndRow );
716 :
717 : //now set the default left+right border distance TODO: there's an sprm containing the default distance!
718 : const PropertyMap::const_iterator aLeftDistanceIter =
719 6720 : aCellIterator->get()->find(PROP_LEFT_BORDER_DISTANCE);
720 6720 : if( aLeftDistanceIter == aCellIterator->get()->end() )
721 : aCellIterator->get()->Insert( PROP_LEFT_BORDER_DISTANCE,
722 6588 : uno::makeAny(rInfo.nLeftBorderDistance ) );
723 : const PropertyMap::const_iterator aRightDistanceIter =
724 6720 : aCellIterator->get()->find(PROP_RIGHT_BORDER_DISTANCE);
725 6720 : if( aRightDistanceIter == aCellIterator->get()->end() )
726 : aCellIterator->get()->Insert( PROP_RIGHT_BORDER_DISTANCE,
727 6341 : uno::makeAny((sal_Int32) rInfo.nRightBorderDistance ) );
728 :
729 : const PropertyMap::const_iterator aTopDistanceIter =
730 6720 : aCellIterator->get()->find(PROP_TOP_BORDER_DISTANCE);
731 6720 : if( aTopDistanceIter == aCellIterator->get()->end() )
732 : aCellIterator->get()->Insert( PROP_TOP_BORDER_DISTANCE,
733 6322 : uno::makeAny((sal_Int32) rInfo.nTopBorderDistance ) );
734 :
735 : const PropertyMap::const_iterator aBottomDistanceIter =
736 6720 : aCellIterator->get()->find(PROP_BOTTOM_BORDER_DISTANCE);
737 6720 : if( aBottomDistanceIter == aCellIterator->get()->end() )
738 : aCellIterator->get()->Insert( PROP_BOTTOM_BORDER_DISTANCE,
739 6634 : uno::makeAny((sal_Int32) rInfo.nBottomBorderDistance ) );
740 :
741 : // Horizontal merge is not an UNO property, extract that info here to rMerges, and then remove it from the map.
742 6720 : const PropertyMap::const_iterator aHorizontalMergeIter = aCellIterator->get()->find(PROP_HORIZONTAL_MERGE);
743 6720 : if (aHorizontalMergeIter != aCellIterator->get()->end())
744 : {
745 4 : if (aHorizontalMergeIter->second.getValue().get<sal_Bool>())
746 : {
747 : // first cell in a merge
748 2 : HorizontallyMergedCell aMerge(nRow, nCell);
749 2 : rMerges.push_back(aMerge);
750 : }
751 2 : else if (!rMerges.empty())
752 : {
753 : // resuming an earlier merge
754 2 : HorizontallyMergedCell& rMerge = rMerges.back();
755 2 : rMerge.m_nLastRow = nRow;
756 2 : rMerge.m_nLastCol = nCell;
757 : }
758 4 : aCellIterator->get()->erase(PROP_HORIZONTAL_MERGE);
759 : }
760 6720 : pSingleCellProperties[nCell] = aCellIterator->get()->GetPropertyValues();
761 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
762 : dmapper_logger->endElement();
763 : #endif
764 : }
765 6720 : ++nCell;
766 6720 : ++aCellIterator;
767 6720 : }
768 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
769 : //-->debug cell properties
770 : {
771 : OUString sNames;
772 : const uno::Sequence< beans::PropertyValues > aDebugCurrentRow = aCellProperties[nRow];
773 : sal_Int32 nDebugCells = aDebugCurrentRow.getLength();
774 : (void) nDebugCells;
775 : for( sal_Int32 nDebugCell = 0; nDebugCell < nDebugCells; ++nDebugCell)
776 : {
777 : const uno::Sequence< beans::PropertyValue >& aDebugCellProperties = aDebugCurrentRow[nDebugCell];
778 : sal_Int32 nDebugCellProperties = aDebugCellProperties.getLength();
779 : for( sal_Int32 nDebugProperty = 0; nDebugProperty < nDebugCellProperties; ++nDebugProperty)
780 : {
781 : const OUString sName = aDebugCellProperties[nDebugProperty].Name;
782 : sNames += sName;
783 : sNames += OUString('-');
784 : }
785 : sNames += OUString('\n');
786 : }
787 : (void)sNames;
788 : }
789 : //--<
790 : #endif
791 2195 : ++nRow;
792 2195 : ++aRowOfCellsIterator;
793 2195 : ++aRowIter;
794 : }
795 :
796 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
797 : dmapper_logger->endElement();
798 : #endif
799 :
800 396 : return aCellProperties;
801 : }
802 :
803 3394 : RowPropertyValuesSeq_t DomainMapperTableHandler::endTableGetRowProperties()
804 : {
805 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
806 : dmapper_logger->startElement("getRowProperties");
807 : #endif
808 :
809 3394 : RowPropertyValuesSeq_t aRowProperties( m_aRowProperties.size() );
810 3394 : PropertyMapVector1::const_iterator aRowIter = m_aRowProperties.begin();
811 3394 : PropertyMapVector1::const_iterator aRowIterEnd = m_aRowProperties.end();
812 3394 : sal_Int32 nRow = 0;
813 8983 : while( aRowIter != aRowIterEnd )
814 : {
815 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
816 : dmapper_logger->startElement("rowProps.row");
817 : #endif
818 2195 : if( aRowIter->get() )
819 : {
820 : //set default to 'break across pages"
821 2183 : if( aRowIter->get()->find(PROP_IS_SPLIT_ALLOWED) == aRowIter->get()->end())
822 2059 : aRowIter->get()->Insert( PROP_IS_SPLIT_ALLOWED, uno::makeAny(sal_True ) );
823 : // tblHeader is only our property, remove before the property map hits UNO
824 2183 : PropertyMap::iterator const aIter = aRowIter->get()->find(PROP_TBL_HEADER);
825 2183 : if (aIter != aRowIter->get()->end())
826 49 : aRowIter->get()->erase(aIter);
827 :
828 2183 : aRowProperties[nRow] = (*aRowIter)->GetPropertyValues();
829 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
830 : ((*aRowIter)->dumpXml( dmapper_logger ));
831 : lcl_DumpPropertyValues(dmapper_logger, aRowProperties[nRow]);
832 : #endif
833 : }
834 2195 : ++nRow;
835 2195 : ++aRowIter;
836 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
837 : dmapper_logger->endElement();
838 : #endif
839 : }
840 :
841 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
842 : dmapper_logger->endElement();
843 : #endif
844 :
845 3394 : return aRowProperties;
846 : }
847 :
848 : // Apply paragraph property to each paragraph within a cell.
849 2605 : static void lcl_ApplyCellParaProps(uno::Reference<table::XCell> xCell, uno::Any aBottomMargin)
850 : {
851 2605 : uno::Reference<container::XEnumerationAccess> xEnumerationAccess(xCell, uno::UNO_QUERY);
852 5210 : uno::Reference<container::XEnumeration> xEnumeration = xEnumerationAccess->createEnumeration();
853 7854 : while (xEnumeration->hasMoreElements())
854 : {
855 2644 : uno::Reference<beans::XPropertySet> xParagraph(xEnumeration->nextElement(), uno::UNO_QUERY);
856 5288 : uno::Reference<beans::XPropertyState> xPropertyState(xParagraph, uno::UNO_QUERY);
857 : // Don't apply in case direct formatting is already present.
858 : // TODO: probably paragraph style has priority over table style here.
859 2644 : if (xPropertyState.is() && xPropertyState->getPropertyState("ParaBottomMargin") == beans::PropertyState_DEFAULT_VALUE)
860 9 : xParagraph->setPropertyValue("ParaBottomMargin", aBottomMargin);
861 5249 : }
862 2605 : }
863 :
864 3394 : void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel)
865 : {
866 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
867 : dmapper_logger->startElement("tablehandler.endTable");
868 : #endif
869 :
870 : // If we want to make this table a floating one.
871 3394 : uno::Sequence<beans::PropertyValue> aFrameProperties = m_rDMapper_Impl.getTableManager().getCurrentTablePosition();
872 6788 : TableInfo aTableInfo;
873 3394 : aTableInfo.nNestLevel = nestedTableLevel;
874 3394 : aTableInfo.pTableStyle = endTableGetTableStyle(aTableInfo, aFrameProperties);
875 : // expands to uno::Sequence< Sequence< beans::PropertyValues > >
876 :
877 6788 : std::vector<HorizontallyMergedCell> aMerges;
878 6788 : CellPropertyValuesSeq_t aCellProperties = endTableGetCellProperties(aTableInfo, aMerges);
879 :
880 6788 : RowPropertyValuesSeq_t aRowProperties = endTableGetRowProperties();
881 :
882 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
883 : lcl_DumpPropertyValueSeq(dmapper_logger, aRowProperties);
884 : #endif
885 :
886 3394 : if (m_pTableSeq->getLength() > 0)
887 : {
888 396 : uno::Reference<text::XTextRange> xStart;
889 792 : uno::Reference<text::XTextRange> xEnd;
890 :
891 396 : bool bFloating = aFrameProperties.hasElements();
892 : // Additional checks: if we can do this.
893 396 : if (bFloating && (*m_pTableSeq)[0].getLength() > 0 && (*m_pTableSeq)[0][0].getLength() > 0)
894 : {
895 31 : xStart = (*m_pTableSeq)[0][0][0];
896 31 : uno::Sequence< uno::Sequence< uno::Reference<text::XTextRange> > >& rLastRow = (*m_pTableSeq)[m_pTableSeq->getLength() - 1];
897 31 : uno::Sequence< uno::Reference<text::XTextRange> >& rLastCell = rLastRow[rLastRow.getLength() - 1];
898 31 : xEnd = rLastCell[1];
899 : }
900 792 : uno::Reference<text::XTextTable> xTable;
901 : try
902 : {
903 396 : if (m_xText.is())
904 : {
905 1151 : xTable = m_xText->convertToTable(*m_pTableSeq,
906 : aCellProperties,
907 : aRowProperties,
908 767 : aTableInfo.aTableProperties);
909 :
910 383 : if (xTable.is())
911 : {
912 383 : m_xTableRange = xTable->getAnchor( );
913 :
914 383 : if (!aMerges.empty())
915 : {
916 : // Perform horizontal merges in reverse order, so the fact that merging changes the position of cells won't cause a problem for us.
917 4 : for (std::vector<HorizontallyMergedCell>::reverse_iterator it = aMerges.rbegin(); it != aMerges.rend(); ++it)
918 : {
919 2 : uno::Reference<table::XCellRange> xCellRange(xTable, uno::UNO_QUERY_THROW);
920 4 : uno::Reference<beans::XPropertySet> xCell(xCellRange->getCellByPosition(it->m_nFirstCol, it->m_nFirstRow), uno::UNO_QUERY_THROW);
921 4 : OUString aFirst = xCell->getPropertyValue("CellName").get<OUString>();
922 2 : xCell.set(xCellRange->getCellByPosition(it->m_nLastCol, it->m_nLastRow), uno::UNO_QUERY_THROW);
923 4 : OUString aLast = xCell->getPropertyValue("CellName").get<OUString>();
924 :
925 4 : uno::Reference<text::XTextTableCursor> xCursor = xTable->createCursorByCellName(aFirst);
926 2 : xCursor->gotoCellByName(aLast, true);
927 2 : xCursor->mergeRange();
928 2 : }
929 : }
930 : }
931 :
932 : // OOXML table style may container paragraph properties, apply these now.
933 4169 : for (int i = 0; i < aTableInfo.aTableProperties.getLength(); ++i)
934 : {
935 3894 : if (aTableInfo.aTableProperties[i].Name == "ParaBottomMargin")
936 : {
937 108 : uno::Reference<table::XCellRange> xCellRange(xTable, uno::UNO_QUERY);
938 216 : uno::Any aBottomMargin = aTableInfo.aTableProperties[i].Value;
939 108 : sal_Int32 nRows = aCellProperties.getLength();
940 1175 : for (sal_Int32 nRow = 0; nRow < nRows; ++nRow)
941 : {
942 1068 : const uno::Sequence< beans::PropertyValues > aCurrentRow = aCellProperties[nRow];
943 1068 : sal_Int32 nCells = aCurrentRow.getLength();
944 3673 : for (sal_Int32 nCell = 0; nCell < nCells; ++nCell)
945 2606 : lcl_ApplyCellParaProps(xCellRange->getCellByPosition(nCell, nRow), aBottomMargin);
946 1068 : }
947 215 : break;
948 : }
949 : }
950 : }
951 : }
952 1 : catch ( const lang::IllegalArgumentException &e )
953 : {
954 : SAL_INFO("writerfilter.dmapper",
955 : "Conversion to table error: " << e.Message);
956 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
957 : dmapper_logger->chars(std::string("failed to import table!"));
958 : #endif
959 : }
960 1 : catch ( const uno::Exception &e )
961 : {
962 : SAL_INFO("writerfilter.dmapper",
963 : "Exception during table creation: " << e.Message);
964 : }
965 :
966 : // If we have a table with a start and an end position, we should make it a floating one.
967 396 : if (xTable.is() && xStart.is() && xEnd.is())
968 : {
969 31 : uno::Reference<beans::XPropertySet> xTableProperties(xTable, uno::UNO_QUERY);
970 31 : sal_Bool bIsRelative = sal_False;
971 31 : xTableProperties->getPropertyValue("IsWidthRelative") >>= bIsRelative;
972 31 : if (!bIsRelative)
973 : {
974 28 : aFrameProperties.realloc(aFrameProperties.getLength() + 1);
975 28 : aFrameProperties[aFrameProperties.getLength() - 1].Name = "Width";
976 28 : aFrameProperties[aFrameProperties.getLength() - 1].Value = xTableProperties->getPropertyValue("Width");
977 : }
978 : else
979 : {
980 3 : aFrameProperties.realloc(aFrameProperties.getLength() + 1);
981 3 : aFrameProperties[aFrameProperties.getLength() - 1].Name = "FrameWidthPercent";
982 3 : aFrameProperties[aFrameProperties.getLength() - 1].Value = xTableProperties->getPropertyValue("RelativeWidth");
983 :
984 : // Applying the relative width to the frame, needs to have the table width to be 100% of the frame width
985 3 : xTableProperties->setPropertyValue("RelativeWidth", uno::makeAny(sal_Int16(100)));
986 : }
987 :
988 : // A non-zero left margin would move the table out of the frame, move the frame itself instead.
989 31 : xTableProperties->setPropertyValue("LeftMargin", uno::makeAny(sal_Int32(0)));
990 :
991 : // In case the document ends with a table, we're called after
992 : // SectionPropertyMap::CloseSectionGroup(), so we'll have no idea
993 : // about the text area width, nor can fix this by delaying the text
994 : // frame conversion: just do it here.
995 : // Also, when the anchor is within a table, then do it here as well,
996 : // as xStart/xEnd would not point to the start/end at conversion
997 : // time anyway.
998 31 : sal_Int32 nTableWidth = 0;
999 31 : m_aTableProperties->getValue(TablePropertyMap::TABLE_WIDTH, nTableWidth);
1000 31 : if (m_rDMapper_Impl.GetSectionContext() && nestedTableLevel <= 1)
1001 29 : m_rDMapper_Impl.m_aPendingFloatingTables.push_back(FloatingTableInfo(xStart, xEnd, aFrameProperties, nTableWidth));
1002 : else
1003 2 : m_xText->convertToTextFrame(xStart, xEnd, aFrameProperties);
1004 396 : }
1005 : }
1006 :
1007 3394 : m_aTableProperties.reset();
1008 3394 : m_aCellProperties.clear();
1009 6788 : m_aRowProperties.clear();
1010 :
1011 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1012 : dmapper_logger->endElement();
1013 : dmapper_logger->endElement();
1014 : #endif
1015 3394 : }
1016 :
1017 2195 : void DomainMapperTableHandler::startRow(unsigned int nCells,
1018 : TablePropertyMapPtr pProps)
1019 : {
1020 2195 : m_aRowProperties.push_back( pProps );
1021 2195 : m_aCellProperties.push_back( PropertyMapVector1() );
1022 :
1023 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1024 : dmapper_logger->startElement("table.row");
1025 : dmapper_logger->attribute("cells", nCells);
1026 : if (pProps != NULL)
1027 : pProps->dumpXml(dmapper_logger);
1028 : #endif
1029 :
1030 2195 : m_pRowSeq = RowSequencePointer_t(new RowSequence_t(nCells));
1031 2195 : m_nCellIndex = 0;
1032 2195 : }
1033 :
1034 2195 : void DomainMapperTableHandler::endRow()
1035 : {
1036 2195 : (*m_pTableSeq)[m_nRowIndex] = *m_pRowSeq;
1037 2195 : ++m_nRowIndex;
1038 2195 : m_nCellIndex = 0;
1039 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1040 : dmapper_logger->endElement();
1041 : #endif
1042 2195 : }
1043 :
1044 6720 : void DomainMapperTableHandler::startCell(const Handle_t & start,
1045 : TablePropertyMapPtr pProps )
1046 : {
1047 6720 : sal_uInt32 nRow = m_aRowProperties.size();
1048 6720 : if ( pProps.get( ) )
1049 4241 : m_aCellProperties[nRow - 1].push_back( pProps );
1050 : else
1051 : {
1052 : // Adding an empty cell properties map to be able to get
1053 : // the table defaults properties
1054 2479 : TablePropertyMapPtr pEmptyProps( new TablePropertyMap( ) );
1055 2479 : m_aCellProperties[nRow - 1].push_back( pEmptyProps );
1056 : }
1057 :
1058 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1059 : dmapper_logger->startElement("table.cell");
1060 : dmapper_logger->startElement("table.cell.start");
1061 : dmapper_logger->chars(toString(start));
1062 : dmapper_logger->endElement();
1063 : lcl_printProperties( pProps );
1064 : #endif
1065 :
1066 : //add a new 'row' of properties
1067 6720 : m_pCellSeq = CellSequencePointer_t(new CellSequence_t(2));
1068 6720 : if (!start.get())
1069 6747 : return;
1070 6693 : (*m_pCellSeq)[0] = start->getStart();
1071 : }
1072 :
1073 6720 : void DomainMapperTableHandler::endCell(const Handle_t & end)
1074 : {
1075 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
1076 : dmapper_logger->startElement("table.cell.end");
1077 : dmapper_logger->chars(toString(end));
1078 : dmapper_logger->endElement();
1079 : dmapper_logger->endElement();
1080 : #endif
1081 :
1082 6720 : if (!end.get())
1083 6747 : return;
1084 6693 : (*m_pCellSeq)[1] = end->getEnd();
1085 6693 : (*m_pRowSeq)[m_nCellIndex] = *m_pCellSeq;
1086 6693 : ++m_nCellIndex;
1087 : }
1088 :
1089 : }}
1090 :
1091 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|