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