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/table/TableBorderDistances.hpp>
23 : #include <com/sun/star/table/TableBorder.hpp>
24 : #include <com/sun/star/table/BorderLine2.hpp>
25 : #include <com/sun/star/text/HoriOrientation.hpp>
26 : #include <com/sun/star/text/RelOrientation.hpp>
27 : #include <dmapperLoggers.hxx>
28 :
29 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
30 : #include <PropertyMapHelper.hxx>
31 : #include <rtl/ustring.hxx>
32 : #endif
33 :
34 : namespace writerfilter {
35 : namespace dmapper {
36 :
37 : using namespace ::com::sun::star;
38 : using namespace ::std;
39 :
40 : #define DEF_BORDER_DIST 190 //0,19cm
41 :
42 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
43 : static void lcl_printProperties( PropertyMapPtr pProps )
44 : {
45 : if( pProps.get() )
46 : {
47 : dmapper_logger->startElement("properties");
48 :
49 : PropertyMap::const_iterator aMapIter = pProps->begin();
50 : PropertyMap::const_iterator aEndIter = pProps->end();
51 : PropertyNameSupplier& rPropSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
52 : for( ; aMapIter != aEndIter; ++aMapIter )
53 : {
54 : SAL_INFO("writerfilter", rPropSupplier.GetName(aMapIter->first.eId));
55 :
56 : table::BorderLine2 aLine;
57 : sal_Int32 nColor;
58 : if ( aMapIter->second >>= aLine )
59 : {
60 : dmapper_logger->startElement("borderline");
61 : dmapper_logger->attribute("color", aLine.Color);
62 : dmapper_logger->attribute("inner", aLine.InnerLineWidth);
63 : dmapper_logger->attribute("outer", aLine.OuterLineWidth);
64 : dmapper_logger->endElement();
65 : }
66 : else if ( aMapIter->second >>= nColor )
67 : {
68 : dmapper_logger->startElement("color");
69 : dmapper_logger->attribute("number", nColor);
70 : dmapper_logger->endElement();
71 : }
72 : }
73 :
74 : dmapper_logger->endElement();
75 : }
76 : }
77 : #endif
78 :
79 438 : DomainMapperTableHandler::DomainMapperTableHandler(TextReference_t xText, DomainMapper_Impl& rDMapper_Impl)
80 : : m_xText(xText),
81 : m_rDMapper_Impl( rDMapper_Impl ),
82 : m_nCellIndex(0),
83 438 : m_nRowIndex(0)
84 : {
85 438 : }
86 :
87 876 : DomainMapperTableHandler::~DomainMapperTableHandler()
88 : {
89 876 : }
90 :
91 708 : void DomainMapperTableHandler::startTable(unsigned int nRows,
92 : unsigned int /*nDepth*/,
93 : TablePropertyMapPtr pProps)
94 : {
95 708 : m_aTableProperties = pProps;
96 708 : m_pTableSeq = TableSequencePointer_t(new TableSequence_t(nRows));
97 708 : m_nRowIndex = 0;
98 :
99 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
100 : dmapper_logger->startElement("tablehandler.table");
101 : dmapper_logger->attribute("rows", nRows);
102 :
103 : if (pProps.get() != NULL)
104 : pProps->dumpXml( dmapper_logger );
105 : #endif
106 708 : }
107 :
108 :
109 :
110 0 : PropertyMapPtr lcl_SearchParentStyleSheetAndMergeProperties(const StyleSheetEntryPtr pStyleSheet, StyleSheetTablePtr pStyleSheetTable)
111 : {
112 0 : PropertyMapPtr pRet;
113 0 : if(!pStyleSheet->sBaseStyleIdentifier.isEmpty())
114 : {
115 0 : const StyleSheetEntryPtr pParentStyleSheet = pStyleSheetTable->FindStyleSheetByISTD( pStyleSheet->sBaseStyleIdentifier );
116 0 : pRet = lcl_SearchParentStyleSheetAndMergeProperties( pParentStyleSheet, pStyleSheetTable );
117 : }
118 : else
119 : {
120 0 : pRet.reset( new PropertyMap );
121 : }
122 :
123 0 : pRet->InsertProps(pStyleSheet->pProperties);
124 :
125 0 : return pRet;
126 : }
127 :
128 1156 : void lcl_mergeBorder( PropertyIds nId, PropertyMapPtr pOrig, PropertyMapPtr pDest )
129 : {
130 1156 : PropertyDefinition aDef( nId, false );
131 1156 : PropertyMap::iterator pOrigIt = pOrig->find( aDef );
132 :
133 1156 : if ( pOrigIt != pOrig->end( ) )
134 : {
135 450 : pDest->Insert( nId, false, pOrigIt->second, false );
136 : }
137 1156 : }
138 :
139 580 : void lcl_computeCellBorders( PropertyMapPtr pTableBorders, PropertyMapPtr pCellProps,
140 : sal_Int32 nCell, sal_Int32 nRow, bool bIsEndCol, bool bIsEndRow )
141 : {
142 580 : PropertyDefinition aVertPDef( META_PROP_VERTICAL_BORDER, false );
143 580 : PropertyDefinition aHorizPDef( META_PROP_HORIZONTAL_BORDER, false );
144 :
145 580 : PropertyMap::iterator aVerticalIter = pCellProps->find( aVertPDef );
146 580 : PropertyMap::iterator aHorizontalIter = pCellProps->find( aHorizPDef );
147 :
148 : // Handle the vertical and horizontal borders
149 580 : bool bHasVert = ( aVerticalIter != pCellProps->end( ) );
150 580 : uno::Any aVertProp;
151 580 : if ( !bHasVert )
152 : {
153 580 : aVerticalIter = pTableBorders->find( aVertPDef );
154 580 : bHasVert = ( aVerticalIter != pTableBorders->end( ) );
155 580 : if ( bHasVert )
156 252 : aVertProp = aVerticalIter->second;
157 : }
158 : else
159 : {
160 0 : aVertProp = aVerticalIter->second;
161 0 : pCellProps->erase( aVerticalIter );
162 : }
163 :
164 580 : bool bHasHoriz = ( aHorizontalIter != pCellProps->end( ) );
165 580 : uno::Any aHorizProp;
166 580 : if ( !bHasHoriz )
167 : {
168 580 : aHorizontalIter = pTableBorders->find( aHorizPDef );
169 580 : bHasHoriz = ( aHorizontalIter != pTableBorders->end( ) );
170 580 : if ( bHasHoriz )
171 240 : aHorizProp = aHorizontalIter->second;
172 : }
173 : else
174 : {
175 0 : aHorizProp = aHorizontalIter->second;
176 0 : pCellProps->erase( aHorizontalIter );
177 : }
178 :
179 580 : if ( nCell == 0 )
180 : {
181 154 : lcl_mergeBorder( PROP_LEFT_BORDER, pTableBorders, pCellProps );
182 154 : if ( bHasVert )
183 64 : pCellProps->Insert( PROP_RIGHT_BORDER, false, aVertProp, false );
184 : }
185 :
186 580 : if ( bIsEndCol )
187 : {
188 154 : lcl_mergeBorder( PROP_RIGHT_BORDER, pTableBorders, pCellProps );
189 154 : if ( bHasVert )
190 64 : pCellProps->Insert( PROP_LEFT_BORDER, false, aVertProp, false );
191 : }
192 :
193 580 : if ( nCell > 0 && !bIsEndCol )
194 : {
195 294 : if ( bHasVert )
196 : {
197 130 : pCellProps->Insert( PROP_RIGHT_BORDER, false, aVertProp, false );
198 130 : pCellProps->Insert( PROP_LEFT_BORDER, false, aVertProp, false );
199 : }
200 : }
201 :
202 580 : if ( nRow == 0 )
203 : {
204 428 : lcl_mergeBorder( PROP_TOP_BORDER, pTableBorders, pCellProps );
205 428 : if ( bHasHoriz )
206 152 : pCellProps->Insert( PROP_BOTTOM_BORDER, false, aHorizProp, false );
207 : }
208 :
209 580 : if ( bIsEndRow )
210 : {
211 420 : lcl_mergeBorder( PROP_BOTTOM_BORDER, pTableBorders, pCellProps );
212 420 : if ( bHasHoriz )
213 158 : pCellProps->Insert( PROP_TOP_BORDER, false, aHorizProp, false );
214 : }
215 :
216 580 : if ( nRow > 0 && !bIsEndRow )
217 : {
218 50 : if ( bHasHoriz )
219 : {
220 26 : pCellProps->Insert( PROP_TOP_BORDER, false, aHorizProp, false );
221 26 : pCellProps->Insert( PROP_BOTTOM_BORDER, false, aHorizProp, false );
222 : }
223 580 : }
224 580 : }
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 708 : struct WRITERFILTER_DLLPRIVATE TableInfo
260 : {
261 : sal_Int32 nLeftBorderDistance;
262 : sal_Int32 nRightBorderDistance;
263 : sal_Int32 nTopBorderDistance;
264 : sal_Int32 nBottomBorderDistance;
265 : sal_Int32 nNestLevel;
266 : PropertyMapPtr pTableDefaults;
267 : PropertyMapPtr pTableBorders;
268 : TableStyleSheetEntry* pTableStyle;
269 : TablePropertyValues_t aTableProperties;
270 :
271 708 : TableInfo()
272 : : nLeftBorderDistance(DEF_BORDER_DIST)
273 : , nRightBorderDistance(DEF_BORDER_DIST)
274 : , nTopBorderDistance(0)
275 : , nBottomBorderDistance(0)
276 : , nNestLevel(0)
277 708 : , pTableDefaults(new PropertyMap)
278 708 : , pTableBorders(new PropertyMap)
279 2124 : , pTableStyle(NULL)
280 : {
281 708 : }
282 :
283 : };
284 :
285 : namespace
286 : {
287 :
288 612 : bool lcl_extractTableBorderProperty(PropertyMapPtr pTableProperties, const PropertyIds nId, TableInfo& rInfo, table::BorderLine2& rLine)
289 : {
290 612 : PropertyMap::iterator aTblBorderIter = pTableProperties->find( PropertyDefinition(nId, false) );
291 612 : if( aTblBorderIter != pTableProperties->end() )
292 : {
293 200 : OSL_VERIFY(aTblBorderIter->second >>= rLine);
294 :
295 200 : rInfo.pTableBorders->Insert( nId, false, uno::makeAny( rLine ) );
296 200 : PropertyMap::iterator pIt = rInfo.pTableDefaults->find( PropertyDefinition( nId, false ) );
297 200 : if ( pIt != rInfo.pTableDefaults->end( ) )
298 200 : rInfo.pTableDefaults->erase( pIt );
299 :
300 200 : return true;
301 : }
302 :
303 412 : return false;
304 : }
305 :
306 : }
307 :
308 708 : TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo & rInfo)
309 : {
310 : // will receive the table style if any
311 708 : TableStyleSheetEntry* pTableStyle = NULL;
312 :
313 708 : if( m_aTableProperties.get() )
314 : {
315 : //create properties from the table attributes
316 : //...pPropMap->Insert( PROP_LEFT_MARGIN, false, uno::makeAny( m_nLeftMargin - m_nGapHalf ));
317 : //pPropMap->Insert( PROP_HORI_ORIENT, false, uno::makeAny( text::HoriOrientation::RIGHT ));
318 102 : sal_Int32 nGapHalf = 0;
319 102 : sal_Int32 nLeftMargin = 0;
320 102 : sal_Int32 nTableWidth = 0;
321 :
322 : PropertyMap::iterator aTableStyleIter =
323 102 : m_aTableProperties->find( PropertyDefinition( META_PROP_TABLE_STYLE_NAME, false ) );
324 102 : if(aTableStyleIter != m_aTableProperties->end())
325 : {
326 : // Apply table style properties recursively
327 50 : OUString sTableStyleName;
328 50 : aTableStyleIter->second >>= sTableStyleName;
329 50 : StyleSheetTablePtr pStyleSheetTable = m_rDMapper_Impl.GetStyleSheetTable();
330 50 : const StyleSheetEntryPtr pStyleSheet = pStyleSheetTable->FindStyleSheetByISTD( sTableStyleName );
331 50 : pTableStyle = dynamic_cast<TableStyleSheetEntry*>( pStyleSheet.get( ) );
332 50 : m_aTableProperties->erase( aTableStyleIter );
333 :
334 50 : if( pStyleSheet )
335 : {
336 : // First get the style properties, then the table ones
337 0 : PropertyMapPtr pTableProps( m_aTableProperties );
338 0 : TablePropertyMapPtr pEmptyProps( new TablePropertyMap );
339 :
340 0 : m_aTableProperties = pEmptyProps;
341 :
342 0 : PropertyMapPtr pMergedProperties = lcl_SearchParentStyleSheetAndMergeProperties(pStyleSheet, pStyleSheetTable);
343 :
344 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
345 : dmapper_logger->startElement("mergedProps");
346 : pMergedProperties->dumpXml( dmapper_logger );
347 : dmapper_logger->endElement();
348 : #endif
349 :
350 0 : m_aTableProperties->InsertProps(pMergedProperties);
351 0 : m_aTableProperties->InsertProps(pTableProps);
352 :
353 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
354 : dmapper_logger->startElement("TableProperties");
355 : m_aTableProperties->dumpXml( dmapper_logger );
356 : dmapper_logger->endElement();
357 : #endif
358 50 : }
359 : }
360 :
361 : // Set the table default attributes for the cells
362 102 : rInfo.pTableDefaults->InsertProps(m_aTableProperties);
363 :
364 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
365 : dmapper_logger->startElement("TableDefaults");
366 : rInfo.pTableDefaults->dumpXml( dmapper_logger );
367 : dmapper_logger->endElement();
368 : #endif
369 :
370 102 : m_aTableProperties->getValue( TablePropertyMap::GAP_HALF, nGapHalf );
371 102 : m_aTableProperties->getValue( TablePropertyMap::LEFT_MARGIN, nLeftMargin );
372 :
373 : m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_LEFT,
374 102 : rInfo.nLeftBorderDistance );
375 : m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_RIGHT,
376 102 : rInfo.nRightBorderDistance );
377 : m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_TOP,
378 102 : rInfo.nTopBorderDistance );
379 : m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_BOTTOM,
380 102 : rInfo.nBottomBorderDistance );
381 :
382 102 : table::TableBorderDistances aDistances;
383 : aDistances.IsTopDistanceValid =
384 : aDistances.IsBottomDistanceValid =
385 : aDistances.IsLeftDistanceValid =
386 102 : aDistances.IsRightDistanceValid = sal_True;
387 102 : aDistances.TopDistance = static_cast<sal_Int16>( rInfo.nTopBorderDistance );
388 102 : aDistances.BottomDistance = static_cast<sal_Int16>( rInfo.nBottomBorderDistance );
389 102 : aDistances.LeftDistance = static_cast<sal_Int16>( rInfo.nLeftBorderDistance );
390 102 : aDistances.RightDistance = static_cast<sal_Int16>( rInfo.nRightBorderDistance );
391 :
392 102 : m_aTableProperties->Insert( PROP_TABLE_BORDER_DISTANCES, false, uno::makeAny( aDistances ) );
393 :
394 : // Set table above/bottom spacing to 0.
395 : // TODO: handle 'Around' text wrapping mode
396 102 : m_aTableProperties->Insert( PROP_TOP_MARGIN, true, uno::makeAny( sal_Int32( 0 ) ) );
397 102 : m_aTableProperties->Insert( PROP_BOTTOM_MARGIN, true, uno::makeAny( sal_Int32( 0 ) ) );
398 :
399 : //table border settings
400 102 : table::TableBorder aTableBorder;
401 102 : table::BorderLine2 aBorderLine, aLeftBorder;
402 :
403 102 : if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_TOP_BORDER, rInfo, aBorderLine))
404 : {
405 32 : aTableBorder.TopLine = aBorderLine;
406 32 : aTableBorder.IsTopLineValid = sal_True;
407 : }
408 102 : if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_BOTTOM_BORDER, rInfo, aBorderLine))
409 : {
410 34 : aTableBorder.BottomLine = aBorderLine;
411 34 : aTableBorder.IsBottomLineValid = sal_True;
412 : }
413 102 : if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_LEFT_BORDER, rInfo, aLeftBorder))
414 : {
415 34 : aTableBorder.LeftLine = aLeftBorder;
416 34 : aTableBorder.IsLeftLineValid = sal_True;
417 34 : rInfo.nLeftBorderDistance += aLeftBorder.LineWidth * 0.5;
418 : }
419 102 : if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_RIGHT_BORDER, rInfo, aBorderLine))
420 : {
421 34 : aTableBorder.RightLine = aBorderLine;
422 34 : aTableBorder.IsRightLineValid = sal_True;
423 : }
424 102 : if (lcl_extractTableBorderProperty(m_aTableProperties, META_PROP_HORIZONTAL_BORDER, rInfo, aBorderLine))
425 : {
426 32 : aTableBorder.HorizontalLine = aBorderLine;
427 32 : aTableBorder.IsHorizontalLineValid = sal_True;
428 : }
429 102 : if (lcl_extractTableBorderProperty(m_aTableProperties, META_PROP_VERTICAL_BORDER, rInfo, aBorderLine))
430 : {
431 34 : aTableBorder.VerticalLine = aBorderLine;
432 34 : aTableBorder.IsVerticalLineValid = sal_True;
433 : }
434 :
435 102 : aTableBorder.Distance = 0;
436 102 : aTableBorder.IsDistanceValid = sal_False;
437 :
438 102 : m_aTableProperties->Insert( PROP_TABLE_BORDER, false, uno::makeAny( aTableBorder ) );
439 :
440 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
441 : lcl_debug_TableBorder(aTableBorder);
442 : #endif
443 :
444 : // Table position in Office is computed in 2 different ways :
445 : // - top level tables: the goal is to have in-cell text starting at table indent pos (tblInd),
446 : // so table's position depends on table's cells margin
447 : // - nested tables: the goal is to have left-most border starting at table_indent pos
448 102 : if (rInfo.nNestLevel > 1)
449 : {
450 10 : m_aTableProperties->Insert( PROP_LEFT_MARGIN, false, uno::makeAny( nLeftMargin - nGapHalf ));
451 : }
452 : else
453 : {
454 92 : m_aTableProperties->Insert( PROP_LEFT_MARGIN, false, uno::makeAny( nLeftMargin - nGapHalf - rInfo.nLeftBorderDistance ));
455 : }
456 :
457 102 : m_aTableProperties->getValue( TablePropertyMap::TABLE_WIDTH, nTableWidth );
458 102 : if( nTableWidth > 0 )
459 102 : m_aTableProperties->Insert( PROP_WIDTH, false, uno::makeAny( nTableWidth ));
460 :
461 102 : sal_Int32 nHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH;
462 102 : m_aTableProperties->getValue( TablePropertyMap::HORI_ORIENT, nHoriOrient ) ;
463 102 : m_aTableProperties->Insert( PROP_HORI_ORIENT, false, uno::makeAny( sal_Int16(nHoriOrient) ) );
464 :
465 : //fill default value - if not available
466 : const PropertyMap::const_iterator aRepeatIter =
467 102 : m_aTableProperties->find( PropertyDefinition( PROP_HEADER_ROW_COUNT, false ) );
468 102 : if( aRepeatIter == m_aTableProperties->end() )
469 102 : m_aTableProperties->Insert( PROP_HEADER_ROW_COUNT, false, uno::makeAny( (sal_Int32)0 ));
470 :
471 102 : rInfo.aTableProperties = m_aTableProperties->GetPropertyValues();
472 :
473 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
474 : dmapper_logger->startElement("debug.tableprops");
475 : m_aTableProperties->dumpXml( dmapper_logger );
476 : dmapper_logger->endElement();
477 : #endif
478 :
479 : }
480 :
481 708 : return pTableStyle;
482 : }
483 :
484 708 : CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(TableInfo & rInfo)
485 : {
486 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
487 : dmapper_logger->startElement("getCellProperties");
488 : #endif
489 :
490 708 : CellPropertyValuesSeq_t aCellProperties( m_aCellProperties.size() );
491 :
492 708 : if ( !m_aCellProperties.size() )
493 : {
494 : #ifdef DEBUG_DOMAINMAPPER
495 : dmapper_logger->endElement();
496 : #endif
497 : return aCellProperties;
498 : }
499 : // std::vector< std::vector<PropertyMapPtr> > m_aCellProperties
500 116 : PropertyMapVector2::const_iterator aRowOfCellsIterator = m_aCellProperties.begin();
501 116 : PropertyMapVector2::const_iterator aRowOfCellsIteratorEnd = m_aCellProperties.end();
502 116 : PropertyMapVector2::const_iterator aLastRowIterator = m_aCellProperties.end() - 1;
503 116 : sal_Int32 nRow = 0;
504 :
505 : //it's a uno::Sequence< beans::PropertyValues >*
506 116 : RowPropertyValuesSeq_t* pCellProperties = aCellProperties.getArray();
507 400 : while( aRowOfCellsIterator != aRowOfCellsIteratorEnd )
508 : {
509 : //aRowOfCellsIterator points to a vector of PropertyMapPtr
510 168 : PropertyMapVector1::const_iterator aCellIterator = aRowOfCellsIterator->begin();
511 168 : PropertyMapVector1::const_iterator aCellIteratorEnd = aRowOfCellsIterator->end();
512 :
513 : // Get the row style properties
514 168 : sal_Int32 nRowStyleMask = sal_Int32( 0 );
515 168 : PropertyMapPtr pRowProps = m_aRowProperties[nRow];
516 168 : if ( pRowProps.get( ) )
517 : {
518 154 : PropertyMap::iterator pTcCnfStyleIt = pRowProps->find( PropertyDefinition( PROP_CNF_STYLE, true ) );
519 154 : if ( pTcCnfStyleIt != pRowProps->end( ) )
520 : {
521 0 : if ( rInfo.pTableStyle )
522 : {
523 0 : OUString sMask;
524 0 : pTcCnfStyleIt->second >>= sMask;
525 0 : nRowStyleMask = sMask.toInt32( 2 );
526 : }
527 0 : pRowProps->erase( pTcCnfStyleIt );
528 : }
529 : }
530 :
531 168 : sal_Int32 nCell = 0;
532 168 : pCellProperties[nRow].realloc( aRowOfCellsIterator->size() );
533 168 : beans::PropertyValues* pSingleCellProperties = pCellProperties[nRow].getArray();
534 916 : while( aCellIterator != aCellIteratorEnd )
535 : {
536 580 : PropertyMapPtr pAllCellProps( new PropertyMap );
537 :
538 580 : PropertyMapVector1::const_iterator aLastCellIterator = aRowOfCellsIterator->end() - 1;
539 580 : bool bIsEndCol = aCellIterator == aLastCellIterator;
540 580 : bool bIsEndRow = aRowOfCellsIterator == aLastRowIterator;
541 :
542 : //aCellIterator points to a PropertyMapPtr;
543 580 : if( aCellIterator->get() )
544 : {
545 580 : if ( rInfo.pTableDefaults->size( ) )
546 0 : pAllCellProps->InsertProps(rInfo.pTableDefaults);
547 :
548 : // Fill the cell properties with the ones of the style
549 580 : sal_Int32 nCellStyleMask = 0;
550 : const PropertyMap::iterator aCnfStyleIter =
551 580 : aCellIterator->get()->find( PropertyDefinition( PROP_CNF_STYLE, false ) );
552 580 : if ( aCnfStyleIter != aCellIterator->get( )->end( ) )
553 : {
554 0 : if ( rInfo.pTableStyle ) {
555 0 : OUString sMask;
556 0 : aCnfStyleIter->second >>= sMask;
557 0 : nCellStyleMask = sMask.toInt32( 2 );
558 : }
559 0 : aCellIterator->get( )->erase( aCnfStyleIter );
560 : }
561 :
562 580 : if ( rInfo.pTableStyle )
563 : {
564 0 : PropertyMapPtr pStyleProps = rInfo.pTableStyle->GetProperties( nCellStyleMask + nRowStyleMask );
565 0 : pAllCellProps->InsertProps(pStyleProps);
566 : }
567 :
568 : // Remove properties from style/row that aren't allowed in cells
569 : const PropertyMap::iterator aDefaultRepeatIt =
570 580 : pAllCellProps->find(
571 1160 : PropertyDefinition( PROP_HEADER_ROW_COUNT, false ) );
572 580 : if ( aDefaultRepeatIt != pAllCellProps->end( ) )
573 0 : pAllCellProps->erase( aDefaultRepeatIt );
574 :
575 : // Then add the cell properties
576 580 : pAllCellProps->InsertProps(*aCellIterator);
577 580 : aCellIterator->get( )->swap( *pAllCellProps.get( ) );
578 :
579 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
580 : dmapper_logger->startElement("cell");
581 : dmapper_logger->attribute("cell", nCell);
582 : dmapper_logger->attribute("row", nRow);
583 : #endif
584 :
585 580 : lcl_computeCellBorders( rInfo.pTableBorders, *aCellIterator, nCell, nRow, bIsEndCol, bIsEndRow );
586 :
587 : //now set the default left+right border distance TODO: there's an sprm containing the default distance!
588 : const PropertyMap::const_iterator aLeftDistanceIter =
589 580 : aCellIterator->get()->find( PropertyDefinition(PROP_LEFT_BORDER_DISTANCE, false) );
590 580 : if( aLeftDistanceIter == aCellIterator->get()->end() )
591 : aCellIterator->get()->Insert( PROP_LEFT_BORDER_DISTANCE, false,
592 580 : uno::makeAny(rInfo.nLeftBorderDistance ) );
593 : const PropertyMap::const_iterator aRightDistanceIter =
594 580 : aCellIterator->get()->find( PropertyDefinition(PROP_RIGHT_BORDER_DISTANCE, false) );
595 580 : if( aRightDistanceIter == aCellIterator->get()->end() )
596 : aCellIterator->get()->Insert( PROP_RIGHT_BORDER_DISTANCE, false,
597 580 : uno::makeAny((sal_Int32) rInfo.nRightBorderDistance ) );
598 :
599 : const PropertyMap::const_iterator aTopDistanceIter =
600 580 : aCellIterator->get()->find( PropertyDefinition(PROP_TOP_BORDER_DISTANCE, false) );
601 580 : if( aTopDistanceIter == aCellIterator->get()->end() )
602 : aCellIterator->get()->Insert( PROP_TOP_BORDER_DISTANCE, false,
603 580 : uno::makeAny((sal_Int32) rInfo.nTopBorderDistance ) );
604 :
605 : const PropertyMap::const_iterator aBottomDistanceIter =
606 580 : aCellIterator->get()->find( PropertyDefinition(PROP_BOTTOM_BORDER_DISTANCE, false) );
607 580 : if( aBottomDistanceIter == aCellIterator->get()->end() )
608 : aCellIterator->get()->Insert( PROP_BOTTOM_BORDER_DISTANCE, false,
609 580 : uno::makeAny((sal_Int32) rInfo.nBottomBorderDistance ) );
610 :
611 580 : pSingleCellProperties[nCell] = aCellIterator->get()->GetPropertyValues();
612 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
613 : dmapper_logger->endElement();
614 : #endif
615 : }
616 580 : ++nCell;
617 580 : ++aCellIterator;
618 580 : }
619 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
620 : //-->debug cell properties
621 : {
622 : OUString sNames;
623 : const uno::Sequence< beans::PropertyValues > aDebugCurrentRow = aCellProperties[nRow];
624 : sal_Int32 nDebugCells = aDebugCurrentRow.getLength();
625 : (void) nDebugCells;
626 : for( sal_Int32 nDebugCell = 0; nDebugCell < nDebugCells; ++nDebugCell)
627 : {
628 : const uno::Sequence< beans::PropertyValue >& aDebugCellProperties = aDebugCurrentRow[nDebugCell];
629 : sal_Int32 nDebugCellProperties = aDebugCellProperties.getLength();
630 : for( sal_Int32 nDebugProperty = 0; nDebugProperty < nDebugCellProperties; ++nDebugProperty)
631 : {
632 : const OUString sName = aDebugCellProperties[nDebugProperty].Name;
633 : sNames += sName;
634 : sNames += OUString('-');
635 : }
636 : sNames += OUString('\n');
637 : }
638 : (void)sNames;
639 : }
640 : //--<
641 : #endif
642 168 : ++nRow;
643 168 : ++aRowOfCellsIterator;
644 168 : }
645 :
646 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
647 : dmapper_logger->endElement();
648 : #endif
649 :
650 0 : return aCellProperties;
651 : }
652 :
653 708 : RowPropertyValuesSeq_t DomainMapperTableHandler::endTableGetRowProperties()
654 : {
655 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
656 : dmapper_logger->startElement("getRowProperties");
657 : #endif
658 :
659 708 : RowPropertyValuesSeq_t aRowProperties( m_aRowProperties.size() );
660 708 : PropertyMapVector1::const_iterator aRowIter = m_aRowProperties.begin();
661 708 : PropertyMapVector1::const_iterator aRowIterEnd = m_aRowProperties.end();
662 708 : sal_Int32 nRow = 0;
663 1584 : while( aRowIter != aRowIterEnd )
664 : {
665 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
666 : dmapper_logger->startElement("rowProps.row");
667 : #endif
668 168 : if( aRowIter->get() )
669 : {
670 : //set default to 'break across pages"
671 154 : if( aRowIter->get()->find( PropertyDefinition( PROP_IS_SPLIT_ALLOWED, false )) == aRowIter->get()->end())
672 126 : aRowIter->get()->Insert( PROP_IS_SPLIT_ALLOWED, false, uno::makeAny(sal_True ) );
673 :
674 154 : aRowProperties[nRow] = (*aRowIter)->GetPropertyValues();
675 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
676 : ((*aRowIter)->dumpXml( dmapper_logger ));
677 : lcl_DumpPropertyValues(dmapper_logger, aRowProperties[nRow]);
678 : #endif
679 : }
680 168 : ++nRow;
681 168 : ++aRowIter;
682 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
683 : dmapper_logger->endElement();
684 : #endif
685 : }
686 :
687 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
688 : dmapper_logger->endElement();
689 : #endif
690 :
691 708 : return aRowProperties;
692 : }
693 :
694 708 : void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel)
695 : {
696 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
697 : dmapper_logger->startElement("tablehandler.endTable");
698 : #endif
699 :
700 708 : TableInfo aTableInfo;
701 708 : aTableInfo.nNestLevel = nestedTableLevel;
702 708 : aTableInfo.pTableStyle = endTableGetTableStyle(aTableInfo);
703 : // expands to uno::Sequence< Sequence< beans::PropertyValues > >
704 :
705 708 : CellPropertyValuesSeq_t aCellProperties = endTableGetCellProperties(aTableInfo);
706 :
707 708 : RowPropertyValuesSeq_t aRowProperties = endTableGetRowProperties();
708 :
709 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
710 : lcl_DumpPropertyValueSeq(dmapper_logger, aRowProperties);
711 : #endif
712 :
713 708 : if (m_pTableSeq->getLength() > 0)
714 : {
715 116 : uno::Reference<text::XTextRange> xStart;
716 116 : uno::Reference<text::XTextRange> xEnd;
717 : // If we want to make this table a floating one.
718 116 : bool bFloating = !m_rDMapper_Impl.getTableManager().getTableVertAnchor().isEmpty();
719 : // Additional checks: if we can do this.
720 116 : if (bFloating && (*m_pTableSeq)[0].getLength() > 0 && (*m_pTableSeq)[0][0].getLength() > 0)
721 : {
722 2 : xStart = (*m_pTableSeq)[0][0][0];
723 2 : uno::Sequence< uno::Sequence< uno::Reference<text::XTextRange> > >& rLastRow = (*m_pTableSeq)[m_pTableSeq->getLength() - 1];
724 2 : uno::Sequence< uno::Reference<text::XTextRange> >& rLastCell = rLastRow[rLastRow.getLength() - 1];
725 2 : xEnd = rLastCell[1];
726 : }
727 116 : uno::Reference<text::XTextTable> xTable;
728 : try
729 : {
730 116 : if (m_xText.is())
731 : {
732 184 : xTable = m_xText->convertToTable(*m_pTableSeq,
733 : aCellProperties,
734 : aRowProperties,
735 184 : aTableInfo.aTableProperties);
736 :
737 92 : if (xTable.is())
738 92 : m_xTableRange = xTable->getAnchor( );
739 : }
740 : }
741 0 : catch ( const lang::IllegalArgumentException &e )
742 : {
743 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
744 : fprintf( stderr, "Conversion to table error: %s\n",
745 : OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
746 : dmapper_logger->chars(std::string("failed to import table!"));
747 : #else
748 : (void)e;
749 : #endif
750 : }
751 0 : catch ( const uno::Exception &e )
752 : {
753 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
754 : fprintf( stderr, "Exception during table creation: %s\n",
755 : OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr( ) );
756 : #else
757 : (void) e;
758 : #endif
759 : }
760 :
761 : // If we have a table with a start and an end position, we should make it a floating one.
762 116 : if (xTable.is() && xStart.is() && xEnd.is())
763 : {
764 2 : uno::Reference<beans::XPropertySet> xTableProperties(xTable, uno::UNO_QUERY);
765 2 : uno::Sequence< beans::PropertyValue > aFrameProperties(16);
766 2 : beans::PropertyValue* pFrameProperties = aFrameProperties.getArray();
767 2 : pFrameProperties[0].Name = "Width";
768 2 : pFrameProperties[0].Value = xTableProperties->getPropertyValue("Width");
769 :
770 2 : pFrameProperties[1].Name = "LeftBorderDistance";
771 2 : pFrameProperties[1].Value <<= sal_Int32(0);
772 2 : pFrameProperties[2].Name = "RightBorderDistance";
773 2 : pFrameProperties[2].Value <<= sal_Int32(0);
774 2 : pFrameProperties[3].Name = "TopBorderDistance";
775 2 : pFrameProperties[3].Value <<= sal_Int32(0);
776 2 : pFrameProperties[4].Name = "BottomBorderDistance";
777 2 : pFrameProperties[4].Value <<= sal_Int32(0);
778 :
779 2 : pFrameProperties[5].Name = "LeftMargin";
780 2 : pFrameProperties[5].Value <<= sal_Int32(0);
781 2 : pFrameProperties[6].Name = "RightMargin";
782 2 : pFrameProperties[6].Value <<= sal_Int32(0);
783 2 : pFrameProperties[7].Name = "TopMargin";
784 2 : pFrameProperties[7].Value <<= sal_Int32(0);
785 2 : pFrameProperties[8].Name = "BottomMargin";
786 2 : pFrameProperties[8].Value <<= sal_Int32(0);
787 :
788 2 : table::BorderLine2 aEmptyBorder;
789 2 : pFrameProperties[9].Name = "TopBorder";
790 2 : pFrameProperties[9].Value <<= aEmptyBorder;
791 2 : pFrameProperties[10].Name = "BottomBorder";
792 2 : pFrameProperties[10].Value <<= aEmptyBorder;
793 2 : pFrameProperties[11].Name = "LeftBorder";
794 2 : pFrameProperties[11].Value <<= aEmptyBorder;
795 2 : pFrameProperties[12].Name = "RightBorder";
796 2 : pFrameProperties[12].Value <<= aEmptyBorder;
797 :
798 2 : pFrameProperties[13].Name = "HoriOrient";
799 2 : pFrameProperties[13].Value <<= text::HoriOrientation::NONE;
800 2 : pFrameProperties[14].Name = "HoriOrientRelation";
801 2 : pFrameProperties[14].Value <<= text::RelOrientation::FRAME;
802 : // A non-zero left margin would move the table out of the frame, move the frame itself instead.
803 2 : pFrameProperties[15].Name = "HoriOrientPosition";
804 2 : pFrameProperties[15].Value <<= xTableProperties->getPropertyValue("LeftMargin");
805 2 : xTableProperties->setPropertyValue("LeftMargin", uno::makeAny(sal_Int32(0)));
806 :
807 2 : uno::Reference< text::XTextContent > xFrame = m_xText->convertToTextFrame(xStart, xEnd, aFrameProperties);
808 116 : }
809 : }
810 :
811 708 : m_aTableProperties.reset();
812 708 : m_aCellProperties.clear();
813 708 : m_aRowProperties.clear();
814 :
815 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
816 : dmapper_logger->endElement();
817 : dmapper_logger->endElement();
818 : #endif
819 708 : }
820 :
821 168 : void DomainMapperTableHandler::startRow(unsigned int nCells,
822 : TablePropertyMapPtr pProps)
823 : {
824 168 : m_aRowProperties.push_back( pProps );
825 168 : m_aCellProperties.push_back( PropertyMapVector1() );
826 :
827 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
828 : dmapper_logger->startElement("table.row");
829 : dmapper_logger->attribute("cells", nCells);
830 : if (pProps != NULL)
831 : pProps->dumpXml(dmapper_logger);
832 : #endif
833 :
834 168 : m_pRowSeq = RowSequencePointer_t(new RowSequence_t(nCells));
835 168 : m_nCellIndex = 0;
836 168 : }
837 :
838 168 : void DomainMapperTableHandler::endRow()
839 : {
840 168 : (*m_pTableSeq)[m_nRowIndex] = *m_pRowSeq;
841 168 : ++m_nRowIndex;
842 168 : m_nCellIndex = 0;
843 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
844 : dmapper_logger->endElement();
845 : #endif
846 168 : }
847 :
848 580 : void DomainMapperTableHandler::startCell(const Handle_t & start,
849 : TablePropertyMapPtr pProps )
850 : {
851 580 : sal_uInt32 nRow = m_aRowProperties.size();
852 580 : if ( pProps.get( ) )
853 430 : m_aCellProperties[nRow - 1].push_back( pProps );
854 : else
855 : {
856 : // Adding an empty cell properties map to be able to get
857 : // the table defaults properties
858 150 : TablePropertyMapPtr pEmptyProps( new TablePropertyMap( ) );
859 150 : m_aCellProperties[nRow - 1].push_back( pEmptyProps );
860 : }
861 :
862 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
863 : dmapper_logger->startElement("table.cell");
864 : dmapper_logger->startElement("table.cell.start");
865 : dmapper_logger->chars(toString(start));
866 : dmapper_logger->endElement();
867 : lcl_printProperties( pProps );
868 : #endif
869 :
870 : //add a new 'row' of properties
871 580 : m_pCellSeq = CellSequencePointer_t(new CellSequence_t(2));
872 580 : if (!start.get())
873 632 : return;
874 528 : (*m_pCellSeq)[0] = start->getStart();
875 : }
876 :
877 580 : void DomainMapperTableHandler::endCell(const Handle_t & end)
878 : {
879 : #ifdef DEBUG_DMAPPER_TABLE_HANDLER
880 : dmapper_logger->startElement("table.cell.end");
881 : dmapper_logger->chars(toString(end));
882 : dmapper_logger->endElement();
883 : dmapper_logger->endElement();
884 : #endif
885 :
886 580 : if (!end.get())
887 632 : return;
888 528 : (*m_pCellSeq)[1] = end->getEnd();
889 528 : (*m_pRowSeq)[m_nCellIndex] = *m_pCellSeq;
890 528 : ++m_nCellIndex;
891 : }
892 :
893 30 : }}
894 :
895 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|