1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
27 #include <comphelper/interfacecontainer4.hxx>
28 #include <o3tl/any.hxx>
29 #include <o3tl/safeint.hxx>
30 #include <tools/UnitConversion.hxx>
31 #include <editeng/memberids.h>
33 #include <swtypes.hxx>
35 #include <unocoll.hxx>
39 #include <section.hxx>
40 #include <unocrsr.hxx>
42 #include <swtblfmt.hxx>
44 #include <IDocumentUndoRedo.hxx>
45 #include <IDocumentContentOperations.hxx>
46 #include <IDocumentFieldsAccess.hxx>
47 #include <IDocumentRedlineAccess.hxx>
48 #include <IDocumentState.hxx>
49 #include <IDocumentLayoutAccess.hxx>
50 #include <shellres.hxx>
55 #include <vcl/svapp.hxx>
56 #include <fmtfsize.hxx>
57 #include <tblafmt.hxx>
59 #include <cellatr.hxx>
60 #include <fmtpdsc.hxx>
61 #include <pagedesc.hxx>
63 #include <rootfrm.hxx>
65 #include <redline.hxx>
66 #include <unoport.hxx>
67 #include <unocrsrhelper.hxx>
68 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
69 #include <com/sun/star/text/WrapTextMode.hpp>
70 #include <com/sun/star/text/TextContentAnchorType.hpp>
71 #include <com/sun/star/text/TableColumnSeparator.hpp>
72 #include <com/sun/star/text/VertOrientation.hpp>
73 #include <com/sun/star/text/XTextSection.hpp>
74 #include <com/sun/star/table/TableBorder.hpp>
75 #include <com/sun/star/table/TableBorder2.hpp>
76 #include <com/sun/star/table/BorderLine2.hpp>
77 #include <com/sun/star/table/TableBorderDistances.hpp>
78 #include <com/sun/star/beans/PropertyAttribute.hpp>
79 #include <com/sun/star/chart/XChartDataChangeEventListener.hpp>
80 #include <com/sun/star/chart/ChartDataChangeEvent.hpp>
81 #include <com/sun/star/table/CellContentType.hpp>
82 #include <unotextrange.hxx>
83 #include <unotextcursor.hxx>
84 #include <unoparagraph.hxx>
85 #include <svl/numformat.hxx>
86 #include <svl/zforlist.hxx>
87 #include <editeng/formatbreakitem.hxx>
88 #include <editeng/shaditem.hxx>
89 #include <editeng/lrspitem.hxx>
90 #include <editeng/ulspitem.hxx>
91 #include <fmtornt.hxx>
92 #include <editeng/keepitem.hxx>
93 #include <fmtlsplt.hxx>
95 #include <SwStyleNameMapper.hxx>
97 #include <sortopt.hxx>
98 #include <sal/log.hxx>
99 #include <editeng/frmdiritem.hxx>
100 #include <comphelper/servicehelper.hxx>
101 #include <comphelper/string.hxx>
102 #include <cppuhelper/supportsservice.hxx>
103 #include <comphelper/sequence.hxx>
104 #include <comphelper/sequenceashashmap.hxx>
105 #include <swtable.hxx>
108 #include <itabenum.hxx>
109 #include <frameformats.hxx>
110 #include <o3tl/string_view.hxx>
112 using namespace ::com::sun::star
;
113 using ::editeng::SvxBorderLine
;
117 template<typename Tcoretype
, typename Tunotype
>
118 struct FindUnoInstanceHint final
: SfxHint
120 FindUnoInstanceHint(Tcoretype
* pCore
) : m_pCore(pCore
), m_pResult(nullptr) {};
121 const Tcoretype
* const m_pCore
;
122 mutable rtl::Reference
<Tunotype
> m_pResult
;
124 SwFrameFormat
* lcl_EnsureCoreConnected(SwFrameFormat
* pFormat
, cppu::OWeakObject
* pObject
)
127 throw uno::RuntimeException("Lost connection to core objects", pObject
);
130 SwTable
* lcl_EnsureTableNotComplex(SwTable
* pTable
, cppu::OWeakObject
* pObject
)
132 if(pTable
->IsTableComplex())
133 throw uno::RuntimeException("Table too complex", pObject
);
137 chart::ChartDataChangeEvent
createChartEvent(uno::Reference
<uno::XInterface
> const& xSource
)
139 //TODO: find appropriate settings of the Event
140 chart::ChartDataChangeEvent event
;
141 event
.Source
= xSource
;
142 event
.Type
= chart::ChartDataChangeType_ALL
;
143 event
.StartColumn
= 0;
150 void lcl_SendChartEvent(std::unique_lock
<std::mutex
>& rGuard
,
151 uno::Reference
<uno::XInterface
> const& xSource
,
152 ::comphelper::OInterfaceContainerHelper4
<chart::XChartDataChangeEventListener
> & rListeners
)
154 if (rListeners
.getLength(rGuard
))
155 rListeners
.notifyEach(rGuard
,
156 &chart::XChartDataChangeEventListener::chartDataChanged
,
157 createChartEvent(xSource
));
161 #define UNO_TABLE_COLUMN_SUM 10000
164 static bool lcl_LineToSvxLine(const table::BorderLine
& rLine
, SvxBorderLine
& rSvxLine
)
166 rSvxLine
.SetColor(Color(ColorTransparency
, rLine
.Color
));
168 rSvxLine
.GuessLinesWidths( SvxBorderLineStyle::NONE
,
169 o3tl::toTwips(rLine
.OuterLineWidth
, o3tl::Length::mm100
),
170 o3tl::toTwips(rLine
.InnerLineWidth
, o3tl::Length::mm100
),
171 o3tl::toTwips(rLine
.LineDistance
, o3tl::Length::mm100
) );
173 return rLine
.InnerLineWidth
> 0 || rLine
.OuterLineWidth
> 0;
176 /// @throws lang::IllegalArgumentException
177 /// @throws uno::RuntimeException
178 static void lcl_SetSpecialProperty(SwFrameFormat
* pFormat
,
179 const SfxItemPropertyMapEntry
* pEntry
,
180 const uno::Any
& aValue
)
182 // special treatment for "non-items"
185 case FN_TABLE_HEADLINE_REPEAT
:
186 case FN_TABLE_HEADLINE_COUNT
:
188 SwTable
* pTable
= SwTable::FindTable( pFormat
);
189 UnoActionContext
aAction(pFormat
->GetDoc());
190 if( pEntry
->nWID
== FN_TABLE_HEADLINE_REPEAT
)
192 pFormat
->GetDoc()->SetRowsToRepeat( *pTable
, aValue
.get
<bool>() ? 1 : 0 );
196 sal_Int32 nRepeat
= 0;
198 if( nRepeat
>= 0 && nRepeat
< SAL_MAX_UINT16
)
199 pFormat
->GetDoc()->SetRowsToRepeat( *pTable
, o3tl::narrowing
<sal_uInt16
>(nRepeat
) );
204 case FN_TABLE_IS_RELATIVE_WIDTH
:
206 case FN_TABLE_RELATIVE_WIDTH
:
208 SwFormatFrameSize
aSz( pFormat
->GetFrameSize() );
209 if(FN_TABLE_WIDTH
== pEntry
->nWID
)
211 sal_Int32 nWidth
= 0;
213 aSz
.SetWidthPercent(0);
214 aSz
.SetWidth ( o3tl::toTwips(nWidth
, o3tl::Length::mm100
) );
216 else if(FN_TABLE_RELATIVE_WIDTH
== pEntry
->nWID
)
220 if(nSet
&& nSet
<=100)
221 aSz
.SetWidthPercent( static_cast<sal_uInt8
>(nSet
) );
223 else if(FN_TABLE_IS_RELATIVE_WIDTH
== pEntry
->nWID
)
225 if(!aValue
.get
<bool>())
226 aSz
.SetWidthPercent(0);
229 lang::IllegalArgumentException aExcept
;
230 aExcept
.Message
= "relative width cannot be switched on with this property";
234 pFormat
->GetDoc()->SetAttr(aSz
, *pFormat
);
241 aValue
>>= sPageStyle
;
242 const SwPageDesc
* pDesc
= nullptr;
243 if (!sPageStyle
.isEmpty())
245 SwStyleNameMapper::FillUIName(sPageStyle
, sPageStyle
, SwGetPoolIdFromName::PageDesc
);
246 pDesc
= SwPageDesc::GetByName(*pFormat
->GetDoc(), sPageStyle
);
248 SwFormatPageDesc
aDesc( pDesc
);
249 pFormat
->GetDoc()->SetAttr(aDesc
, *pFormat
);
254 throw lang::IllegalArgumentException();
258 static uno::Any
lcl_GetSpecialProperty(SwFrameFormat
* pFormat
, const SfxItemPropertyMapEntry
* pEntry
)
262 case FN_TABLE_HEADLINE_REPEAT
:
263 case FN_TABLE_HEADLINE_COUNT
:
265 SwTable
* pTable
= SwTable::FindTable( pFormat
);
266 const sal_uInt16 nRepeat
= pTable
->GetRowsToRepeat();
267 if(pEntry
->nWID
== FN_TABLE_HEADLINE_REPEAT
)
268 return uno::Any(nRepeat
> 0);
269 return uno::Any(sal_Int32(nRepeat
));
273 case FN_TABLE_IS_RELATIVE_WIDTH
:
274 case FN_TABLE_RELATIVE_WIDTH
:
277 const SwFormatFrameSize
& rSz
= pFormat
->GetFrameSize();
278 if(FN_TABLE_WIDTH
== pEntry
->nWID
)
279 rSz
.QueryValue(aRet
, MID_FRMSIZE_WIDTH
|CONVERT_TWIPS
);
280 else if(FN_TABLE_RELATIVE_WIDTH
== pEntry
->nWID
)
281 rSz
.QueryValue(aRet
, MID_FRMSIZE_REL_WIDTH
);
283 aRet
<<= (0 != rSz
.GetWidthPercent());
289 const SfxItemSet
& rSet
= pFormat
->GetAttrSet();
290 if(const SwFormatPageDesc
* pItem
= rSet
.GetItemIfSet(RES_PAGEDESC
, false))
292 const SwPageDesc
* pDsc
= pItem
->GetPageDesc();
294 return uno::Any(SwStyleNameMapper::GetProgName(pDsc
->GetName(), SwGetPoolIdFromName::PageDesc
));
296 return uno::Any(OUString());
300 return uno::Any(text::TextContentAnchorType_AT_PARAGRAPH
);
302 case FN_UNO_ANCHOR_TYPES
:
304 uno::Sequence
<text::TextContentAnchorType
> aTypes
{text::TextContentAnchorType_AT_PARAGRAPH
};
305 return uno::Any(aTypes
);
309 return uno::Any(text::WrapTextMode_NONE
);
311 case FN_PARAM_LINK_DISPLAY_NAME
:
312 return uno::Any(pFormat
->GetName());
314 case FN_UNO_REDLINE_NODE_START
:
315 case FN_UNO_REDLINE_NODE_END
:
317 SwTable
* pTable
= SwTable::FindTable( pFormat
);
318 SwNode
* pTableNode
= pTable
->GetTableNode();
319 if(FN_UNO_REDLINE_NODE_END
== pEntry
->nWID
)
320 pTableNode
= pTableNode
->EndOfSectionNode();
321 for(const SwRangeRedline
* pRedline
: pFormat
->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable())
323 const SwNode
& rRedPointNode
= pRedline
->GetPointNode();
324 const SwNode
& rRedMarkNode
= pRedline
->GetMarkNode();
325 if(rRedPointNode
== *pTableNode
|| rRedMarkNode
== *pTableNode
)
327 const SwNode
& rStartOfRedline
= SwNodeIndex(rRedPointNode
) <= SwNodeIndex(rRedMarkNode
) ?
328 rRedPointNode
: rRedMarkNode
;
329 bool bIsStart
= &rStartOfRedline
== pTableNode
;
330 return uno::Any(SwXRedlinePortion::CreateRedlineProperties(*pRedline
, bIsStart
));
338 /** get position of a cell with a given name
340 * If everything was OK, the indices for column and row are changed (both >= 0).
341 * In case of errors, at least one of them is < 0.
343 * Also since the implementations of tables does not really have columns using
344 * this function is appropriate only for tables that are not complex (i.e.
345 * where IsTableComplex() returns false).
347 * @param rCellName e.g. A1..Z1, a1..z1, AA1..AZ1, Aa1..Az1, BA1..BZ1, Ba1..Bz1, ...
348 * @param [IN,OUT] o_rColumn (0-based)
349 * @param [IN,OUT] o_rRow (0-based)
351 //TODO: potential for throwing proper exceptions instead of having every caller to check for errors
352 void SwXTextTable::GetCellPosition(std::u16string_view aCellName
, sal_Int32
& o_rColumn
, sal_Int32
& o_rRow
)
354 o_rColumn
= o_rRow
= -1; // default return values indicating failure
355 const sal_Int32 nLen
= aCellName
.size();
358 SAL_WARN("sw.uno", "failed to get column or row index");
361 sal_Int32 nRowPos
= 0;
364 if (aCellName
[nRowPos
]>='0' && aCellName
[nRowPos
]<='9')
370 if (nRowPos
<=0 || nRowPos
>=nLen
)
373 sal_Int32 nColIdx
= 0;
374 for (sal_Int32 i
= 0; i
< nRowPos
; ++i
)
379 const sal_Unicode cChar
= aCellName
[i
];
380 if ('A' <= cChar
&& cChar
<= 'Z')
381 nColIdx
+= cChar
- 'A';
382 else if ('a' <= cChar
&& cChar
<= 'z')
383 nColIdx
+= 26 + cChar
- 'a';
386 nColIdx
= -1; // sth failed
392 o_rRow
= o3tl::toInt32(aCellName
.substr(nRowPos
)) - 1; // - 1 because indices ought to be 0 based
395 /** compare position of two cells (check rows first)
397 * @note this function probably also make sense only
398 * for cell names of non-complex tables
400 * @param rCellName1 e.g. "A1" (non-empty string with valid cell name)
401 * @param rCellName2 e.g. "A1" (non-empty string with valid cell name)
402 * @return -1 if cell_1 < cell_2; 0 if both cells are equal; +1 if cell_1 > cell_2
404 int sw_CompareCellsByRowFirst( std::u16string_view aCellName1
, std::u16string_view aCellName2
)
406 sal_Int32 nCol1
= -1, nRow1
= -1, nCol2
= -1, nRow2
= -1;
407 SwXTextTable::GetCellPosition( aCellName1
, nCol1
, nRow1
);
408 SwXTextTable::GetCellPosition( aCellName2
, nCol2
, nRow2
);
410 if (nRow1
< nRow2
|| (nRow1
== nRow2
&& nCol1
< nCol2
))
412 else if (nCol1
== nCol2
&& nRow1
== nRow2
)
418 /** compare position of two cells (check columns first)
420 * @note this function probably also make sense only
421 * for cell names of non-complex tables
423 * @param rCellName1 e.g. "A1" (non-empty string with valid cell name)
424 * @param rCellName2 e.g. "A1" (non-empty string with valid cell name)
425 * @return -1 if cell_1 < cell_2; 0 if both cells are equal; +1 if cell_1 > cell_2
427 int sw_CompareCellsByColFirst( std::u16string_view aCellName1
, std::u16string_view aCellName2
)
429 sal_Int32 nCol1
= -1, nRow1
= -1, nCol2
= -1, nRow2
= -1;
430 SwXTextTable::GetCellPosition( aCellName1
, nCol1
, nRow1
);
431 SwXTextTable::GetCellPosition( aCellName2
, nCol2
, nRow2
);
433 if (nCol1
< nCol2
|| (nCol1
== nCol2
&& nRow1
< nRow2
))
435 else if (nRow1
== nRow2
&& nCol1
== nCol2
)
441 /** compare position of two cell ranges
443 * @note this function probably also make sense only
444 * for cell names of non-complex tables
446 * @param rRange1StartCell e.g. "A1" (non-empty string with valid cell name)
447 * @param rRange1EndCell e.g. "A1" (non-empty string with valid cell name)
448 * @param rRange2StartCell e.g. "A1" (non-empty string with valid cell name)
449 * @param rRange2EndCell e.g. "A1" (non-empty string with valid cell name)
450 * @param bCmpColsFirst if <true> position in columns will be compared first before rows
452 * @return -1 if cell_range_1 < cell_range_2; 0 if both cell ranges are equal; +1 if cell_range_1 > cell_range_2
454 int sw_CompareCellRanges(
455 std::u16string_view aRange1StartCell
, std::u16string_view aRange1EndCell
,
456 std::u16string_view aRange2StartCell
, std::u16string_view aRange2EndCell
,
459 int (*pCompareCells
)( std::u16string_view
, std::u16string_view
) =
460 bCmpColsFirst
? &sw_CompareCellsByColFirst
: &sw_CompareCellsByRowFirst
;
462 int nCmpResStartCells
= pCompareCells( aRange1StartCell
, aRange2StartCell
);
463 if ((-1 == nCmpResStartCells
) ||
464 ( 0 == nCmpResStartCells
&&
465 -1 == pCompareCells( aRange1EndCell
, aRange2EndCell
) ))
467 else if (0 == nCmpResStartCells
&&
468 0 == pCompareCells( aRange1EndCell
, aRange2EndCell
))
474 /** get cell name at a specified coordinate
476 * @param nColumn column index (0-based)
477 * @param nRow row index (0-based)
478 * @return the cell name
480 OUString
sw_GetCellName( sal_Int32 nColumn
, sal_Int32 nRow
)
482 if (nColumn
< 0 || nRow
< 0)
485 sw_GetTableBoxColStr( static_cast< sal_uInt16
>(nColumn
), sCellName
);
486 return sCellName
+ OUString::number( nRow
+ 1 );
489 /** Find the top left or bottom right corner box in given table.
490 Consider nested lines when finding the box.
492 @param rTableLines the table
493 @param i_bTopLeft if true, find top left box, otherwise find bottom
496 static const SwTableBox
* lcl_FindCornerTableBox(const SwTableLines
& rTableLines
, const bool i_bTopLeft
)
498 const SwTableLines
* pLines(&rTableLines
);
501 assert(!pLines
->empty());
504 const SwTableLine
* pLine(i_bTopLeft
? pLines
->front() : pLines
->back());
506 const SwTableBoxes
& rBoxes(pLine
->GetTabBoxes());
507 assert(rBoxes
.size() != 0);
508 const SwTableBox
* pBox
= i_bTopLeft
? rBoxes
.front() : rBoxes
.back();
510 if (pBox
->GetSttNd())
512 pLines
= &pBox
->GetTabLines();
516 /** cleanup order in a range
518 * Sorts the input to a uniform format. I.e. for the four possible representation
519 * A1:C5, C5:A1, A5:C1, C1:A5
520 * the result will be always A1:C5.
522 * @param [IN,OUT] rCell1 cell name (will be modified to upper-left corner), e.g. "A1" (non-empty string with valid cell name)
523 * @param [IN,OUT] rCell2 cell name (will be modified to lower-right corner), e.g. "A1" (non-empty string with valid cell name)
525 void sw_NormalizeRange(OUString
&rCell1
, OUString
&rCell2
)
527 sal_Int32 nCol1
= -1, nRow1
= -1, nCol2
= -1, nRow2
= -1;
528 SwXTextTable::GetCellPosition( rCell1
, nCol1
, nRow1
);
529 SwXTextTable::GetCellPosition( rCell2
, nCol2
, nRow2
);
530 if (nCol2
< nCol1
|| nRow2
< nRow1
)
532 rCell1
= sw_GetCellName( std::min(nCol1
, nCol2
), std::min(nRow1
, nRow2
) );
533 rCell2
= sw_GetCellName( std::max(nCol1
, nCol2
), std::max(nRow1
, nRow2
) );
537 void SwRangeDescriptor::Normalize()
540 std::swap(nBottom
, nTop
);
542 std::swap(nLeft
, nRight
);
545 static rtl::Reference
<SwXCell
> lcl_CreateXCell(SwFrameFormat
* pFormat
, sal_Int32 nColumn
, sal_Int32 nRow
)
547 const OUString sCellName
= sw_GetCellName(nColumn
, nRow
);
548 SwTable
* pTable
= SwTable::FindTable(pFormat
);
549 SwTableBox
* pBox
= const_cast<SwTableBox
*>(pTable
->GetTableBox(sCellName
));
552 return SwXCell::CreateXCell(pFormat
, pBox
, pTable
);
555 static void lcl_InspectLines(SwTableLines
& rLines
, std::vector
<OUString
>& rAllNames
)
557 for(auto pLine
: rLines
)
559 for(auto pBox
: pLine
->GetTabBoxes())
561 if(!pBox
->GetName().isEmpty() && pBox
->getRowSpan() > 0)
562 rAllNames
.push_back(pBox
->GetName());
563 SwTableLines
& rBoxLines
= pBox
->GetTabLines();
564 if(!rBoxLines
.empty())
565 lcl_InspectLines(rBoxLines
, rAllNames
);
570 static bool lcl_FormatTable(SwFrameFormat
const * pTableFormat
)
572 bool bHasFrames
= false;
573 SwIterator
<SwFrame
,SwFormat
> aIter( *pTableFormat
);
574 for(SwFrame
* pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next())
576 vcl::RenderContext
* pRenderContext
= pFrame
->getRootFrame()->GetCurrShell()->GetOut();
577 // mba: no TYPEINFO for SwTabFrame
578 if(!pFrame
->IsTabFrame())
580 DisableCallbackAction
a(*pFrame
->getRootFrame());
581 SwTabFrame
* pTabFrame
= static_cast<SwTabFrame
*>(pFrame
);
582 if(pTabFrame
->isFrameAreaDefinitionValid())
583 pTabFrame
->InvalidatePos();
584 pTabFrame
->SetONECalcLowers();
585 pTabFrame
->Calc(pRenderContext
);
591 static void lcl_CursorSelect(SwPaM
& rCursor
, bool bExpand
)
595 if(!rCursor
.HasMark())
598 else if(rCursor
.HasMark())
599 rCursor
.DeleteMark();
602 static void lcl_GetTableSeparators(uno::Any
& rRet
, SwTable
const * pTable
, SwTableBox
const * pBox
, bool bRow
)
605 aCols
.SetLeftMin ( 0 );
607 aCols
.SetRight ( UNO_TABLE_COLUMN_SUM
);
608 aCols
.SetRightMax( UNO_TABLE_COLUMN_SUM
);
610 pTable
->GetTabCols( aCols
, pBox
, false, bRow
);
612 const size_t nSepCount
= aCols
.Count();
613 uno::Sequence
< text::TableColumnSeparator
> aColSeq(nSepCount
);
614 text::TableColumnSeparator
* pArray
= aColSeq
.getArray();
616 for(size_t i
= 0; i
< nSepCount
; ++i
)
618 pArray
[i
].Position
= static_cast< sal_Int16
>(aCols
[i
]);
619 pArray
[i
].IsVisible
= !aCols
.IsHidden(i
);
620 if(!bRow
&& !pArray
[i
].IsVisible
)
631 static void lcl_SetTableSeparators(const uno::Any
& rVal
, SwTable
* pTable
, SwTableBox
const * pBox
, bool bRow
, SwDoc
* pDoc
)
635 aOldCols
.SetLeftMin ( 0 );
636 aOldCols
.SetLeft ( 0 );
637 aOldCols
.SetRight ( UNO_TABLE_COLUMN_SUM
);
638 aOldCols
.SetRightMax( UNO_TABLE_COLUMN_SUM
);
640 pTable
->GetTabCols( aOldCols
, pBox
, false, bRow
);
641 const size_t nOldCount
= aOldCols
.Count();
642 // there is no use in setting tab cols if there is only one column
647 o3tl::tryAccess
<uno::Sequence
<text::TableColumnSeparator
>>(rVal
);
648 if(!pSepSeq
|| static_cast<size_t>(pSepSeq
->getLength()) != nOldCount
)
650 SwTabCols
aCols(aOldCols
);
651 const text::TableColumnSeparator
* pArray
= pSepSeq
->getConstArray();
652 tools::Long nLastValue
= 0;
653 //sal_Int32 nTableWidth = aCols.GetRight() - aCols.GetLeft();
654 for(size_t i
= 0; i
< nOldCount
; ++i
)
656 aCols
[i
] = pArray
[i
].Position
;
657 if(bool(pArray
[i
].IsVisible
) == aCols
.IsHidden(i
) ||
658 (!bRow
&& aCols
.IsHidden(i
)) ||
659 aCols
[i
] < nLastValue
||
660 UNO_TABLE_COLUMN_SUM
< aCols
[i
] )
661 return; // probably this should assert()
662 nLastValue
= aCols
[i
];
664 pDoc
->SetTabCols(*pTable
, aCols
, aOldCols
, pBox
, bRow
);
667 /* non UNO function call to set string in SwXCell */
668 void sw_setString( SwXCell
&rCell
, const OUString
&rText
,
669 bool bKeepNumberFormat
= false )
673 SwFrameFormat
* pBoxFormat
= rCell
.m_pBox
->ClaimFrameFormat();
674 pBoxFormat
->LockModify();
675 pBoxFormat
->ResetFormatAttr( RES_BOXATR_FORMULA
);
676 pBoxFormat
->ResetFormatAttr( RES_BOXATR_VALUE
);
677 if (!bKeepNumberFormat
)
678 pBoxFormat
->SetFormatAttr( SwTableBoxNumFormat(/*default Text*/) );
679 pBoxFormat
->UnlockModify();
681 rCell
.SwXText::setString(rText
);
685 /* non UNO function call to set value in SwXCell */
686 void sw_setValue( SwXCell
&rCell
, double nVal
)
690 // first this text (maybe) needs to be deleted
691 SwNodeOffset nNdPos
= rCell
.m_pBox
->IsValidNumTextNd();
692 if(NODE_OFFSET_MAX
!= nNdPos
)
693 sw_setString( rCell
, OUString(), true ); // true == keep number format
694 SwDoc
* pDoc
= rCell
.GetDoc();
695 UnoActionContext
aAction(pDoc
);
696 SwFrameFormat
* pBoxFormat
= rCell
.m_pBox
->ClaimFrameFormat();
697 SfxItemSetFixed
<RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
> aSet(pDoc
->GetAttrPool());
699 //!! do we need to set a new number format? Yes, if
700 // - there is no current number format
701 // - the current number format is not a number format according to the number formatter, but rather a text format
702 const SwTableBoxNumFormat
* pNumFormat
= pBoxFormat
->GetAttrSet().GetItemIfSet(RES_BOXATR_FORMAT
);
704 || pDoc
->GetNumberFormatter()->IsTextFormat(pNumFormat
->GetValue()))
706 aSet
.Put(SwTableBoxNumFormat(0));
709 SwTableBoxValue
aVal(nVal
);
711 pDoc
->SetTableBoxFormulaAttrs( *rCell
.m_pBox
, aSet
);
713 pDoc
->getIDocumentFieldsAccess().UpdateTableFields(SwTable::FindTable(rCell
.GetFrameFormat()));
717 SwXCell::SwXCell(SwFrameFormat
* pTableFormat
, SwTableBox
* pBx
, size_t const nPos
) :
718 SwXText(pTableFormat
->GetDoc(), CursorType::TableText
),
719 m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TABLE_CELL
)),
721 m_pStartNode(nullptr),
722 m_pTableFormat(pTableFormat
),
725 StartListening(pTableFormat
->GetNotifier());
728 SwXCell::SwXCell(SwFrameFormat
* pTableFormat
, const SwStartNode
& rStartNode
) :
729 SwXText(pTableFormat
->GetDoc(), CursorType::TableText
),
730 m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TABLE_CELL
)),
732 m_pStartNode(&rStartNode
),
733 m_pTableFormat(pTableFormat
),
736 StartListening(pTableFormat
->GetNotifier());
741 SolarMutexGuard aGuard
;
745 uno::Sequence
< uno::Type
> SAL_CALL
SwXCell::getTypes( )
747 return comphelper::concatSequences(
748 SwXCellBaseClass::getTypes(),
753 uno::Sequence
< sal_Int8
> SAL_CALL
SwXCell::getImplementationId( )
755 return css::uno::Sequence
<sal_Int8
>();
758 void SAL_CALL
SwXCell::acquire( ) noexcept
760 SwXCellBaseClass::acquire();
763 void SAL_CALL
SwXCell::release( ) noexcept
765 SolarMutexGuard aGuard
;
767 SwXCellBaseClass::release();
770 uno::Any SAL_CALL
SwXCell::queryInterface( const uno::Type
& aType
)
772 uno::Any aRet
= SwXText::queryInterface(aType
);
773 if(aRet
.getValueType() == cppu::UnoType
<void>::get())
774 aRet
= SwXCellBaseClass::queryInterface(aType
);
778 const SwStartNode
*SwXCell::GetStartNode() const
780 const SwStartNode
* pSttNd
= nullptr;
782 if( m_pStartNode
|| IsValid() )
783 pSttNd
= m_pStartNode
? m_pStartNode
: m_pBox
->GetSttNd();
788 bool SwXCell::IsValid() const
790 // FIXME: this is now a const method, to make SwXText::IsValid invisible
791 // but the const_cast here are still ridiculous. TODO: find a better way.
792 SwFrameFormat
* pTableFormat
= m_pBox
? GetFrameFormat() : nullptr;
795 const_cast<SwXCell
*>(this)->m_pBox
= nullptr;
799 SwTable
* pTable
= SwTable::FindTable( pTableFormat
);
800 SwTableBox
const*const pFoundBox
=
801 const_cast<SwXCell
*>(this)->FindBox(pTable
, m_pBox
);
804 const_cast<SwXCell
*>(this)->m_pBox
= nullptr;
807 return nullptr != m_pBox
;
810 OUString
SwXCell::getFormula()
812 SolarMutexGuard aGuard
;
815 SwTableBoxFormula
aFormula( m_pBox
->GetFrameFormat()->GetTableBoxFormula() );
816 SwTable
* pTable
= SwTable::FindTable( GetFrameFormat() );
817 aFormula
.PtrToBoxNm( pTable
);
818 return aFormula
.GetFormula();
821 ///@see sw_setValue (TODO: seems to be copy and paste programming here)
822 void SwXCell::setFormula(const OUString
& rFormula
)
824 SolarMutexGuard aGuard
;
827 // first this text (maybe) needs to be deleted
828 SwNodeOffset nNdPos
= m_pBox
->IsValidNumTextNd();
829 if(SwNodeOffset(USHRT_MAX
) == nNdPos
)
830 sw_setString( *this, OUString(), true );
831 OUString
sFormula(comphelper::string::stripStart(rFormula
, ' '));
832 if( !sFormula
.isEmpty() && '=' == sFormula
[0] )
833 sFormula
= sFormula
.copy( 1 );
834 SwTableBoxFormula
aFormula( sFormula
);
835 SwDoc
* pMyDoc
= GetDoc();
836 UnoActionContext
aAction(pMyDoc
);
837 SfxItemSetFixed
<RES_BOXATR_FORMAT
, RES_BOXATR_FORMULA
> aSet(pMyDoc
->GetAttrPool());
838 SwFrameFormat
* pBoxFormat
= m_pBox
->GetFrameFormat();
839 const SwTableBoxNumFormat
* pNumFormat
=
840 pBoxFormat
->GetAttrSet().GetItemIfSet(RES_BOXATR_FORMAT
);
842 || pMyDoc
->GetNumberFormatter()->IsTextFormat(pNumFormat
->GetValue()))
844 aSet
.Put(SwTableBoxNumFormat(0));
847 GetDoc()->SetTableBoxFormulaAttrs( *m_pBox
, aSet
);
849 pMyDoc
->getIDocumentFieldsAccess().UpdateTableFields(SwTable::FindTable(GetFrameFormat()));
852 double SwXCell::getValue()
854 SolarMutexGuard aGuard
;
855 // #i112652# a table cell may contain NaN as a value, do not filter that
856 if(IsValid() && !getString().isEmpty())
857 return m_pBox
->GetFrameFormat()->GetTableBoxValue().GetValue();
858 return std::numeric_limits
<double>::quiet_NaN();
861 void SwXCell::setValue(double rValue
)
863 SolarMutexGuard aGuard
;
864 sw_setValue( *this, rValue
);
867 table::CellContentType
SwXCell::getType()
869 SolarMutexGuard aGuard
;
871 table::CellContentType nRes
= table::CellContentType_EMPTY
;
872 sal_uInt32 nNdPos
= m_pBox
->IsFormulaOrValueBox();
875 case 0 : nRes
= table::CellContentType_TEXT
; break;
876 case USHRT_MAX
: nRes
= table::CellContentType_EMPTY
; break;
877 case RES_BOXATR_VALUE
: nRes
= table::CellContentType_VALUE
; break;
878 case RES_BOXATR_FORMULA
: nRes
= table::CellContentType_FORMULA
; break;
880 OSL_FAIL( "unexpected case" );
885 void SwXCell::setString(const OUString
& aString
)
887 SolarMutexGuard aGuard
;
888 sw_setString( *this, aString
);
891 sal_Int32
SwXCell::getError()
893 SolarMutexGuard aGuard
;
894 OUString sContent
= getString();
895 return sal_Int32(sContent
== SwViewShell::GetShellRes()->aCalc_Error
);
898 rtl::Reference
< SwXTextCursor
> SwXCell::createXTextCursor()
900 if(!m_pStartNode
&& !IsValid())
901 throw uno::RuntimeException();
902 const SwStartNode
* pSttNd
= m_pStartNode
? m_pStartNode
: m_pBox
->GetSttNd();
903 SwPosition
aPos(*pSttNd
);
904 rtl::Reference
<SwXTextCursor
> const pXCursor
=
905 new SwXTextCursor(*GetDoc(), this, CursorType::TableText
, aPos
);
906 auto& rUnoCursor(pXCursor
->GetCursor());
907 rUnoCursor
.Move(fnMoveForward
, GoInNode
);
911 rtl::Reference
<SwXTextCursor
> SwXCell::createXTextCursorByRange(const uno::Reference
< text::XTextRange
> & xTextPosition
)
913 SwUnoInternalPaM
aPam(*GetDoc());
914 if((!m_pStartNode
&& !IsValid()) || !::sw::XTextRangeToSwPaM(aPam
, xTextPosition
))
915 throw uno::RuntimeException();
916 const SwStartNode
* pSttNd
= m_pStartNode
? m_pStartNode
: m_pBox
->GetSttNd();
918 SwStartNode
* p1
= aPam
.GetPointNode().StartOfSectionNode();
919 while(p1
->IsSectionNode())
920 p1
= p1
->StartOfSectionNode();
923 return new SwXTextCursor(*GetDoc(), this, CursorType::TableText
,
924 *aPam
.GetPoint(), aPam
.GetMark());
927 uno::Reference
< beans::XPropertySetInfo
> SwXCell::getPropertySetInfo()
929 static uno::Reference
< beans::XPropertySetInfo
> xRef
= m_pPropSet
->getPropertySetInfo();
933 void SwXCell::setPropertyValue(const OUString
& rPropertyName
, const uno::Any
& aValue
)
935 SolarMutexGuard aGuard
;
938 // Hack to support hidden property to transfer textDirection
939 if(rPropertyName
== "FRMDirection")
941 SvxFrameDirectionItem
aItem(SvxFrameDirection::Environment
, RES_FRAMEDIR
);
942 aItem
.PutValue(aValue
, 0);
943 m_pBox
->GetFrameFormat()->SetFormatAttr(aItem
);
945 else if(rPropertyName
== "TableRedlineParams")
947 // Get the table row properties
948 uno::Sequence
<beans::PropertyValue
> tableCellProperties
= aValue
.get
< uno::Sequence
< beans::PropertyValue
> >();
949 comphelper::SequenceAsHashMap
aPropMap(tableCellProperties
);
950 OUString sRedlineType
;
951 if(!(aPropMap
.getValue("RedlineType") >>= sRedlineType
))
952 throw beans::UnknownPropertyException("No redline type property: ", static_cast<cppu::OWeakObject
*>(this));
954 // Create a 'Table Cell Redline' object
955 SwUnoCursorHelper::makeTableCellRedline(*m_pBox
, sRedlineType
, tableCellProperties
);
959 else if (rPropertyName
== "VerticalMerge")
961 //Hack to allow clearing of numbering from the paragraphs in the merged cells.
962 SwNodeIndex
aIdx(*GetStartNode(), 1);
963 const SwNode
* pEndNd
= aIdx
.GetNode().EndOfSectionNode();
964 while (&aIdx
.GetNode() != pEndNd
)
966 SwTextNode
* pNd
= aIdx
.GetNode().GetTextNode();
968 pNd
->SetCountedInList(false);
974 auto pEntry(m_pPropSet
->getPropertyMap().getByName(rPropertyName
));
977 // not a table property: ignore it, if it is a paragraph/character property
978 const SfxItemPropertySet
& rParaPropSet
= *aSwMapProvider
.GetPropertySet(PROPERTY_MAP_PARAGRAPH
);
979 pEntry
= rParaPropSet
.getPropertyMap().getByName(rPropertyName
);
986 throw beans::UnknownPropertyException(rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
987 if(pEntry
->nWID
!= FN_UNO_CELL_ROW_SPAN
)
989 SwFrameFormat
* pBoxFormat
= m_pBox
->ClaimFrameFormat();
990 SwAttrSet
aSet(pBoxFormat
->GetAttrSet());
991 m_pPropSet
->setPropertyValue(rPropertyName
, aValue
, aSet
);
992 pBoxFormat
->GetDoc()->SetAttr(aSet
, *pBoxFormat
);
994 else if(aValue
.isExtractableTo(cppu::UnoType
<sal_Int32
>::get()))
995 m_pBox
->setRowSpan(aValue
.get
<sal_Int32
>());
999 uno::Any
SwXCell::getPropertyValue(const OUString
& rPropertyName
)
1001 SolarMutexGuard aGuard
;
1004 auto pEntry(m_pPropSet
->getPropertyMap().getByName(rPropertyName
));
1006 throw beans::UnknownPropertyException(rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
1007 switch(pEntry
->nWID
)
1009 case FN_UNO_CELL_ROW_SPAN
:
1010 return uno::Any(m_pBox
->getRowSpan());
1011 case FN_UNO_TEXT_SECTION
:
1013 SwFrameFormat
* pTableFormat
= GetFrameFormat();
1014 SwTable
* pTable
= SwTable::FindTable(pTableFormat
);
1015 SwTableNode
* pTableNode
= pTable
->GetTableNode();
1016 SwSectionNode
* pSectionNode
= pTableNode
->FindSectionNode();
1019 SwSection
& rSect
= pSectionNode
->GetSection();
1020 return uno::Any(SwXTextSections::GetObject(*rSect
.GetFormat()));
1023 case FN_UNO_CELL_NAME
:
1024 return uno::Any(m_pBox
->GetName());
1025 case FN_UNO_REDLINE_NODE_START
:
1026 case FN_UNO_REDLINE_NODE_END
:
1028 //redline can only be returned if it's a living object
1029 return SwXText::getPropertyValue(rPropertyName
);
1032 case FN_UNO_PARENT_TEXT
:
1034 if (!m_xParentText
.is())
1036 const SwStartNode
* pSttNd
= m_pBox
->GetSttNd();
1040 const SwTableNode
* pTableNode
= pSttNd
->FindTableNode();
1044 SwPosition
aPos(*pTableNode
);
1045 SwDoc
& rDoc
= aPos
.GetDoc();
1046 m_xParentText
= sw::CreateParentXText(rDoc
, aPos
);
1049 return uno::Any(m_xParentText
);
1054 const SwAttrSet
& rSet
= m_pBox
->GetFrameFormat()->GetAttrSet();
1056 m_pPropSet
->getPropertyValue(rPropertyName
, rSet
, aResult
);
1062 void SwXCell::addPropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1063 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1065 void SwXCell::removePropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1066 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1068 void SwXCell::addVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1069 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1071 void SwXCell::removeVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1072 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1074 uno::Reference
<container::XEnumeration
> SwXCell::createEnumeration()
1076 SolarMutexGuard aGuard
;
1078 return uno::Reference
<container::XEnumeration
>();
1079 const SwStartNode
* pSttNd
= m_pBox
->GetSttNd();
1080 SwPosition
aPos(*pSttNd
);
1081 auto pUnoCursor(GetDoc()->CreateUnoCursor(aPos
));
1082 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
1083 // remember table and start node for later travelling
1084 // (used in export of tables in tables)
1085 return SwXParagraphEnumeration::Create(this, pUnoCursor
, CursorType::TableText
, m_pBox
);
1088 uno::Type SAL_CALL
SwXCell::getElementType()
1090 return cppu::UnoType
<text::XTextRange
>::get();
1093 sal_Bool
SwXCell::hasElements()
1098 void SwXCell::Notify(const SfxHint
& rHint
)
1100 if(rHint
.GetId() == SfxHintId::Dying
)
1102 m_pTableFormat
= nullptr;
1104 else if(auto pFindHint
= dynamic_cast<const FindUnoInstanceHint
<SwTableBox
, SwXCell
>*>(&rHint
))
1106 if(!pFindHint
->m_pResult
&& pFindHint
->m_pCore
== GetTableBox())
1107 pFindHint
->m_pResult
= this;
1111 rtl::Reference
<SwXCell
> SwXCell::CreateXCell(SwFrameFormat
* pTableFormat
, SwTableBox
* pBox
, SwTable
*pTable
)
1113 if(!pTableFormat
|| !pBox
)
1116 pTable
= SwTable::FindTable(pTableFormat
);
1117 SwTableSortBoxes::const_iterator it
= pTable
->GetTabSortBoxes().find(pBox
);
1118 if(it
== pTable
->GetTabSortBoxes().end())
1120 size_t const nPos
= it
- pTable
->GetTabSortBoxes().begin();
1121 FindUnoInstanceHint
<SwTableBox
, SwXCell
> aHint
{pBox
};
1122 pTableFormat
->GetNotifier().Broadcast(aHint
);
1123 return aHint
.m_pResult
? aHint
.m_pResult
.get() : new SwXCell(pTableFormat
, pBox
, nPos
);
1126 /** search if a box exists in a table
1128 * @param pTable the table to search in
1129 * @param pBox2 box model to find
1130 * @return the box if existent in pTable, 0 (!!!) if not found
1132 SwTableBox
* SwXCell::FindBox(SwTable
* pTable
, SwTableBox
* pBox2
)
1134 // check if nFndPos happens to point to the right table box
1135 if( m_nFndPos
< pTable
->GetTabSortBoxes().size() &&
1136 pBox2
== pTable
->GetTabSortBoxes()[ m_nFndPos
] )
1139 // if not, seek the entry (and return, if successful)
1140 SwTableSortBoxes::const_iterator it
= pTable
->GetTabSortBoxes().find( pBox2
);
1141 if( it
!= pTable
->GetTabSortBoxes().end() )
1143 m_nFndPos
= it
- pTable
->GetTabSortBoxes().begin();
1147 // box not found: reset nFndPos pointer
1148 m_nFndPos
= NOTFOUND
;
1152 double SwXCell::GetForcedNumericalValue() const
1154 if(table::CellContentType_TEXT
!= const_cast<SwXCell
*>(this)->getType())
1156 // now we'll try to get a useful numerical value
1157 // from the text in the cell...
1159 SvNumberFormatter
* pNumFormatter(const_cast<SvNumberFormatter
*>(GetDoc()->GetNumberFormatter()));
1160 // look for SwTableBoxNumFormat value in parents as well
1161 auto pBoxFormat(GetTableBox()->GetFrameFormat());
1162 const SwTableBoxNumFormat
* pNumFormat
= pBoxFormat
->GetAttrSet().GetItemIfSet(RES_BOXATR_FORMAT
);
1166 // please note that the language of the numberformat
1167 // is implicitly coded into the below value as well
1168 nFIndex
= pNumFormat
->GetValue();
1170 // since the current value indicates a text format but the call
1171 // to 'IsNumberFormat' below won't work for text formats
1172 // we need to get rid of the part that indicates the text format.
1173 // According to ER this can be done like this:
1174 nFIndex
-= (nFIndex
% SV_COUNTRY_LANGUAGE_OFFSET
);
1178 // system language is probably not the best possible choice
1179 // but since we have to guess anyway (because the language of at
1180 // the text is NOT the one used for the number format!)
1181 // it is at least conform to what is used in
1182 // SwTableShell::Execute when
1183 // SID_ATTR_NUMBERFORMAT_VALUE is set...
1184 LanguageType eLang
= LANGUAGE_SYSTEM
;
1185 nFIndex
= pNumFormatter
->GetStandardIndex( eLang
);
1188 if (!const_cast<SwDoc
*>(GetDoc())->IsNumberFormat(const_cast<SwXCell
*>(this)->getString(), nFIndex
, fTmp
))
1189 return std::numeric_limits
<double>::quiet_NaN();
1193 uno::Any
SwXCell::GetAny() const
1196 throw uno::RuntimeException();
1197 // check if table box value item is set
1198 auto pBoxFormat(m_pBox
->GetFrameFormat());
1199 const bool bIsNum
= pBoxFormat
->GetItemState(RES_BOXATR_VALUE
, false) == SfxItemState::SET
;
1200 return bIsNum
? uno::Any(getValue()) : uno::Any(const_cast<SwXCell
*>(this)->getString());
1203 OUString
SwXCell::getImplementationName()
1204 { return "SwXCell"; }
1206 sal_Bool
SwXCell::supportsService(const OUString
& rServiceName
)
1207 { return cppu::supportsService(this, rServiceName
); }
1209 uno::Sequence
< OUString
> SwXCell::getSupportedServiceNames()
1210 { return {"com.sun.star.text.CellProperties"}; }
1212 OUString
SwXTextTableRow::getImplementationName()
1213 { return "SwXTextTableRow"; }
1215 sal_Bool
SwXTextTableRow::supportsService(const OUString
& rServiceName
)
1216 { return cppu::supportsService(this, rServiceName
); }
1218 uno::Sequence
< OUString
> SwXTextTableRow::getSupportedServiceNames()
1219 { return {"com.sun.star.text.TextTableRow"}; }
1222 SwXTextTableRow::SwXTextTableRow(SwFrameFormat
* pFormat
, SwTableLine
* pLn
) :
1225 m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TEXT_TABLE_ROW
))
1227 StartListening(m_pFormat
->GetNotifier());
1230 SwXTextTableRow::~SwXTextTableRow()
1232 SolarMutexGuard aGuard
;
1236 uno::Reference
< beans::XPropertySetInfo
> SwXTextTableRow::getPropertySetInfo()
1238 static uno::Reference
<beans::XPropertySetInfo
> xRef
= m_pPropSet
->getPropertySetInfo();
1242 void SwXTextTableRow::setPropertyValue(const OUString
& rPropertyName
, const uno::Any
& aValue
)
1244 SolarMutexGuard aGuard
;
1245 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
1246 SwTable
* pTable
= SwTable::FindTable( pFormat
);
1247 SwTableLine
* pLn
= SwXTextTableRow::FindLine(pTable
, m_pLine
);
1251 // Check for a specific property
1252 if ( rPropertyName
== "TableRedlineParams" )
1254 // Get the table row properties
1255 uno::Sequence
< beans::PropertyValue
> tableRowProperties
= aValue
.get
< uno::Sequence
< beans::PropertyValue
> >();
1256 comphelper::SequenceAsHashMap
aPropMap( tableRowProperties
);
1257 OUString sRedlineType
;
1258 if( !(aPropMap
.getValue("RedlineType") >>= sRedlineType
) )
1260 throw beans::UnknownPropertyException("No redline type property: ", static_cast < cppu::OWeakObject
* > ( this ) );
1263 // Create a 'Table Row Redline' object
1264 SwUnoCursorHelper::makeTableRowRedline( *pLn
, sRedlineType
, tableRowProperties
);
1269 const SfxItemPropertyMapEntry
* pEntry
=
1270 m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
1271 SwDoc
* pDoc
= pFormat
->GetDoc();
1273 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
1274 if ( pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
1275 throw beans::PropertyVetoException("Property is read-only: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
1277 switch(pEntry
->nWID
)
1279 case FN_UNO_ROW_HEIGHT
:
1280 case FN_UNO_ROW_AUTO_HEIGHT
:
1282 SwFormatFrameSize
aFrameSize(pLn
->GetFrameFormat()->GetFrameSize());
1283 if(FN_UNO_ROW_AUTO_HEIGHT
== pEntry
->nWID
)
1285 bool bSet
= *o3tl::doAccess
<bool>(aValue
);
1286 aFrameSize
.SetHeightSizeType(bSet
? SwFrameSize::Variable
: SwFrameSize::Fixed
);
1290 sal_Int32 nHeight
= 0;
1292 Size
aSz(aFrameSize
.GetSize());
1293 aSz
.setHeight( o3tl::toTwips(nHeight
, o3tl::Length::mm100
) );
1294 aFrameSize
.SetSize(aSz
);
1296 pDoc
->SetAttr(aFrameSize
, *pLn
->ClaimFrameFormat());
1300 case FN_UNO_TABLE_COLUMN_SEPARATORS
:
1302 UnoActionContext
aContext(pDoc
);
1303 SwTable
* pTable2
= SwTable::FindTable( pFormat
);
1304 lcl_SetTableSeparators(aValue
, pTable2
, m_pLine
->GetTabBoxes()[0], true, pDoc
);
1310 SwFrameFormat
* pLnFormat
= pLn
->ClaimFrameFormat();
1311 SwAttrSet
aSet(pLnFormat
->GetAttrSet());
1312 m_pPropSet
->setPropertyValue(*pEntry
, aValue
, aSet
);
1313 pDoc
->SetAttr(aSet
, *pLnFormat
);
1319 uno::Any
SwXTextTableRow::getPropertyValue(const OUString
& rPropertyName
)
1321 SolarMutexGuard aGuard
;
1323 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
1324 SwTable
* pTable
= SwTable::FindTable( pFormat
);
1325 SwTableLine
* pLn
= SwXTextTableRow::FindLine(pTable
, m_pLine
);
1328 const SfxItemPropertyMapEntry
* pEntry
=
1329 m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
1331 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
1333 switch(pEntry
->nWID
)
1335 case FN_UNO_ROW_HEIGHT
:
1336 case FN_UNO_ROW_AUTO_HEIGHT
:
1338 const SwFormatFrameSize
& rSize
= pLn
->GetFrameFormat()->GetFrameSize();
1339 if(FN_UNO_ROW_AUTO_HEIGHT
== pEntry
->nWID
)
1341 aRet
<<= SwFrameSize::Variable
== rSize
.GetHeightSizeType();
1344 aRet
<<= static_cast<sal_Int32
>(convertTwipToMm100(rSize
.GetSize().Height()));
1348 case FN_UNO_TABLE_COLUMN_SEPARATORS
:
1350 lcl_GetTableSeparators(aRet
, pTable
, m_pLine
->GetTabBoxes()[0], true);
1356 const SwAttrSet
& rSet
= pLn
->GetFrameFormat()->GetAttrSet();
1357 m_pPropSet
->getPropertyValue(*pEntry
, rSet
, aRet
);
1364 void SwXTextTableRow::addPropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1365 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1367 void SwXTextTableRow::removePropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1368 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1370 void SwXTextTableRow::addVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1371 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1373 void SwXTextTableRow::removeVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1374 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1376 void SwXTextTableRow::Notify(const SfxHint
& rHint
)
1378 if(rHint
.GetId() == SfxHintId::Dying
)
1380 m_pFormat
= nullptr;
1381 } else if(auto pFindHint
= dynamic_cast<const FindUnoInstanceHint
<SwTableLine
, SwXTextTableRow
>*>(&rHint
))
1383 if(!pFindHint
->m_pCore
&& pFindHint
->m_pCore
== m_pLine
)
1384 pFindHint
->m_pResult
= this;
1388 SwTableLine
* SwXTextTableRow::FindLine(SwTable
* pTable
, SwTableLine
const * pLine
)
1390 for(const auto& pCurrentLine
: pTable
->GetTabLines())
1391 if(pCurrentLine
== pLine
)
1392 return pCurrentLine
;
1396 // SwXTextTableCursor
1398 OUString
SwXTextTableCursor::getImplementationName()
1399 { return "SwXTextTableCursor"; }
1401 sal_Bool
SwXTextTableCursor::supportsService(const OUString
& rServiceName
)
1402 { return cppu::supportsService(this, rServiceName
); }
1404 void SwXTextTableCursor::release() noexcept
1406 SolarMutexGuard aGuard
;
1407 SwXTextTableCursor_Base::release();
1410 const SwPaM
* SwXTextTableCursor::GetPaM() const { return &GetCursor(); }
1411 SwPaM
* SwXTextTableCursor::GetPaM() { return &GetCursor(); }
1412 const SwDoc
* SwXTextTableCursor::GetDoc() const { return GetFrameFormat()->GetDoc(); }
1413 SwDoc
* SwXTextTableCursor::GetDoc() { return GetFrameFormat()->GetDoc(); }
1414 const SwUnoCursor
& SwXTextTableCursor::GetCursor() const { return *m_pUnoCursor
; }
1415 SwUnoCursor
& SwXTextTableCursor::GetCursor() { return *m_pUnoCursor
; }
1417 uno::Sequence
<OUString
> SwXTextTableCursor::getSupportedServiceNames()
1418 { return {"com.sun.star.text.TextTableCursor"}; }
1420 SwXTextTableCursor::SwXTextTableCursor(SwFrameFormat
* pFrameFormat
, SwTableBox
const* pBox
)
1421 : m_pFrameFormat(pFrameFormat
)
1422 , m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TEXT_TABLE_CURSOR
))
1424 StartListening(m_pFrameFormat
->GetNotifier());
1425 SwDoc
* pDoc
= m_pFrameFormat
->GetDoc();
1426 const SwStartNode
* pSttNd
= pBox
->GetSttNd();
1427 SwPosition
aPos(*pSttNd
);
1428 m_pUnoCursor
= pDoc
->CreateUnoCursor(aPos
, true);
1429 m_pUnoCursor
->Move( fnMoveForward
, GoInNode
);
1430 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(*m_pUnoCursor
);
1431 rTableCursor
.MakeBoxSels();
1434 SwXTextTableCursor::SwXTextTableCursor(SwFrameFormat
& rTableFormat
, const SwTableCursor
* pTableSelection
)
1435 : m_pFrameFormat(&rTableFormat
)
1436 , m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TEXT_TABLE_CURSOR
))
1438 StartListening(m_pFrameFormat
->GetNotifier());
1439 m_pUnoCursor
= pTableSelection
->GetDoc().CreateUnoCursor(*pTableSelection
->GetPoint(), true);
1440 if(pTableSelection
->HasMark())
1442 m_pUnoCursor
->SetMark();
1443 *m_pUnoCursor
->GetMark() = *pTableSelection
->GetMark();
1445 const SwSelBoxes
& rBoxes
= pTableSelection
->GetSelectedBoxes();
1446 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(*m_pUnoCursor
);
1447 for(auto pBox
: rBoxes
)
1448 rTableCursor
.InsertBox(*pBox
);
1449 rTableCursor
.MakeBoxSels();
1452 OUString
SwXTextTableCursor::getRangeName()
1454 SolarMutexGuard aGuard
;
1455 SwUnoCursor
& rUnoCursor
= GetCursor();
1456 SwUnoTableCursor
* pTableCursor
= dynamic_cast<SwUnoTableCursor
*>(&rUnoCursor
);
1457 //!! see also SwChartDataSequence::getSourceRangeRepresentation
1460 pTableCursor
->MakeBoxSels();
1461 const SwStartNode
* pNode
= pTableCursor
->GetPoint()->GetNode().FindTableBoxStartNode();
1462 const SwTable
* pTable
= SwTable::FindTable(GetFrameFormat());
1463 const SwTableBox
* pEndBox
= pTable
->GetTableBox(pNode
->GetIndex());
1464 if(pTableCursor
->HasMark())
1466 pNode
= pTableCursor
->GetMark()->GetNode().FindTableBoxStartNode();
1467 const SwTableBox
* pStartBox
= pTable
->GetTableBox(pNode
->GetIndex());
1468 if(pEndBox
!= pStartBox
)
1470 // need to switch start and end?
1471 if(*pTableCursor
->GetPoint() < *pTableCursor
->GetMark())
1472 std::swap(pStartBox
, pEndBox
);
1473 return pStartBox
->GetName() + ":" + pEndBox
->GetName();
1476 return pEndBox
->GetName();
1479 sal_Bool
SwXTextTableCursor::gotoCellByName(const OUString
& sCellName
, sal_Bool bExpand
)
1481 SolarMutexGuard aGuard
;
1482 SwUnoCursor
& rUnoCursor
= GetCursor();
1483 auto& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1484 lcl_CursorSelect(rTableCursor
, bExpand
);
1485 return rTableCursor
.GotoTableBox(sCellName
);
1488 sal_Bool
SwXTextTableCursor::goLeft(sal_Int16 Count
, sal_Bool bExpand
)
1490 SolarMutexGuard aGuard
;
1491 SwUnoCursor
& rUnoCursor
= GetCursor();
1492 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1493 lcl_CursorSelect(rTableCursor
, bExpand
);
1494 return rTableCursor
.Left(Count
);
1497 sal_Bool
SwXTextTableCursor::goRight(sal_Int16 Count
, sal_Bool bExpand
)
1499 SolarMutexGuard aGuard
;
1500 SwUnoCursor
& rUnoCursor
= GetCursor();
1501 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1502 lcl_CursorSelect(rTableCursor
, bExpand
);
1503 return rTableCursor
.Right(Count
);
1506 sal_Bool
SwXTextTableCursor::goUp(sal_Int16 Count
, sal_Bool bExpand
)
1508 SolarMutexGuard aGuard
;
1509 SwUnoCursor
& rUnoCursor
= GetCursor();
1510 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1511 lcl_CursorSelect(rTableCursor
, bExpand
);
1512 return rTableCursor
.UpDown(true, Count
, nullptr, 0,
1513 *rUnoCursor
.GetDoc().getIDocumentLayoutAccess().GetCurrentLayout());
1516 sal_Bool
SwXTextTableCursor::goDown(sal_Int16 Count
, sal_Bool bExpand
)
1518 SolarMutexGuard aGuard
;
1519 SwUnoCursor
& rUnoCursor
= GetCursor();
1520 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1521 lcl_CursorSelect(rTableCursor
, bExpand
);
1522 return rTableCursor
.UpDown(false, Count
, nullptr, 0,
1523 *rUnoCursor
.GetDoc().getIDocumentLayoutAccess().GetCurrentLayout());
1526 void SwXTextTableCursor::gotoStart(sal_Bool bExpand
)
1528 SolarMutexGuard aGuard
;
1529 SwUnoCursor
& rUnoCursor
= GetCursor();
1530 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1531 lcl_CursorSelect(rTableCursor
, bExpand
);
1532 rTableCursor
.MoveTable(GotoCurrTable
, fnTableStart
);
1535 void SwXTextTableCursor::gotoEnd(sal_Bool bExpand
)
1537 SolarMutexGuard aGuard
;
1538 SwUnoCursor
& rUnoCursor
= GetCursor();
1539 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1540 lcl_CursorSelect(rTableCursor
, bExpand
);
1541 rTableCursor
.MoveTable(GotoCurrTable
, fnTableEnd
);
1544 sal_Bool
SwXTextTableCursor::mergeRange()
1546 SolarMutexGuard aGuard
;
1547 SwUnoCursor
& rUnoCursor
= GetCursor();
1549 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1551 // HACK: remove pending actions for selecting old style tables
1552 UnoActionRemoveContext
aRemoveContext(rTableCursor
);
1554 rTableCursor
.MakeBoxSels();
1557 UnoActionContext
aContext(&rUnoCursor
.GetDoc());
1558 bResult
= TableMergeErr::Ok
== rTableCursor
.GetDoc().MergeTable(rTableCursor
);
1562 size_t nCount
= rTableCursor
.GetSelectedBoxesCount();
1564 rTableCursor
.DeleteBox(nCount
);
1566 rTableCursor
.MakeBoxSels();
1570 sal_Bool
SwXTextTableCursor::splitRange(sal_Int16 Count
, sal_Bool Horizontal
)
1572 SolarMutexGuard aGuard
;
1574 throw uno::RuntimeException("Illegal first argument: needs to be > 0", static_cast<cppu::OWeakObject
*>(this));
1575 SwUnoCursor
& rUnoCursor
= GetCursor();
1576 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1578 // HACK: remove pending actions for selecting old style tables
1579 UnoActionRemoveContext
aRemoveContext(rTableCursor
);
1581 rTableCursor
.MakeBoxSels();
1584 UnoActionContext
aContext(&rUnoCursor
.GetDoc());
1585 bResult
= rTableCursor
.GetDoc().SplitTable(rTableCursor
.GetSelectedBoxes(), !Horizontal
, Count
);
1587 rTableCursor
.MakeBoxSels();
1591 uno::Reference
< beans::XPropertySetInfo
> SwXTextTableCursor::getPropertySetInfo()
1593 static uno::Reference
< beans::XPropertySetInfo
> xRef
= m_pPropSet
->getPropertySetInfo();
1597 void SwXTextTableCursor::setPropertyValue(const OUString
& rPropertyName
, const uno::Any
& aValue
)
1599 SolarMutexGuard aGuard
;
1600 SwUnoCursor
& rUnoCursor
= GetCursor();
1601 auto pEntry(m_pPropSet
->getPropertyMap().getByName(rPropertyName
));
1603 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
1604 if(pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
1605 throw beans::PropertyVetoException("Property is read-only: " + rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
1607 auto pSttNode
= rUnoCursor
.GetPointNode().StartOfSectionNode();
1608 const SwTableNode
* pTableNode
= pSttNode
->FindTableNode();
1609 lcl_FormatTable(pTableNode
->GetTable().GetFrameFormat());
1611 auto& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1612 rTableCursor
.MakeBoxSels();
1613 SwDoc
& rDoc
= rUnoCursor
.GetDoc();
1614 switch(pEntry
->nWID
)
1616 case FN_UNO_TABLE_CELL_BACKGROUND
:
1618 std::unique_ptr
<SfxPoolItem
> aBrush(std::make_unique
<SvxBrushItem
>(RES_BACKGROUND
));
1619 SwDoc::GetBoxAttr(rUnoCursor
, aBrush
);
1620 aBrush
->PutValue(aValue
, pEntry
->nMemberId
);
1621 rDoc
.SetBoxAttr(rUnoCursor
, *aBrush
);
1625 case RES_BOXATR_FORMAT
:
1627 SfxUInt32Item
aNumberFormat(RES_BOXATR_FORMAT
);
1628 aNumberFormat
.PutValue(aValue
, 0);
1629 rDoc
.SetBoxAttr(rUnoCursor
, aNumberFormat
);
1632 case FN_UNO_PARA_STYLE
:
1633 SwUnoCursorHelper::SetTextFormatColl(aValue
, rUnoCursor
);
1637 SfxItemSet
aItemSet(rDoc
.GetAttrPool(), pEntry
->nWID
, pEntry
->nWID
);
1638 SwUnoCursorHelper::GetCursorAttr(rTableCursor
.GetSelRing(),
1641 if (!SwUnoCursorHelper::SetCursorPropertyValue(
1642 *pEntry
, aValue
, rTableCursor
.GetSelRing(), aItemSet
))
1644 m_pPropSet
->setPropertyValue(*pEntry
, aValue
, aItemSet
);
1646 SwUnoCursorHelper::SetCursorAttr(rTableCursor
.GetSelRing(),
1647 aItemSet
, SetAttrMode::DEFAULT
, true);
1652 uno::Any
SwXTextTableCursor::getPropertyValue(const OUString
& rPropertyName
)
1654 SolarMutexGuard aGuard
;
1655 SwUnoCursor
& rUnoCursor
= GetCursor();
1657 auto pSttNode
= rUnoCursor
.GetPointNode().StartOfSectionNode();
1658 const SwTableNode
* pTableNode
= pSttNode
->FindTableNode();
1659 lcl_FormatTable(pTableNode
->GetTable().GetFrameFormat());
1661 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1662 auto pEntry(m_pPropSet
->getPropertyMap().getByName(rPropertyName
));
1664 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
1665 rTableCursor
.MakeBoxSels();
1667 switch(pEntry
->nWID
)
1669 case FN_UNO_TABLE_CELL_BACKGROUND
:
1671 std::unique_ptr
<SfxPoolItem
> aBrush(std::make_unique
<SvxBrushItem
>(RES_BACKGROUND
));
1672 if (SwDoc::GetBoxAttr(rUnoCursor
, aBrush
))
1673 aBrush
->QueryValue(aResult
, pEntry
->nMemberId
);
1676 case RES_BOXATR_FORMAT
:
1677 // TODO: GetAttr for table selections in a Doc is missing
1678 throw uno::RuntimeException("Unknown property: " + rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
1680 case FN_UNO_PARA_STYLE
:
1682 auto pFormat(SwUnoCursorHelper::GetCurTextFormatColl(rUnoCursor
, false));
1684 aResult
<<= pFormat
->GetName();
1690 <RES_CHRATR_BEGIN
, RES_FRMATR_END
-1,
1691 RES_UNKNOWNATR_CONTAINER
, RES_UNKNOWNATR_CONTAINER
>
1692 aSet(rTableCursor
.GetDoc().GetAttrPool());
1693 SwUnoCursorHelper::GetCursorAttr(rTableCursor
.GetSelRing(), aSet
);
1694 m_pPropSet
->getPropertyValue(*pEntry
, aSet
, aResult
);
1700 void SwXTextTableCursor::addPropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1701 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1703 void SwXTextTableCursor::removePropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1704 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1706 void SwXTextTableCursor::addVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1707 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1709 void SwXTextTableCursor::removeVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1710 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1712 void SwXTextTableCursor::Notify( const SfxHint
& rHint
)
1714 if(rHint
.GetId() == SfxHintId::Dying
)
1715 m_pFrameFormat
= nullptr;
1719 // SwXTextTable ===========================================================
1723 class SwTableProperties_Impl
1725 SwUnoCursorHelper::SwAnyMapHelper m_aAnyMap
;
1728 SwTableProperties_Impl();
1730 void SetProperty(sal_uInt16 nWhichId
, sal_uInt16 nMemberId
, const uno::Any
& aVal
);
1731 bool GetProperty(sal_uInt16 nWhichId
, sal_uInt16 nMemberId
, const uno::Any
*& rpAny
);
1732 void AddItemToSet(SfxItemSet
& rSet
, std::function
<std::unique_ptr
<SfxPoolItem
>()> aItemFactory
,
1733 sal_uInt16 nWhich
, std::initializer_list
<sal_uInt16
> vMember
, bool bAddTwips
= false);
1734 void ApplyTableAttr(const SwTable
& rTable
, SwDoc
& rDoc
);
1739 SwTableProperties_Impl::SwTableProperties_Impl()
1742 void SwTableProperties_Impl::SetProperty(sal_uInt16 nWhichId
, sal_uInt16 nMemberId
, const uno::Any
& rVal
)
1744 m_aAnyMap
.SetValue(nWhichId
, nMemberId
, rVal
);
1747 bool SwTableProperties_Impl::GetProperty(sal_uInt16 nWhichId
, sal_uInt16 nMemberId
, const uno::Any
*& rpAny
)
1749 return m_aAnyMap
.FillValue(nWhichId
, nMemberId
, rpAny
);
1752 void SwTableProperties_Impl::AddItemToSet(SfxItemSet
& rSet
,
1753 std::function
<std::unique_ptr
<SfxPoolItem
>()> aItemFactory
,
1754 sal_uInt16 nWhich
, std::initializer_list
<sal_uInt16
> vMember
, bool bAddTwips
)
1756 std::vector
< std::pair
<sal_uInt16
, const uno::Any
* > > vMemberAndAny
;
1757 for(sal_uInt16 nMember
: vMember
)
1759 const uno::Any
* pAny
= nullptr;
1760 GetProperty(nWhich
, nMember
, pAny
);
1762 vMemberAndAny
.emplace_back(nMember
, pAny
);
1764 if(!vMemberAndAny
.empty())
1766 std::unique_ptr
<SfxPoolItem
> aItem(aItemFactory());
1767 for(const auto& aMemberAndAny
: vMemberAndAny
)
1768 aItem
->PutValue(*aMemberAndAny
.second
, aMemberAndAny
.first
| (bAddTwips
? CONVERT_TWIPS
: 0) );
1769 rSet
.Put(std::move(aItem
));
1772 void SwTableProperties_Impl::ApplyTableAttr(const SwTable
& rTable
, SwDoc
& rDoc
)
1775 RES_FRM_SIZE
, RES_BREAK
,
1776 RES_HORI_ORIENT
, RES_HORI_ORIENT
,
1777 RES_BACKGROUND
, RES_BACKGROUND
,
1778 RES_SHADOW
, RES_SHADOW
,
1780 RES_LAYOUT_SPLIT
, RES_LAYOUT_SPLIT
>
1781 aSet(rDoc
.GetAttrPool());
1782 const uno::Any
* pRepHead
;
1783 const SwFrameFormat
&rFrameFormat
= *rTable
.GetFrameFormat();
1784 if(GetProperty(FN_TABLE_HEADLINE_REPEAT
, 0xff, pRepHead
))
1786 bool bVal(pRepHead
->get
<bool>());
1787 const_cast<SwTable
&>(rTable
).SetRowsToRepeat( bVal
? 1 : 0 ); // TODO: MULTIHEADER
1790 AddItemToSet(aSet
, [&rFrameFormat
]() { return rFrameFormat
.makeBackgroundBrushItem(); }, RES_BACKGROUND
, {
1792 MID_GRAPHIC_TRANSPARENT
,
1793 MID_GRAPHIC_POSITION
,
1795 MID_GRAPHIC_FILTER
});
1797 bool bPutBreak
= true;
1798 const uno::Any
* pPage
;
1799 if(GetProperty(FN_UNO_PAGE_STYLE
, 0, pPage
) || GetProperty(RES_PAGEDESC
, 0xff, pPage
))
1801 OUString sPageStyle
= pPage
->get
<OUString
>();
1802 if(!sPageStyle
.isEmpty())
1804 SwStyleNameMapper::FillUIName(sPageStyle
, sPageStyle
, SwGetPoolIdFromName::PageDesc
);
1805 const SwPageDesc
* pDesc
= SwPageDesc::GetByName(rDoc
, sPageStyle
);
1808 SwFormatPageDesc
aDesc(pDesc
);
1809 const uno::Any
* pPgNo
;
1810 if(GetProperty(RES_PAGEDESC
, MID_PAGEDESC_PAGENUMOFFSET
, pPgNo
))
1812 aDesc
.SetNumOffset(pPgNo
->get
<sal_Int16
>());
1822 AddItemToSet(aSet
, [&rFrameFormat
]() { return std::unique_ptr
<SfxPoolItem
>(rFrameFormat
.GetBreak().Clone()); }, RES_BREAK
, {0});
1823 AddItemToSet(aSet
, [&rFrameFormat
]() { return std::unique_ptr
<SfxPoolItem
>(rFrameFormat
.GetShadow().Clone()); }, RES_SHADOW
, {0}, true);
1824 AddItemToSet(aSet
, [&rFrameFormat
]() { return std::unique_ptr
<SfxPoolItem
>(rFrameFormat
.GetKeep().Clone()); }, RES_KEEP
, {0});
1825 AddItemToSet(aSet
, [&rFrameFormat
]() { return std::unique_ptr
<SfxPoolItem
>(rFrameFormat
.GetHoriOrient().Clone()); }, RES_HORI_ORIENT
, {MID_HORIORIENT_ORIENT
}, true);
1827 const uno::Any
* pSzRel(nullptr);
1828 GetProperty(FN_TABLE_IS_RELATIVE_WIDTH
, 0xff, pSzRel
);
1829 const uno::Any
* pRelWidth(nullptr);
1830 GetProperty(FN_TABLE_RELATIVE_WIDTH
, 0xff, pRelWidth
);
1831 const uno::Any
* pWidth(nullptr);
1832 GetProperty(FN_TABLE_WIDTH
, 0xff, pWidth
);
1834 bool bPutSize
= pWidth
!= nullptr;
1835 SwFormatFrameSize
aSz(SwFrameSize::Variable
);
1838 aSz
.PutValue(*pWidth
, MID_FRMSIZE_WIDTH
);
1841 if(pSzRel
&& pSzRel
->get
<bool>() && pRelWidth
)
1843 aSz
.PutValue(*pRelWidth
, MID_FRMSIZE_REL_WIDTH
|CONVERT_TWIPS
);
1849 aSz
.SetWidth(MINLAY
);
1852 AddItemToSet(aSet
, [&rFrameFormat
]() { return std::unique_ptr
<SfxPoolItem
>(rFrameFormat
.GetLRSpace().Clone()); }, RES_LR_SPACE
, {
1853 MID_L_MARGIN
|CONVERT_TWIPS
,
1854 MID_R_MARGIN
|CONVERT_TWIPS
});
1855 AddItemToSet(aSet
, [&rFrameFormat
]() { return std::unique_ptr
<SfxPoolItem
>(rFrameFormat
.GetULSpace().Clone()); }, RES_UL_SPACE
, {
1856 MID_UP_MARGIN
|CONVERT_TWIPS
,
1857 MID_LO_MARGIN
|CONVERT_TWIPS
});
1858 const::uno::Any
* pSplit(nullptr);
1859 if(GetProperty(RES_LAYOUT_SPLIT
, 0, pSplit
))
1861 SwFormatLayoutSplit
aSp(pSplit
->get
<bool>());
1866 rDoc
.SetAttr(aSet
, *rTable
.GetFrameFormat());
1870 class SwXTextTable::Impl
1871 : public SvtListener
1874 SwFrameFormat
* m_pFrameFormat
;
1877 unotools::WeakReference
<SwXTextTable
> m_wThis
;
1878 std::mutex m_Mutex
; // just for OInterfaceContainerHelper4
1879 ::comphelper::OInterfaceContainerHelper4
<css::lang::XEventListener
> m_EventListeners
;
1880 ::comphelper::OInterfaceContainerHelper4
<chart::XChartDataChangeEventListener
> m_ChartListeners
;
1882 const SfxItemPropertySet
* m_pPropSet
;
1884 css::uno::WeakReference
<css::table::XTableRows
> m_xRows
;
1885 css::uno::WeakReference
<css::table::XTableColumns
> m_xColumns
;
1887 bool m_bFirstRowAsLabel
;
1888 bool m_bFirstColumnAsLabel
;
1890 // Descriptor-interface
1891 std::unique_ptr
<SwTableProperties_Impl
> m_pTableProps
;
1892 OUString m_sTableName
;
1893 unsigned short m_nRows
;
1894 unsigned short m_nColumns
;
1896 explicit Impl(SwFrameFormat
* const pFrameFormat
)
1897 : m_pFrameFormat(pFrameFormat
)
1898 , m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TEXT_TABLE
))
1899 , m_bFirstRowAsLabel(false)
1900 , m_bFirstColumnAsLabel(false)
1901 , m_pTableProps(pFrameFormat
? nullptr : new SwTableProperties_Impl
)
1902 , m_nRows(pFrameFormat
? 0 : 2)
1903 , m_nColumns(pFrameFormat
? 0 : 2)
1906 StartListening(m_pFrameFormat
->GetNotifier());
1909 SwFrameFormat
* GetFrameFormat() { return m_pFrameFormat
; }
1910 void SetFrameFormat(SwFrameFormat
& rFrameFormat
)
1913 m_pFrameFormat
= &rFrameFormat
;
1914 StartListening(m_pFrameFormat
->GetNotifier());
1917 bool IsDescriptor() const { return m_pTableProps
!= nullptr; }
1919 // note: lock mutex before calling this to avoid concurrent update
1920 static std::pair
<sal_uInt16
, sal_uInt16
> ThrowIfComplex(SwXTextTable
&rThis
)
1922 sal_uInt16
const nRowCount(rThis
.m_pImpl
->GetRowCount());
1923 sal_uInt16
const nColCount(rThis
.m_pImpl
->GetColumnCount());
1924 if (!nRowCount
|| !nColCount
)
1926 throw uno::RuntimeException("Table too complex",
1927 static_cast<cppu::OWeakObject
*>(&rThis
));
1929 return std::make_pair(nRowCount
, nColCount
);
1932 sal_uInt16
GetRowCount();
1933 sal_uInt16
GetColumnCount();
1935 virtual void Notify(const SfxHint
&) override
;
1939 SwXTextTable::SwXTextTable()
1940 : m_pImpl(new Impl(nullptr))
1944 SwXTextTable::SwXTextTable(SwFrameFormat
& rFrameFormat
)
1945 : m_pImpl(new Impl(&rFrameFormat
))
1949 SwXTextTable::~SwXTextTable()
1953 rtl::Reference
<SwXTextTable
> SwXTextTable::CreateXTextTable(SwFrameFormat
* const pFrameFormat
)
1955 rtl::Reference
<SwXTextTable
> xTable
;
1957 xTable
= dynamic_cast<SwXTextTable
*>(pFrameFormat
->GetXObject().get().get()); // cached?
1960 xTable
= pFrameFormat
? new SwXTextTable(*pFrameFormat
) : new SwXTextTable();
1962 pFrameFormat
->SetXObject(static_cast<cppu::OWeakObject
*>(xTable
.get()));
1963 // need a permanent Reference to initialize m_wThis
1964 xTable
->m_pImpl
->m_wThis
= xTable
.get();
1968 SwFrameFormat
* SwXTextTable::GetFrameFormat()
1970 return m_pImpl
->GetFrameFormat();
1973 void SwXTextTable::initialize(sal_Int32 nR
, sal_Int32 nC
)
1975 if (!m_pImpl
->IsDescriptor() || nR
<= 0 || nC
<= 0 || nR
>= SAL_MAX_UINT16
|| nC
>= SAL_MAX_UINT16
)
1976 throw uno::RuntimeException();
1977 m_pImpl
->m_nRows
= o3tl::narrowing
<sal_uInt16
>(nR
);
1978 m_pImpl
->m_nColumns
= o3tl::narrowing
<sal_uInt16
>(nC
);
1981 uno::Reference
<table::XTableRows
> SAL_CALL
SwXTextTable::getRows()
1983 SolarMutexGuard aGuard
;
1984 uno::Reference
<table::XTableRows
> xResult(m_pImpl
->m_xRows
);
1987 if(SwFrameFormat
* pFormat
= GetFrameFormat())
1988 m_pImpl
->m_xRows
= xResult
= new SwXTableRows(*pFormat
);
1990 throw uno::RuntimeException();
1994 uno::Reference
<table::XTableColumns
> SAL_CALL
SwXTextTable::getColumns()
1996 SolarMutexGuard aGuard
;
1997 uno::Reference
<table::XTableColumns
> xResult(m_pImpl
->m_xColumns
);
2000 if(SwFrameFormat
* pFormat
= GetFrameFormat())
2001 m_pImpl
->m_xColumns
= xResult
= new SwXTableColumns(*pFormat
);
2003 throw uno::RuntimeException();
2007 uno::Reference
<table::XCell
> SwXTextTable::getCellByName(const OUString
& sCellName
)
2009 SolarMutexGuard aGuard
;
2010 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
2011 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2012 SwTableBox
* pBox
= const_cast<SwTableBox
*>(pTable
->GetTableBox(sCellName
));
2015 return SwXCell::CreateXCell(pFormat
, pBox
);
2018 uno::Sequence
<OUString
> SwXTextTable::getCellNames()
2020 SolarMutexGuard aGuard
;
2021 SwFrameFormat
* pFormat(GetFrameFormat());
2024 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2025 // exists at the table and at all boxes
2026 SwTableLines
& rTableLines
= pTable
->GetTabLines();
2027 std::vector
<OUString
> aAllNames
;
2028 lcl_InspectLines(rTableLines
, aAllNames
);
2029 return comphelper::containerToSequence(aAllNames
);
2032 uno::Reference
<text::XTextTableCursor
> SwXTextTable::createCursorByCellName(const OUString
& sCellName
)
2034 SolarMutexGuard aGuard
;
2035 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
2036 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2037 SwTableBox
* pBox
= const_cast<SwTableBox
*>(pTable
->GetTableBox(sCellName
));
2038 if(!pBox
|| pBox
->getRowSpan() == 0)
2039 throw uno::RuntimeException();
2040 return new SwXTextTableCursor(pFormat
, pBox
);
2044 SwXTextTable::attach(const uno::Reference
<text::XTextRange
> & xTextRange
)
2046 SolarMutexGuard aGuard
;
2048 // attach() must only be called once
2049 if (!m_pImpl
->IsDescriptor()) /* already attached ? */
2050 throw uno::RuntimeException("SwXTextTable: already attached to range.", static_cast<cppu::OWeakObject
*>(this));
2052 SwXTextRange
* pRange(dynamic_cast<SwXTextRange
*>(xTextRange
.get()));
2053 OTextCursorHelper
* pCursor(dynamic_cast<OTextCursorHelper
*>(xTextRange
.get()));
2054 SwDoc
* pDoc
= pRange
? &pRange
->GetDoc() : pCursor
? pCursor
->GetDoc() : nullptr;
2055 if (!pDoc
|| !m_pImpl
->m_nRows
|| !m_pImpl
->m_nColumns
)
2056 throw lang::IllegalArgumentException();
2057 SwUnoInternalPaM
aPam(*pDoc
);
2058 // this now needs to return TRUE
2059 ::sw::XTextRangeToSwPaM(aPam
, xTextRange
);
2061 UnoActionContext
aCont(pDoc
);
2063 pDoc
->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY
, nullptr);
2064 const SwTable
* pTable(nullptr);
2065 if( 0 != aPam
.Start()->GetContentIndex() )
2067 pDoc
->getIDocumentContentOperations().SplitNode(*aPam
.Start(), false);
2069 //TODO: if it is the last paragraph than add another one!
2072 pDoc
->getIDocumentContentOperations().DeleteAndJoin(aPam
);
2077 if (const::uno::Any
* pName
;
2078 m_pImpl
->m_pTableProps
->GetProperty(FN_UNO_TABLE_NAME
, 0, pName
))
2080 tableName
= pName
->get
<OUString
>();
2082 else if (!m_pImpl
->m_sTableName
.isEmpty())
2084 sal_uInt16 nIndex
= 1;
2085 tableName
= m_pImpl
->m_sTableName
;
2086 while (pDoc
->FindTableFormatByName(tableName
, true) && nIndex
< USHRT_MAX
)
2087 tableName
= m_pImpl
->m_sTableName
+ OUString::number(nIndex
++);
2090 pTable
= pDoc
->InsertTable(SwInsertTableOptions( SwInsertTableFlags::Headline
| SwInsertTableFlags::DefaultBorder
| SwInsertTableFlags::SplitLayout
, 0 ),
2093 m_pImpl
->m_nColumns
,
2094 text::HoriOrientation::FULL
,
2095 nullptr, nullptr, false, true,
2099 // here, the properties of the descriptor need to be analyzed
2100 m_pImpl
->m_pTableProps
->ApplyTableAttr(*pTable
, *pDoc
);
2101 SwFrameFormat
* pTableFormat(pTable
->GetFrameFormat());
2102 lcl_FormatTable(pTableFormat
);
2104 m_pImpl
->SetFrameFormat(*pTableFormat
);
2106 m_pImpl
->m_pTableProps
.reset();
2108 pDoc
->GetIDocumentUndoRedo().EndUndo( SwUndoId::END
, nullptr );
2112 uno::Reference
<text::XTextRange
> SwXTextTable::getAnchor()
2114 SolarMutexGuard aGuard
;
2115 SwTableFormat
*const pFormat
= static_cast<SwTableFormat
*>(
2116 lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
2117 return new SwXTextRange(*pFormat
);
2120 void SwXTextTable::dispose()
2122 SolarMutexGuard aGuard
;
2123 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
2124 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2125 SwSelBoxes aSelBoxes
;
2126 for(auto& rBox
: pTable
->GetTabSortBoxes() )
2127 aSelBoxes
.insert(rBox
);
2128 pFormat
->GetDoc()->DeleteRowCol(aSelBoxes
, SwDoc::RowColMode::DeleteProtected
);
2131 void SAL_CALL
SwXTextTable::addEventListener(
2132 const uno::Reference
<lang::XEventListener
> & xListener
)
2134 // no need to lock here as m_pImpl is const and container threadsafe
2135 std::unique_lock
aGuard(m_pImpl
->m_Mutex
);
2136 m_pImpl
->m_EventListeners
.addInterface(aGuard
, xListener
);
2139 void SAL_CALL
SwXTextTable::removeEventListener(
2140 const uno::Reference
< lang::XEventListener
> & xListener
)
2142 // no need to lock here as m_pImpl is const and container threadsafe
2143 std::unique_lock
aGuard(m_pImpl
->m_Mutex
);
2144 m_pImpl
->m_EventListeners
.removeInterface(aGuard
, xListener
);
2147 uno::Reference
<table::XCell
> SwXTextTable::getCellByPosition(sal_Int32 nColumn
, sal_Int32 nRow
)
2149 SolarMutexGuard aGuard
;
2150 SwFrameFormat
* pFormat(GetFrameFormat());
2151 // sheet is unimportant
2152 if(nColumn
>= 0 && nRow
>= 0 && pFormat
)
2154 auto pXCell
= lcl_CreateXCell(pFormat
, nColumn
, nRow
);
2158 throw lang::IndexOutOfBoundsException();
2163 uno::Reference
<table::XCellRange
> GetRangeByName(
2164 SwFrameFormat
* pFormat
, SwTable
const * pTable
,
2165 const OUString
& rTLName
, const OUString
& rBRName
,
2166 SwRangeDescriptor
const & rDesc
)
2168 const SwTableBox
* pTLBox
= pTable
->GetTableBox(rTLName
);
2171 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
2172 SwPosition
aPos(*pSttNd
);
2173 // set cursor to the upper-left cell of the range
2174 auto pUnoCursor(pFormat
->GetDoc()->CreateUnoCursor(aPos
, true));
2175 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
2176 pUnoCursor
->SetRemainInSection(false);
2177 const SwTableBox
* pBRBox(pTable
->GetTableBox(rBRName
));
2180 pUnoCursor
->SetMark();
2181 pUnoCursor
->GetPoint()->Assign( *pBRBox
->GetSttNd() );
2182 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
2183 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
2184 // HACK: remove pending actions for selecting old style tables
2185 UnoActionRemoveContext
aRemoveContext(rCursor
);
2186 rCursor
.MakeBoxSels();
2187 // pUnoCursor will be provided and will not be deleted
2188 return SwXCellRange::CreateXCellRange(pUnoCursor
, *pFormat
, rDesc
);
2193 uno::Reference
<table::XCellRange
> SwXTextTable::getCellRangeByPosition(sal_Int32 nLeft
, sal_Int32 nTop
, sal_Int32 nRight
, sal_Int32 nBottom
)
2195 SolarMutexGuard aGuard
;
2196 SwFrameFormat
* pFormat(GetFrameFormat());
2198 nLeft
<= nRight
&& nTop
<= nBottom
&&
2199 nLeft
>= 0 && nRight
>= 0 && nTop
>= 0 && nBottom
>= 0 )
2201 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2202 if(!pTable
->IsTableComplex())
2204 SwRangeDescriptor aDesc
;
2206 aDesc
.nBottom
= nBottom
;
2207 aDesc
.nLeft
= nLeft
;
2208 aDesc
.nRight
= nRight
;
2209 const OUString sTLName
= sw_GetCellName(aDesc
.nLeft
, aDesc
.nTop
);
2210 const OUString sBRName
= sw_GetCellName(aDesc
.nRight
, aDesc
.nBottom
);
2211 // please note that according to the 'if' statement at the begin
2212 // sTLName:sBRName already denotes the normalized range string
2213 return GetRangeByName(pFormat
, pTable
, sTLName
, sBRName
, aDesc
);
2216 throw lang::IndexOutOfBoundsException();
2219 uno::Reference
<table::XCellRange
> SwXTextTable::getCellRangeByName(const OUString
& sRange
)
2221 SolarMutexGuard aGuard
;
2222 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
2223 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFormat
), static_cast<cppu::OWeakObject
*>(this));
2225 const OUString
sTLName(sRange
.getToken(0, ':', nPos
));
2226 const OUString
sBRName(sRange
.getToken(0, ':', nPos
));
2227 if(sTLName
.isEmpty() || sBRName
.isEmpty())
2228 throw uno::RuntimeException();
2229 SwRangeDescriptor aDesc
;
2230 aDesc
.nTop
= aDesc
.nLeft
= aDesc
.nBottom
= aDesc
.nRight
= -1;
2231 SwXTextTable::GetCellPosition(sTLName
, aDesc
.nLeft
, aDesc
.nTop
);
2232 SwXTextTable::GetCellPosition(sBRName
, aDesc
.nRight
, aDesc
.nBottom
);
2234 // we should normalize the range now (e.g. A5:C1 will become A1:C5)
2235 // since (depending on what is done later) it will be troublesome
2236 // elsewhere when the cursor in the implementation does not
2237 // point to the top-left and bottom-right cells
2239 return GetRangeByName(pFormat
, pTable
, sTLName
, sBRName
, aDesc
);
2242 uno::Sequence
< uno::Sequence
< uno::Any
> > SAL_CALL
SwXTextTable::getDataArray()
2244 SolarMutexGuard aGuard
;
2245 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2246 uno::Reference
<sheet::XCellRangeData
> const xAllRange(
2247 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2248 uno::UNO_QUERY_THROW
);
2249 return xAllRange
->getDataArray();
2252 void SAL_CALL
SwXTextTable::setDataArray(const uno::Sequence
< uno::Sequence
< uno::Any
> >& rArray
)
2254 SolarMutexGuard aGuard
;
2255 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2256 uno::Reference
<sheet::XCellRangeData
> const xAllRange(
2257 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2258 uno::UNO_QUERY_THROW
);
2259 return xAllRange
->setDataArray(rArray
);
2262 uno::Sequence
< uno::Sequence
< double > > SwXTextTable::getData()
2264 SolarMutexGuard aGuard
;
2265 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2266 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2267 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2268 uno::UNO_QUERY_THROW
);
2269 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2270 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2271 return xAllRange
->getData();
2274 void SwXTextTable::setData(const uno::Sequence
< uno::Sequence
< double > >& rData
)
2276 SolarMutexGuard aGuard
;
2277 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2278 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2279 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2280 uno::UNO_QUERY_THROW
);
2281 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2282 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2283 xAllRange
->setData(rData
);
2284 // this is rather inconsistent: setData on XTextTable sends events, but e.g. CellRanges do not
2285 std::unique_lock
aGuard2(m_pImpl
->m_Mutex
);
2286 lcl_SendChartEvent(aGuard2
, *this, m_pImpl
->m_ChartListeners
);
2289 uno::Sequence
<OUString
> SwXTextTable::getRowDescriptions()
2291 SolarMutexGuard aGuard
;
2292 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2293 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2294 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2295 uno::UNO_QUERY_THROW
);
2296 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2297 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2298 return xAllRange
->getRowDescriptions();
2301 void SwXTextTable::setRowDescriptions(const uno::Sequence
<OUString
>& rRowDesc
)
2303 SolarMutexGuard aGuard
;
2304 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2305 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2306 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2307 uno::UNO_QUERY_THROW
);
2308 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2309 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2310 xAllRange
->setRowDescriptions(rRowDesc
);
2313 uno::Sequence
<OUString
> SwXTextTable::getColumnDescriptions()
2315 SolarMutexGuard aGuard
;
2316 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2317 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2318 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2319 uno::UNO_QUERY_THROW
);
2320 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2321 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2322 return xAllRange
->getColumnDescriptions();
2325 void SwXTextTable::setColumnDescriptions(const uno::Sequence
<OUString
>& rColumnDesc
)
2327 SolarMutexGuard aGuard
;
2328 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2329 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2330 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2331 uno::UNO_QUERY_THROW
);
2332 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2333 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2334 return xAllRange
->setColumnDescriptions(rColumnDesc
);
2337 void SAL_CALL
SwXTextTable::addChartDataChangeEventListener(
2338 const uno::Reference
<chart::XChartDataChangeEventListener
> & xListener
)
2340 // no need to lock here as m_pImpl is const and container threadsafe
2341 std::unique_lock
aGuard(m_pImpl
->m_Mutex
);
2342 m_pImpl
->m_ChartListeners
.addInterface(aGuard
, xListener
);
2345 void SAL_CALL
SwXTextTable::removeChartDataChangeEventListener(
2346 const uno::Reference
<chart::XChartDataChangeEventListener
> & xListener
)
2348 // no need to lock here as m_pImpl is const and container threadsafe
2349 std::unique_lock
aGuard(m_pImpl
->m_Mutex
);
2350 m_pImpl
->m_ChartListeners
.removeInterface(aGuard
, xListener
);
2353 sal_Bool
SwXTextTable::isNotANumber(double nNumber
)
2355 // We use DBL_MIN because starcalc does (which uses it because chart
2356 // wants it that way!)
2357 return ( nNumber
== DBL_MIN
);
2360 double SwXTextTable::getNotANumber()
2362 // We use DBL_MIN because starcalc does (which uses it because chart
2363 // wants it that way!)
2367 uno::Sequence
< beans::PropertyValue
> SwXTextTable::createSortDescriptor()
2369 SolarMutexGuard aGuard
;
2371 return SwUnoCursorHelper::CreateSortDescriptor(true);
2374 void SwXTextTable::sort(const uno::Sequence
< beans::PropertyValue
>& rDescriptor
)
2376 SolarMutexGuard aGuard
;
2377 SwSortOptions aSortOpt
;
2378 SwFrameFormat
* pFormat
= GetFrameFormat();
2380 SwUnoCursorHelper::ConvertSortProperties(rDescriptor
, aSortOpt
)))
2383 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2385 const SwTableSortBoxes
& rTBoxes
= pTable
->GetTabSortBoxes();
2386 for (size_t n
= 0; n
< rTBoxes
.size(); ++n
)
2388 SwTableBox
* pBox
= rTBoxes
[ n
];
2389 aBoxes
.insert( pBox
);
2391 UnoActionContext
aContext( pFormat
->GetDoc() );
2392 pFormat
->GetDoc()->SortTable(aBoxes
, aSortOpt
);
2395 void SwXTextTable::autoFormat(const OUString
& sAutoFormatName
)
2397 SolarMutexGuard aGuard
;
2398 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
2399 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFormat
), static_cast<cppu::OWeakObject
*>(this));
2400 SwTableAutoFormatTable aAutoFormatTable
;
2401 aAutoFormatTable
.Load();
2402 for (size_t i
= aAutoFormatTable
.size(); i
;)
2403 if( sAutoFormatName
== aAutoFormatTable
[ --i
].GetName() )
2406 const SwTableSortBoxes
& rTBoxes
= pTable
->GetTabSortBoxes();
2407 for (size_t n
= 0; n
< rTBoxes
.size(); ++n
)
2409 SwTableBox
* pBox
= rTBoxes
[ n
];
2410 aBoxes
.insert( pBox
);
2412 UnoActionContext
aContext( pFormat
->GetDoc() );
2413 pFormat
->GetDoc()->SetTableAutoFormat( aBoxes
, aAutoFormatTable
[i
] );
2418 uno::Reference
< beans::XPropertySetInfo
> SwXTextTable::getPropertySetInfo()
2420 static uno::Reference
<beans::XPropertySetInfo
> xRef
= m_pImpl
->m_pPropSet
->getPropertySetInfo();
2424 void SwXTextTable::setPropertyValue(const OUString
& rPropertyName
, const uno::Any
& aValue
)
2426 SolarMutexGuard aGuard
;
2427 SwFrameFormat
* pFormat
= GetFrameFormat();
2428 if(!aValue
.hasValue())
2429 throw lang::IllegalArgumentException();
2430 const SfxItemPropertyMapEntry
* pEntry
=
2431 m_pImpl
->m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
2433 throw lang::IllegalArgumentException();
2436 if ( pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
2437 throw beans::PropertyVetoException("Property is read-only: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
2439 if(0xBF == pEntry
->nMemberId
)
2441 lcl_SetSpecialProperty(pFormat
, pEntry
, aValue
);
2445 switch(pEntry
->nWID
)
2447 case FN_UNO_TABLE_NAME
:
2455 case FN_UNO_RANGE_ROW_LABEL
:
2457 bool bTmp
= *o3tl::doAccess
<bool>(aValue
);
2458 if (m_pImpl
->m_bFirstRowAsLabel
!= bTmp
)
2460 std::unique_lock
aGuard2(m_pImpl
->m_Mutex
);
2461 lcl_SendChartEvent(aGuard2
, *this, m_pImpl
->m_ChartListeners
);
2462 m_pImpl
->m_bFirstRowAsLabel
= bTmp
;
2467 case FN_UNO_RANGE_COL_LABEL
:
2469 bool bTmp
= *o3tl::doAccess
<bool>(aValue
);
2470 if (m_pImpl
->m_bFirstColumnAsLabel
!= bTmp
)
2472 std::unique_lock
aGuard2(m_pImpl
->m_Mutex
);
2473 lcl_SendChartEvent(aGuard2
, *this, m_pImpl
->m_ChartListeners
);
2474 m_pImpl
->m_bFirstColumnAsLabel
= bTmp
;
2479 case FN_UNO_TABLE_BORDER
:
2480 case FN_UNO_TABLE_BORDER2
:
2482 table::TableBorder oldBorder
;
2483 table::TableBorder2 aBorder
;
2484 SvxBorderLine aTopLine
;
2485 SvxBorderLine aBottomLine
;
2486 SvxBorderLine aLeftLine
;
2487 SvxBorderLine aRightLine
;
2488 SvxBorderLine aHoriLine
;
2489 SvxBorderLine aVertLine
;
2490 if (aValue
>>= oldBorder
)
2492 aBorder
.IsTopLineValid
= oldBorder
.IsTopLineValid
;
2493 aBorder
.IsBottomLineValid
= oldBorder
.IsBottomLineValid
;
2494 aBorder
.IsLeftLineValid
= oldBorder
.IsLeftLineValid
;
2495 aBorder
.IsRightLineValid
= oldBorder
.IsRightLineValid
;
2496 aBorder
.IsHorizontalLineValid
= oldBorder
.IsHorizontalLineValid
;
2497 aBorder
.IsVerticalLineValid
= oldBorder
.IsVerticalLineValid
;
2498 aBorder
.Distance
= oldBorder
.Distance
;
2499 aBorder
.IsDistanceValid
= oldBorder
.IsDistanceValid
;
2501 oldBorder
.TopLine
, aTopLine
);
2503 oldBorder
.BottomLine
, aBottomLine
);
2505 oldBorder
.LeftLine
, aLeftLine
);
2507 oldBorder
.RightLine
, aRightLine
);
2509 oldBorder
.HorizontalLine
, aHoriLine
);
2511 oldBorder
.VerticalLine
, aVertLine
);
2513 else if (aValue
>>= aBorder
)
2515 SvxBoxItem::LineToSvxLine(
2516 aBorder
.TopLine
, aTopLine
, true);
2517 SvxBoxItem::LineToSvxLine(
2518 aBorder
.BottomLine
, aBottomLine
, true);
2519 SvxBoxItem::LineToSvxLine(
2520 aBorder
.LeftLine
, aLeftLine
, true);
2521 SvxBoxItem::LineToSvxLine(
2522 aBorder
.RightLine
, aRightLine
, true);
2523 SvxBoxItem::LineToSvxLine(
2524 aBorder
.HorizontalLine
, aHoriLine
, true);
2525 SvxBoxItem::LineToSvxLine(
2526 aBorder
.VerticalLine
, aVertLine
, true);
2530 break; // something else
2532 SwDoc
* pDoc
= pFormat
->GetDoc();
2533 if(!lcl_FormatTable(pFormat
))
2535 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2536 SwTableLines
&rLines
= pTable
->GetTabLines();
2538 const SwTableBox
* pTLBox
= lcl_FindCornerTableBox(rLines
, true);
2539 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
2540 SwPosition
aPos(*pSttNd
);
2541 // set cursor to top left cell
2542 auto pUnoCursor(pDoc
->CreateUnoCursor(aPos
, true));
2543 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
2544 pUnoCursor
->SetRemainInSection( false );
2546 const SwTableBox
* pBRBox
= lcl_FindCornerTableBox(rLines
, false);
2547 pUnoCursor
->SetMark();
2548 pUnoCursor
->GetPoint()->Assign( *pBRBox
->GetSttNd() );
2549 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
2550 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
2551 // HACK: remove pending actions for selecting old style tables
2552 UnoActionRemoveContext
aRemoveContext(rCursor
);
2553 rCursor
.MakeBoxSels();
2555 SfxItemSetFixed
<RES_BOX
, RES_BOX
,
2556 SID_ATTR_BORDER_INNER
, SID_ATTR_BORDER_INNER
>
2557 aSet(pDoc
->GetAttrPool());
2559 SvxBoxItem
aBox( RES_BOX
);
2560 SvxBoxInfoItem
aBoxInfo( SID_ATTR_BORDER_INNER
);
2562 aBox
.SetLine(aTopLine
.isEmpty() ? nullptr : &aTopLine
, SvxBoxItemLine::TOP
);
2563 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::TOP
, aBorder
.IsTopLineValid
);
2565 aBox
.SetLine(aBottomLine
.isEmpty() ? nullptr : &aBottomLine
, SvxBoxItemLine::BOTTOM
);
2566 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::BOTTOM
, aBorder
.IsBottomLineValid
);
2568 aBox
.SetLine(aLeftLine
.isEmpty() ? nullptr : &aLeftLine
, SvxBoxItemLine::LEFT
);
2569 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::LEFT
, aBorder
.IsLeftLineValid
);
2571 aBox
.SetLine(aRightLine
.isEmpty() ? nullptr : &aRightLine
, SvxBoxItemLine::RIGHT
);
2572 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::RIGHT
, aBorder
.IsRightLineValid
);
2574 aBoxInfo
.SetLine(aHoriLine
.isEmpty() ? nullptr : &aHoriLine
, SvxBoxInfoItemLine::HORI
);
2575 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::HORI
, aBorder
.IsHorizontalLineValid
);
2577 aBoxInfo
.SetLine(aVertLine
.isEmpty() ? nullptr : &aVertLine
, SvxBoxInfoItemLine::VERT
);
2578 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::VERT
, aBorder
.IsVerticalLineValid
);
2580 aBox
.SetAllDistances(o3tl::toTwips(aBorder
.Distance
, o3tl::Length::mm100
));
2581 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::DISTANCE
, aBorder
.IsDistanceValid
);
2586 pDoc
->SetTabBorders(rCursor
, aSet
);
2590 case FN_UNO_TABLE_BORDER_DISTANCES
:
2592 table::TableBorderDistances aTableBorderDistances
;
2593 if( !(aValue
>>= aTableBorderDistances
) ||
2594 (!aTableBorderDistances
.IsLeftDistanceValid
&&
2595 !aTableBorderDistances
.IsRightDistanceValid
&&
2596 !aTableBorderDistances
.IsTopDistanceValid
&&
2597 !aTableBorderDistances
.IsBottomDistanceValid
))
2600 const sal_uInt16 nLeftDistance
= o3tl::toTwips(aTableBorderDistances
.LeftDistance
, o3tl::Length::mm100
);
2601 const sal_uInt16 nRightDistance
= o3tl::toTwips(aTableBorderDistances
.RightDistance
, o3tl::Length::mm100
);
2602 const sal_uInt16 nTopDistance
= o3tl::toTwips(aTableBorderDistances
.TopDistance
, o3tl::Length::mm100
);
2603 const sal_uInt16 nBottomDistance
= o3tl::toTwips(aTableBorderDistances
.BottomDistance
, o3tl::Length::mm100
);
2604 SwDoc
* pDoc
= pFormat
->GetDoc();
2605 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2606 SwTableLines
&rLines
= pTable
->GetTabLines();
2607 pDoc
->GetIDocumentUndoRedo().StartUndo(SwUndoId::START
, nullptr);
2608 for(size_t i
= 0; i
< rLines
.size(); ++i
)
2610 SwTableLine
* pLine
= rLines
[i
];
2611 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
2612 for(size_t k
= 0; k
< rBoxes
.size(); ++k
)
2614 SwTableBox
* pBox
= rBoxes
[k
];
2615 const SwFrameFormat
* pBoxFormat
= pBox
->GetFrameFormat();
2616 const SvxBoxItem
& rBox
= pBoxFormat
->GetBox();
2618 (aTableBorderDistances
.IsLeftDistanceValid
&& nLeftDistance
!= rBox
.GetDistance( SvxBoxItemLine::LEFT
)) ||
2619 (aTableBorderDistances
.IsRightDistanceValid
&& nRightDistance
!= rBox
.GetDistance( SvxBoxItemLine::RIGHT
)) ||
2620 (aTableBorderDistances
.IsTopDistanceValid
&& nTopDistance
!= rBox
.GetDistance( SvxBoxItemLine::TOP
)) ||
2621 (aTableBorderDistances
.IsBottomDistanceValid
&& nBottomDistance
!= rBox
.GetDistance( SvxBoxItemLine::BOTTOM
)))
2623 SvxBoxItem
aSetBox( rBox
);
2624 SwFrameFormat
* pSetBoxFormat
= pBox
->ClaimFrameFormat();
2625 if( aTableBorderDistances
.IsLeftDistanceValid
)
2626 aSetBox
.SetDistance( nLeftDistance
, SvxBoxItemLine::LEFT
);
2627 if( aTableBorderDistances
.IsRightDistanceValid
)
2628 aSetBox
.SetDistance( nRightDistance
, SvxBoxItemLine::RIGHT
);
2629 if( aTableBorderDistances
.IsTopDistanceValid
)
2630 aSetBox
.SetDistance( nTopDistance
, SvxBoxItemLine::TOP
);
2631 if( aTableBorderDistances
.IsBottomDistanceValid
)
2632 aSetBox
.SetDistance( nBottomDistance
, SvxBoxItemLine::BOTTOM
);
2633 pDoc
->SetAttr( aSetBox
, *pSetBoxFormat
);
2637 pDoc
->GetIDocumentUndoRedo().EndUndo(SwUndoId::END
, nullptr);
2641 case FN_UNO_TABLE_COLUMN_SEPARATORS
:
2643 UnoActionContext
aContext(pFormat
->GetDoc());
2644 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2645 lcl_SetTableSeparators(aValue
, pTable
, pTable
->GetTabLines()[0]->GetTabBoxes()[0], false, pFormat
->GetDoc());
2649 case FN_UNO_TABLE_COLUMN_RELATIVE_SUM
:/*_readonly_*/ break;
2651 case FN_UNO_TABLE_TEMPLATE_NAME
:
2653 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2655 if (!(aValue
>>= sName
))
2657 SwStyleNameMapper::FillUIName(sName
, sName
, SwGetPoolIdFromName::TabStyle
);
2658 pTable
->SetTableStyleName(sName
);
2659 SwDoc
* pDoc
= pFormat
->GetDoc();
2660 if (SwFEShell
* pFEShell
= pDoc
->GetDocShell()->GetFEShell())
2661 pFEShell
->UpdateTableStyleFormatting(pTable
->GetTableNode());
2667 SwAttrSet
aSet(pFormat
->GetAttrSet());
2668 m_pImpl
->m_pPropSet
->setPropertyValue(*pEntry
, aValue
, aSet
);
2669 pFormat
->GetDoc()->SetAttr(aSet
, *pFormat
);
2674 else if (m_pImpl
->IsDescriptor())
2676 m_pImpl
->m_pTableProps
->SetProperty(pEntry
->nWID
, pEntry
->nMemberId
, aValue
);
2679 throw uno::RuntimeException();
2682 uno::Any
SwXTextTable::getPropertyValue(const OUString
& rPropertyName
)
2684 SolarMutexGuard aGuard
;
2686 SwFrameFormat
* pFormat
= GetFrameFormat();
2687 const SfxItemPropertyMapEntry
* pEntry
=
2688 m_pImpl
->m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
2691 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
2695 if(0xBF == pEntry
->nMemberId
)
2697 aRet
= lcl_GetSpecialProperty(pFormat
, pEntry
);
2701 switch(pEntry
->nWID
)
2703 case FN_UNO_TABLE_NAME
:
2709 case FN_UNO_ANCHOR_TYPES
:
2710 case FN_UNO_TEXT_WRAP
:
2711 case FN_UNO_ANCHOR_TYPE
:
2712 ::sw::GetDefaultTextContentValue(
2713 aRet
, u
"", pEntry
->nWID
);
2716 case FN_UNO_RANGE_ROW_LABEL
:
2718 aRet
<<= m_pImpl
->m_bFirstRowAsLabel
;
2722 case FN_UNO_RANGE_COL_LABEL
:
2723 aRet
<<= m_pImpl
->m_bFirstColumnAsLabel
;
2726 case FN_UNO_TABLE_BORDER
:
2727 case FN_UNO_TABLE_BORDER2
:
2729 SwDoc
* pDoc
= pFormat
->GetDoc();
2730 // tables without layout (invisible header/footer?)
2731 if(!lcl_FormatTable(pFormat
))
2733 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2734 SwTableLines
&rLines
= pTable
->GetTabLines();
2736 const SwTableBox
* pTLBox
= lcl_FindCornerTableBox(rLines
, true);
2737 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
2738 SwPosition
aPos(*pSttNd
);
2739 // set cursor to top left cell
2740 auto pUnoCursor(pDoc
->CreateUnoCursor(aPos
, true));
2741 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
2742 pUnoCursor
->SetRemainInSection( false );
2744 const SwTableBox
* pBRBox
= lcl_FindCornerTableBox(rLines
, false);
2745 pUnoCursor
->SetMark();
2746 const SwStartNode
* pLastNd
= pBRBox
->GetSttNd();
2747 pUnoCursor
->GetPoint()->Assign( *pLastNd
);
2749 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
2750 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
2751 // HACK: remove pending actions for selecting old style tables
2752 UnoActionRemoveContext
aRemoveContext(rCursor
);
2753 rCursor
.MakeBoxSels();
2755 SfxItemSetFixed
<RES_BOX
, RES_BOX
,
2756 SID_ATTR_BORDER_INNER
, SID_ATTR_BORDER_INNER
>
2757 aSet(pDoc
->GetAttrPool());
2758 aSet
.Put(SvxBoxInfoItem( SID_ATTR_BORDER_INNER
));
2759 SwDoc::GetTabBorders(rCursor
, aSet
);
2760 const SvxBoxInfoItem
& rBoxInfoItem
= aSet
.Get(SID_ATTR_BORDER_INNER
);
2761 const SvxBoxItem
& rBox
= aSet
.Get(RES_BOX
);
2763 if (FN_UNO_TABLE_BORDER
== pEntry
->nWID
)
2765 table::TableBorder aTableBorder
;
2766 aTableBorder
.TopLine
= SvxBoxItem::SvxLineToLine(rBox
.GetTop(), true);
2767 aTableBorder
.IsTopLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::TOP
);
2768 aTableBorder
.BottomLine
= SvxBoxItem::SvxLineToLine(rBox
.GetBottom(), true);
2769 aTableBorder
.IsBottomLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::BOTTOM
);
2770 aTableBorder
.LeftLine
= SvxBoxItem::SvxLineToLine(rBox
.GetLeft(), true);
2771 aTableBorder
.IsLeftLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::LEFT
);
2772 aTableBorder
.RightLine
= SvxBoxItem::SvxLineToLine(rBox
.GetRight(), true);
2773 aTableBorder
.IsRightLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::RIGHT
);
2774 aTableBorder
.HorizontalLine
= SvxBoxItem::SvxLineToLine(rBoxInfoItem
.GetHori(), true);
2775 aTableBorder
.IsHorizontalLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::HORI
);
2776 aTableBorder
.VerticalLine
= SvxBoxItem::SvxLineToLine(rBoxInfoItem
.GetVert(), true);
2777 aTableBorder
.IsVerticalLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::VERT
);
2778 aTableBorder
.Distance
= convertTwipToMm100(rBox
.GetSmallestDistance());
2779 aTableBorder
.IsDistanceValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::DISTANCE
);
2780 aRet
<<= aTableBorder
;
2784 table::TableBorder2 aTableBorder
;
2785 aTableBorder
.TopLine
= SvxBoxItem::SvxLineToLine(rBox
.GetTop(), true);
2786 aTableBorder
.IsTopLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::TOP
);
2787 aTableBorder
.BottomLine
= SvxBoxItem::SvxLineToLine(rBox
.GetBottom(), true);
2788 aTableBorder
.IsBottomLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::BOTTOM
);
2789 aTableBorder
.LeftLine
= SvxBoxItem::SvxLineToLine(rBox
.GetLeft(), true);
2790 aTableBorder
.IsLeftLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::LEFT
);
2791 aTableBorder
.RightLine
= SvxBoxItem::SvxLineToLine(rBox
.GetRight(), true);
2792 aTableBorder
.IsRightLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::RIGHT
);
2793 aTableBorder
.HorizontalLine
= SvxBoxItem::SvxLineToLine(rBoxInfoItem
.GetHori(), true);
2794 aTableBorder
.IsHorizontalLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::HORI
);
2795 aTableBorder
.VerticalLine
= SvxBoxItem::SvxLineToLine(rBoxInfoItem
.GetVert(), true);
2796 aTableBorder
.IsVerticalLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::VERT
);
2797 aTableBorder
.Distance
= convertTwipToMm100(rBox
.GetSmallestDistance());
2798 aTableBorder
.IsDistanceValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::DISTANCE
);
2799 aRet
<<= aTableBorder
;
2804 case FN_UNO_TABLE_BORDER_DISTANCES
:
2806 table::TableBorderDistances
aTableBorderDistances( 0, true, 0, true, 0, true, 0, true ) ;
2807 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2808 const SwTableLines
&rLines
= pTable
->GetTabLines();
2810 sal_uInt16 nLeftDistance
= 0;
2811 sal_uInt16 nRightDistance
= 0;
2812 sal_uInt16 nTopDistance
= 0;
2813 sal_uInt16 nBottomDistance
= 0;
2815 for(size_t i
= 0; i
< rLines
.size(); ++i
)
2817 const SwTableLine
* pLine
= rLines
[i
];
2818 const SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
2819 for(size_t k
= 0; k
< rBoxes
.size(); ++k
)
2821 const SwTableBox
* pBox
= rBoxes
[k
];
2822 SwFrameFormat
* pBoxFormat
= pBox
->GetFrameFormat();
2823 const SvxBoxItem
& rBox
= pBoxFormat
->GetBox();
2826 nLeftDistance
= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::LEFT
));
2827 nRightDistance
= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::RIGHT
));
2828 nTopDistance
= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::TOP
));
2829 nBottomDistance
= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::BOTTOM
));
2834 if( aTableBorderDistances
.IsLeftDistanceValid
&&
2835 nLeftDistance
!= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::LEFT
)))
2836 aTableBorderDistances
.IsLeftDistanceValid
= false;
2837 if( aTableBorderDistances
.IsRightDistanceValid
&&
2838 nRightDistance
!= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::RIGHT
)))
2839 aTableBorderDistances
.IsRightDistanceValid
= false;
2840 if( aTableBorderDistances
.IsTopDistanceValid
&&
2841 nTopDistance
!= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::TOP
)))
2842 aTableBorderDistances
.IsTopDistanceValid
= false;
2843 if( aTableBorderDistances
.IsBottomDistanceValid
&&
2844 nBottomDistance
!= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::BOTTOM
)))
2845 aTableBorderDistances
.IsBottomDistanceValid
= false;
2849 if( !aTableBorderDistances
.IsLeftDistanceValid
&&
2850 !aTableBorderDistances
.IsRightDistanceValid
&&
2851 !aTableBorderDistances
.IsTopDistanceValid
&&
2852 !aTableBorderDistances
.IsBottomDistanceValid
)
2855 if( aTableBorderDistances
.IsLeftDistanceValid
)
2856 aTableBorderDistances
.LeftDistance
= nLeftDistance
;
2857 if( aTableBorderDistances
.IsRightDistanceValid
)
2858 aTableBorderDistances
.RightDistance
= nRightDistance
;
2859 if( aTableBorderDistances
.IsTopDistanceValid
)
2860 aTableBorderDistances
.TopDistance
= nTopDistance
;
2861 if( aTableBorderDistances
.IsBottomDistanceValid
)
2862 aTableBorderDistances
.BottomDistance
= nBottomDistance
;
2864 aRet
<<= aTableBorderDistances
;
2868 case FN_UNO_TABLE_COLUMN_SEPARATORS
:
2870 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2871 lcl_GetTableSeparators(aRet
, pTable
, pTable
->GetTabLines()[0]->GetTabBoxes()[0], false);
2875 case FN_UNO_TABLE_COLUMN_RELATIVE_SUM
:
2876 aRet
<<= sal_Int16(UNO_TABLE_COLUMN_SUM
);
2880 // AnchorType is readonly and might be void (no return value)
2883 case FN_UNO_TEXT_SECTION
:
2885 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2886 SwTableNode
* pTableNode
= pTable
->GetTableNode();
2887 SwSectionNode
* pSectionNode
= pTableNode
->FindSectionNode();
2890 SwSection
& rSect
= pSectionNode
->GetSection();
2891 uno::Reference
< text::XTextSection
> xSect
=
2892 SwXTextSections::GetObject( *rSect
.GetFormat() );
2898 case FN_UNO_TABLE_TEMPLATE_NAME
:
2900 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2902 SwStyleNameMapper::FillProgName(pTable
->GetTableStyleName(), sName
, SwGetPoolIdFromName::TabStyle
);
2909 const SwAttrSet
& rSet
= pFormat
->GetAttrSet();
2910 m_pImpl
->m_pPropSet
->getPropertyValue(*pEntry
, rSet
, aRet
);
2915 else if (m_pImpl
->IsDescriptor())
2917 const uno::Any
* pAny
= nullptr;
2918 if (!m_pImpl
->m_pTableProps
->GetProperty(pEntry
->nWID
, pEntry
->nMemberId
, pAny
))
2919 throw lang::IllegalArgumentException();
2924 throw uno::RuntimeException();
2928 void SwXTextTable::addPropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
2929 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
2931 void SwXTextTable::removePropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
2932 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
2934 void SwXTextTable::addVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
2935 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
2937 void SwXTextTable::removeVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
2938 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
2940 OUString
SwXTextTable::getName()
2942 SolarMutexGuard aGuard
;
2943 SwFrameFormat
* pFormat
= GetFrameFormat();
2944 if (!pFormat
&& !m_pImpl
->IsDescriptor())
2945 throw uno::RuntimeException();
2948 return pFormat
->GetName();
2950 return m_pImpl
->m_sTableName
;
2953 void SwXTextTable::setName(const OUString
& rName
)
2955 SolarMutexGuard aGuard
;
2956 SwFrameFormat
* pFormat
= GetFrameFormat();
2957 if ((!pFormat
&& !m_pImpl
->IsDescriptor()) ||
2959 rName
.indexOf('.')>=0 ||
2960 rName
.indexOf(' ')>=0 )
2961 throw uno::RuntimeException();
2965 const OUString
aOldName( pFormat
->GetName() );
2966 const sw::TableFrameFormats
* pFrameFormats
= pFormat
->GetDoc()->GetTableFrameFormats();
2967 for (size_t i
= pFrameFormats
->size(); i
;)
2969 const SwTableFormat
* pTmpFormat
= (*pFrameFormats
)[--i
];
2970 if( !pTmpFormat
->IsDefault() &&
2971 pTmpFormat
->GetName() == rName
&&
2972 pFormat
->GetDoc()->IsUsed( *pTmpFormat
))
2974 throw uno::RuntimeException();
2978 pFormat
->SetFormatName( rName
);
2981 SwNodeIndex
aIdx( *pFormat
->GetDoc()->GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
2982 while ( nullptr != (pStNd
= aIdx
.GetNode().GetStartNode()) )
2985 SwNode
*const pNd
= & aIdx
.GetNode();
2986 if ( pNd
->IsOLENode() &&
2987 aOldName
== static_cast<const SwOLENode
*>(pNd
)->GetChartTableName() )
2989 static_cast<SwOLENode
*>(pNd
)->SetChartTableName( rName
);
2991 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2992 //TL_CHART2: chart needs to be notified about name changes
2993 pFormat
->GetDoc()->UpdateCharts( pTable
->GetFrameFormat()->GetName() );
2995 aIdx
.Assign( *pStNd
->EndOfSectionNode(), + 1 );
2997 pFormat
->GetDoc()->getIDocumentState().SetModified();
3000 m_pImpl
->m_sTableName
= rName
;
3003 sal_uInt16
SwXTextTable::Impl::GetRowCount()
3005 sal_uInt16 nRet
= 0;
3006 SwFrameFormat
* pFormat
= GetFrameFormat();
3009 SwTable
* pTable
= SwTable::FindTable( pFormat
);
3010 if(!pTable
->IsTableComplex())
3012 nRet
= pTable
->GetTabLines().size();
3018 sal_uInt16
SwXTextTable::Impl::GetColumnCount()
3020 SwFrameFormat
* pFormat
= GetFrameFormat();
3021 sal_uInt16 nRet
= 0;
3024 SwTable
* pTable
= SwTable::FindTable( pFormat
);
3025 if(!pTable
->IsTableComplex())
3027 SwTableLines
& rLines
= pTable
->GetTabLines();
3028 SwTableLine
* pLine
= rLines
.front();
3029 nRet
= pLine
->GetTabBoxes().size();
3035 void SwXTextTable::Impl::Notify(const SfxHint
& rHint
)
3037 if(rHint
.GetId() == SfxHintId::Dying
)
3039 m_pFrameFormat
= nullptr;
3042 std::unique_lock
aGuard(m_Mutex
);
3043 if (m_EventListeners
.getLength(aGuard
) == 0 && m_ChartListeners
.getLength(aGuard
) == 0)
3045 uno::Reference
<uno::XInterface
> const xThis(m_wThis
);
3046 // fdo#72695: if UNO object is already dead, don't revive it with event
3051 lang::EventObject
const ev(xThis
);
3052 m_EventListeners
.disposeAndClear(aGuard
, ev
);
3053 m_ChartListeners
.disposeAndClear(aGuard
, ev
);
3057 lcl_SendChartEvent(aGuard
, xThis
, m_ChartListeners
);
3061 OUString SAL_CALL
SwXTextTable::getImplementationName()
3062 { return "SwXTextTable"; }
3064 sal_Bool
SwXTextTable::supportsService(const OUString
& rServiceName
)
3065 { return cppu::supportsService(this, rServiceName
); }
3067 uno::Sequence
<OUString
> SwXTextTable::getSupportedServiceNames()
3070 "com.sun.star.document.LinkTarget",
3071 "com.sun.star.text.TextTable",
3072 "com.sun.star.text.TextContent",
3073 "com.sun.star.text.TextSortable" };
3077 class SwXCellRange::Impl
3078 : public SvtListener
3081 SwFrameFormat
* m_pFrameFormat
;
3084 uno::WeakReference
<uno::XInterface
> m_wThis
;
3085 std::mutex m_Mutex
; // just for OInterfaceContainerHelper4
3086 ::comphelper::OInterfaceContainerHelper4
<chart::XChartDataChangeEventListener
> m_ChartListeners
;
3088 sw::UnoCursorPointer m_pTableCursor
;
3090 SwRangeDescriptor m_RangeDescriptor
;
3091 const SfxItemPropertySet
* m_pPropSet
;
3093 bool m_bFirstRowAsLabel
;
3094 bool m_bFirstColumnAsLabel
;
3096 Impl(sw::UnoCursorPointer
const& pCursor
, SwFrameFormat
& rFrameFormat
, SwRangeDescriptor
const& rDesc
)
3097 : m_pFrameFormat(&rFrameFormat
)
3098 , m_pTableCursor(pCursor
)
3099 , m_RangeDescriptor(rDesc
)
3100 , m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TABLE_RANGE
))
3101 , m_bFirstRowAsLabel(false)
3102 , m_bFirstColumnAsLabel(false)
3104 StartListening(rFrameFormat
.GetNotifier());
3105 m_RangeDescriptor
.Normalize();
3108 SwFrameFormat
* GetFrameFormat()
3110 return m_pFrameFormat
;
3113 std::tuple
<sal_uInt32
, sal_uInt32
, sal_uInt32
, sal_uInt32
> GetLabelCoordinates(bool bRow
);
3115 uno::Sequence
<OUString
> GetLabelDescriptions(SwXCellRange
& rThis
, bool bRow
);
3117 void SetLabelDescriptions(SwXCellRange
& rThis
,
3118 const css::uno::Sequence
<OUString
>& rDesc
, bool bRow
);
3120 sal_Int32
GetRowCount() const;
3121 sal_Int32
GetColumnCount() const;
3123 virtual void Notify(const SfxHint
& ) override
;
3127 OUString
SwXCellRange::getImplementationName()
3128 { return "SwXCellRange"; }
3130 sal_Bool
SwXCellRange::supportsService(const OUString
& rServiceName
)
3131 { return cppu::supportsService(this, rServiceName
); }
3133 uno::Sequence
<OUString
> SwXCellRange::getSupportedServiceNames()
3136 "com.sun.star.text.CellRange",
3137 "com.sun.star.style.CharacterProperties",
3138 "com.sun.star.style.CharacterPropertiesAsian",
3139 "com.sun.star.style.CharacterPropertiesComplex",
3140 "com.sun.star.style.ParagraphProperties",
3141 "com.sun.star.style.ParagraphPropertiesAsian",
3142 "com.sun.star.style.ParagraphPropertiesComplex" };
3145 SwXCellRange::SwXCellRange(sw::UnoCursorPointer
const& pCursor
,
3146 SwFrameFormat
& rFrameFormat
, SwRangeDescriptor
const & rDesc
)
3147 : m_pImpl(new Impl(pCursor
, rFrameFormat
, rDesc
))
3151 SwXCellRange::~SwXCellRange()
3155 rtl::Reference
<SwXCellRange
> SwXCellRange::CreateXCellRange(
3156 sw::UnoCursorPointer
const& pCursor
, SwFrameFormat
& rFrameFormat
,
3157 SwRangeDescriptor
const & rDesc
)
3159 rtl::Reference
<SwXCellRange
> pCellRange(new SwXCellRange(pCursor
, rFrameFormat
, rDesc
));
3160 // need a permanent Reference to initialize m_wThis
3161 pCellRange
->m_pImpl
->m_wThis
= uno::Reference
<table::XCellRange
>(pCellRange
);
3165 void SwXCellRange::SetLabels(bool bFirstRowAsLabel
, bool bFirstColumnAsLabel
)
3167 m_pImpl
->m_bFirstRowAsLabel
= bFirstRowAsLabel
;
3168 m_pImpl
->m_bFirstColumnAsLabel
= bFirstColumnAsLabel
;
3171 std::vector
< uno::Reference
< table::XCell
> > SwXCellRange::GetCells()
3173 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3174 const sal_Int32
nRowCount(m_pImpl
->GetRowCount());
3175 const sal_Int32
nColCount(m_pImpl
->GetColumnCount());
3176 std::vector
< uno::Reference
< table::XCell
> > vResult
;
3177 vResult
.reserve(static_cast<size_t>(nRowCount
)*static_cast<size_t>(nColCount
));
3178 for(sal_Int32 nRow
= 0; nRow
< nRowCount
; ++nRow
)
3179 for(sal_Int32 nCol
= 0; nCol
< nColCount
; ++nCol
)
3180 vResult
.emplace_back(lcl_CreateXCell(pFormat
, m_pImpl
->m_RangeDescriptor
.nLeft
+ nCol
, m_pImpl
->m_RangeDescriptor
.nTop
+ nRow
));
3184 uno::Reference
<table::XCell
> SAL_CALL
3185 SwXCellRange::getCellByPosition(sal_Int32 nColumn
, sal_Int32 nRow
)
3187 SolarMutexGuard aGuard
;
3188 uno::Reference
< table::XCell
> aRet
;
3189 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3192 if(nColumn
>= 0 && nRow
>= 0 &&
3193 m_pImpl
->GetColumnCount() > nColumn
&& m_pImpl
->GetRowCount() > nRow
)
3195 rtl::Reference
<SwXCell
> pXCell
= lcl_CreateXCell(pFormat
,
3196 m_pImpl
->m_RangeDescriptor
.nLeft
+ nColumn
,
3197 m_pImpl
->m_RangeDescriptor
.nTop
+ nRow
);
3203 throw lang::IndexOutOfBoundsException();
3207 uno::Reference
<table::XCellRange
> SAL_CALL
3208 SwXCellRange::getCellRangeByPosition(
3209 sal_Int32 nLeft
, sal_Int32 nTop
, sal_Int32 nRight
, sal_Int32 nBottom
)
3211 SolarMutexGuard aGuard
;
3212 uno::Reference
< table::XCellRange
> aRet
;
3213 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3214 if (pFormat
&& m_pImpl
->GetColumnCount() > nRight
3215 && m_pImpl
->GetRowCount() > nBottom
&&
3216 nLeft
<= nRight
&& nTop
<= nBottom
3217 && nLeft
>= 0 && nRight
>= 0 && nTop
>= 0 && nBottom
>= 0 )
3219 SwTable
* pTable
= SwTable::FindTable( pFormat
);
3220 if(!pTable
->IsTableComplex())
3222 SwRangeDescriptor aNewDesc
;
3223 aNewDesc
.nTop
= nTop
+ m_pImpl
->m_RangeDescriptor
.nTop
;
3224 aNewDesc
.nBottom
= nBottom
+ m_pImpl
->m_RangeDescriptor
.nTop
;
3225 aNewDesc
.nLeft
= nLeft
+ m_pImpl
->m_RangeDescriptor
.nLeft
;
3226 aNewDesc
.nRight
= nRight
+ m_pImpl
->m_RangeDescriptor
.nLeft
;
3227 aNewDesc
.Normalize();
3228 const OUString sTLName
= sw_GetCellName(aNewDesc
.nLeft
, aNewDesc
.nTop
);
3229 const OUString sBRName
= sw_GetCellName(aNewDesc
.nRight
, aNewDesc
.nBottom
);
3230 const SwTableBox
* pTLBox
= pTable
->GetTableBox( sTLName
);
3233 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
3234 SwPosition
aPos(*pSttNd
);
3235 // set cursor in the upper-left cell of the range
3236 auto pUnoCursor(pFormat
->GetDoc()->CreateUnoCursor(aPos
, true));
3237 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
3238 pUnoCursor
->SetRemainInSection( false );
3239 const SwTableBox
* pBRBox
= pTable
->GetTableBox( sBRName
);
3242 pUnoCursor
->SetMark();
3243 pUnoCursor
->GetPoint()->Assign( *pBRBox
->GetSttNd() );
3244 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
3245 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
3246 // HACK: remove pending actions for selecting old style tables
3247 UnoActionRemoveContext
aRemoveContext(rCursor
);
3248 rCursor
.MakeBoxSels();
3249 // pUnoCursor will be provided and will not be deleted
3250 aRet
= SwXCellRange::CreateXCellRange(pUnoCursor
, *pFormat
, aNewDesc
).get();
3256 throw lang::IndexOutOfBoundsException();
3260 uno::Reference
<table::XCellRange
> SAL_CALL
3261 SwXCellRange::getCellRangeByName(const OUString
& rRange
)
3263 SolarMutexGuard aGuard
;
3265 const OUString
sTLName(rRange
.getToken(0, ':', nPos
));
3266 const OUString
sBRName(rRange
.getToken(0, ':', nPos
));
3267 if(sTLName
.isEmpty() || sBRName
.isEmpty())
3268 throw uno::RuntimeException();
3269 SwRangeDescriptor aDesc
;
3270 aDesc
.nTop
= aDesc
.nLeft
= aDesc
.nBottom
= aDesc
.nRight
= -1;
3271 SwXTextTable::GetCellPosition( sTLName
, aDesc
.nLeft
, aDesc
.nTop
);
3272 SwXTextTable::GetCellPosition( sBRName
, aDesc
.nRight
, aDesc
.nBottom
);
3274 return getCellRangeByPosition(
3275 aDesc
.nLeft
- m_pImpl
->m_RangeDescriptor
.nLeft
,
3276 aDesc
.nTop
- m_pImpl
->m_RangeDescriptor
.nTop
,
3277 aDesc
.nRight
- m_pImpl
->m_RangeDescriptor
.nLeft
,
3278 aDesc
.nBottom
- m_pImpl
->m_RangeDescriptor
.nTop
);
3281 uno::Reference
< beans::XPropertySetInfo
> SwXCellRange::getPropertySetInfo()
3283 static uno::Reference
<beans::XPropertySetInfo
> xRef
= m_pImpl
->m_pPropSet
->getPropertySetInfo();
3288 SwXCellRange::setPropertyValue(const OUString
& rPropertyName
, const uno::Any
& aValue
)
3290 SolarMutexGuard aGuard
;
3291 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3295 const SfxItemPropertyMapEntry
*const pEntry
=
3296 m_pImpl
->m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
3298 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
3300 if ( pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
3301 throw beans::PropertyVetoException("Property is read-only: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
3303 SwDoc
& rDoc
= m_pImpl
->m_pTableCursor
->GetDoc();
3304 SwUnoTableCursor
& rCursor(dynamic_cast<SwUnoTableCursor
&>(*m_pImpl
->m_pTableCursor
));
3306 // HACK: remove pending actions for selecting old style tables
3307 UnoActionRemoveContext
aRemoveContext(rCursor
);
3309 rCursor
.MakeBoxSels();
3310 switch(pEntry
->nWID
)
3312 case FN_UNO_TABLE_CELL_BACKGROUND
:
3314 std::unique_ptr
<SfxPoolItem
> aBrush(std::make_unique
<SvxBrushItem
>(RES_BACKGROUND
));
3315 SwDoc::GetBoxAttr(*m_pImpl
->m_pTableCursor
, aBrush
);
3316 aBrush
->PutValue(aValue
, pEntry
->nMemberId
);
3317 rDoc
.SetBoxAttr(*m_pImpl
->m_pTableCursor
, *aBrush
);
3323 SfxItemSetFixed
<RES_BOX
, RES_BOX
,
3324 SID_ATTR_BORDER_INNER
, SID_ATTR_BORDER_INNER
>
3325 aSet(rDoc
.GetAttrPool());
3326 SvxBoxInfoItem
aBoxInfo( SID_ATTR_BORDER_INNER
);
3327 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::ALL
, false);
3328 SvxBoxInfoItemValidFlags nValid
= SvxBoxInfoItemValidFlags::NONE
;
3329 switch(pEntry
->nMemberId
& ~CONVERT_TWIPS
)
3331 case LEFT_BORDER
: nValid
= SvxBoxInfoItemValidFlags::LEFT
; break;
3332 case RIGHT_BORDER
: nValid
= SvxBoxInfoItemValidFlags::RIGHT
; break;
3333 case TOP_BORDER
: nValid
= SvxBoxInfoItemValidFlags::TOP
; break;
3334 case BOTTOM_BORDER
: nValid
= SvxBoxInfoItemValidFlags::BOTTOM
; break;
3335 case LEFT_BORDER_DISTANCE
:
3336 case RIGHT_BORDER_DISTANCE
:
3337 case TOP_BORDER_DISTANCE
:
3338 case BOTTOM_BORDER_DISTANCE
:
3339 nValid
= SvxBoxInfoItemValidFlags::DISTANCE
;
3342 aBoxInfo
.SetValid(nValid
);
3345 SwDoc::GetTabBorders(rCursor
, aSet
);
3348 SvxBoxItem
aBoxItem(aSet
.Get(RES_BOX
));
3349 static_cast<SfxPoolItem
&>(aBoxItem
).PutValue(aValue
, pEntry
->nMemberId
);
3351 rDoc
.SetTabBorders(*m_pImpl
->m_pTableCursor
, aSet
);
3354 case RES_BOXATR_FORMAT
:
3356 SfxUInt32Item
aNumberFormat(RES_BOXATR_FORMAT
);
3357 static_cast<SfxPoolItem
&>(aNumberFormat
).PutValue(aValue
, 0);
3358 rDoc
.SetBoxAttr(rCursor
, aNumberFormat
);
3361 case FN_UNO_RANGE_ROW_LABEL
:
3363 bool bTmp
= *o3tl::doAccess
<bool>(aValue
);
3364 if (m_pImpl
->m_bFirstRowAsLabel
!= bTmp
)
3366 std::unique_lock
aGuard2(m_pImpl
->m_Mutex
);
3367 lcl_SendChartEvent(aGuard2
, *this, m_pImpl
->m_ChartListeners
);
3368 m_pImpl
->m_bFirstRowAsLabel
= bTmp
;
3372 case FN_UNO_RANGE_COL_LABEL
:
3374 bool bTmp
= *o3tl::doAccess
<bool>(aValue
);
3375 if (m_pImpl
->m_bFirstColumnAsLabel
!= bTmp
)
3377 std::unique_lock
aGuard2(m_pImpl
->m_Mutex
);
3378 lcl_SendChartEvent(aGuard2
, *this, m_pImpl
->m_ChartListeners
);
3379 m_pImpl
->m_bFirstColumnAsLabel
= bTmp
;
3383 case RES_VERT_ORIENT
:
3385 sal_Int16 nAlign
= -1;
3387 if( nAlign
>= text::VertOrientation::NONE
&& nAlign
<= text::VertOrientation::BOTTOM
)
3388 rDoc
.SetBoxAlign( rCursor
, nAlign
);
3393 SfxItemSet
aItemSet( rDoc
.GetAttrPool(), pEntry
->nWID
, pEntry
->nWID
);
3394 SwUnoCursorHelper::GetCursorAttr(rCursor
.GetSelRing(),
3397 if (!SwUnoCursorHelper::SetCursorPropertyValue(
3398 *pEntry
, aValue
, rCursor
.GetSelRing(), aItemSet
))
3400 m_pImpl
->m_pPropSet
->setPropertyValue(*pEntry
, aValue
, aItemSet
);
3402 SwUnoCursorHelper::SetCursorAttr(rCursor
.GetSelRing(),
3403 aItemSet
, SetAttrMode::DEFAULT
, true);
3408 uno::Any SAL_CALL
SwXCellRange::getPropertyValue(const OUString
& rPropertyName
)
3410 SolarMutexGuard aGuard
;
3412 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3415 const SfxItemPropertyMapEntry
*const pEntry
=
3416 m_pImpl
->m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
3418 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
3420 switch(pEntry
->nWID
)
3422 case FN_UNO_TABLE_CELL_BACKGROUND
:
3424 std::unique_ptr
<SfxPoolItem
> aBrush(std::make_unique
<SvxBrushItem
>(RES_BACKGROUND
));
3425 if (SwDoc::GetBoxAttr(*m_pImpl
->m_pTableCursor
, aBrush
))
3426 aBrush
->QueryValue(aRet
, pEntry
->nMemberId
);
3432 SwDoc
& rDoc
= m_pImpl
->m_pTableCursor
->GetDoc();
3433 SfxItemSetFixed
<RES_BOX
, RES_BOX
,
3434 SID_ATTR_BORDER_INNER
, SID_ATTR_BORDER_INNER
>
3435 aSet(rDoc
.GetAttrPool());
3436 aSet
.Put(SvxBoxInfoItem( SID_ATTR_BORDER_INNER
));
3437 SwDoc::GetTabBorders(*m_pImpl
->m_pTableCursor
, aSet
);
3438 const SvxBoxItem
& rBoxItem
= aSet
.Get(RES_BOX
);
3439 rBoxItem
.QueryValue(aRet
, pEntry
->nMemberId
);
3442 case RES_BOXATR_FORMAT
:
3443 OSL_FAIL("not implemented");
3445 case FN_UNO_PARA_STYLE
:
3447 SwFormatColl
*const pTmpFormat
=
3448 SwUnoCursorHelper::GetCurTextFormatColl(*m_pImpl
->m_pTableCursor
, false);
3451 sRet
= pTmpFormat
->GetName();
3455 case FN_UNO_RANGE_ROW_LABEL
:
3456 aRet
<<= m_pImpl
->m_bFirstRowAsLabel
;
3458 case FN_UNO_RANGE_COL_LABEL
:
3459 aRet
<<= m_pImpl
->m_bFirstColumnAsLabel
;
3461 case RES_VERT_ORIENT
:
3463 std::unique_ptr
<SfxPoolItem
> aVertOrient(
3464 std::make_unique
<SwFormatVertOrient
>(RES_VERT_ORIENT
));
3465 if (SwDoc::GetBoxAttr(*m_pImpl
->m_pTableCursor
, aVertOrient
))
3467 aVertOrient
->QueryValue( aRet
, pEntry
->nMemberId
);
3474 RES_CHRATR_BEGIN
, RES_FRMATR_END
- 1,
3475 RES_UNKNOWNATR_CONTAINER
,
3476 RES_UNKNOWNATR_CONTAINER
>
3477 aSet(m_pImpl
->m_pTableCursor
->GetDoc().GetAttrPool());
3478 // first look at the attributes of the cursor
3479 SwUnoTableCursor
& rCursor
=
3480 dynamic_cast<SwUnoTableCursor
&>(*m_pImpl
->m_pTableCursor
);
3481 SwUnoCursorHelper::GetCursorAttr(rCursor
.GetSelRing(), aSet
);
3482 m_pImpl
->m_pPropSet
->getPropertyValue(*pEntry
, aSet
, aRet
);
3490 void SwXCellRange::addPropertyChangeListener(const OUString
& /*PropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*aListener*/)
3491 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3493 void SwXCellRange::removePropertyChangeListener(const OUString
& /*PropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*aListener*/)
3494 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3496 void SwXCellRange::addVetoableChangeListener(const OUString
& /*PropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*aListener*/)
3497 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3499 void SwXCellRange::removeVetoableChangeListener(const OUString
& /*PropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*aListener*/)
3500 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3502 ///@see SwXCellRange::getData
3503 uno::Sequence
<uno::Sequence
<uno::Any
>> SAL_CALL
SwXCellRange::getDataArray()
3505 SolarMutexGuard aGuard
;
3506 const sal_Int32 nRowCount
= m_pImpl
->GetRowCount();
3507 const sal_Int32 nColCount
= m_pImpl
->GetColumnCount();
3508 if(!nRowCount
|| !nColCount
)
3509 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3510 lcl_EnsureCoreConnected(m_pImpl
->GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
3511 uno::Sequence
< uno::Sequence
< uno::Any
> > aRowSeq(nRowCount
);
3512 auto vCells(GetCells());
3513 auto pCurrentCell(vCells
.begin());
3514 for(auto& rRow
: asNonConstRange(aRowSeq
))
3516 rRow
= uno::Sequence
< uno::Any
>(nColCount
);
3517 for(auto& rCellAny
: asNonConstRange(rRow
))
3519 auto pCell(static_cast<SwXCell
*>(pCurrentCell
->get()));
3521 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3522 rCellAny
= pCell
->GetAny();
3529 ///@see SwXCellRange::setData
3530 void SAL_CALL
SwXCellRange::setDataArray(const uno::Sequence
< uno::Sequence
< uno::Any
> >& rArray
)
3532 SolarMutexGuard aGuard
;
3533 const sal_Int32 nRowCount
= m_pImpl
->GetRowCount();
3534 const sal_Int32 nColCount
= m_pImpl
->GetColumnCount();
3535 if(!nRowCount
|| !nColCount
)
3536 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3537 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3540 if(rArray
.getLength() != nRowCount
)
3541 throw uno::RuntimeException("Row count mismatch. expected: " + OUString::number(nRowCount
) + " got: " + OUString::number(rArray
.getLength()), static_cast<cppu::OWeakObject
*>(this));
3542 auto vCells(GetCells());
3543 auto pCurrentCell(vCells
.begin());
3544 for(const auto& rColSeq
: rArray
)
3546 if(rColSeq
.getLength() != nColCount
)
3547 throw uno::RuntimeException("Column count mismatch. expected: " + OUString::number(nColCount
) + " got: " + OUString::number(rColSeq
.getLength()), static_cast<cppu::OWeakObject
*>(this));
3548 for(const auto& aValue
: rColSeq
)
3550 auto pCell(static_cast<SwXCell
*>(pCurrentCell
->get()));
3551 if(!pCell
|| !pCell
->GetTableBox())
3552 throw uno::RuntimeException("Box for cell missing", static_cast<cppu::OWeakObject
*>(this));
3553 if(aValue
.isExtractableTo(cppu::UnoType
<OUString
>::get()))
3554 sw_setString(*pCell
, aValue
.get
<OUString
>());
3555 else if(aValue
.isExtractableTo(cppu::UnoType
<double>::get()))
3556 sw_setValue(*pCell
, aValue
.get
<double>());
3558 sw_setString(*pCell
, OUString(), true);
3564 uno::Sequence
<uno::Sequence
<double>> SAL_CALL
3565 SwXCellRange::getData()
3567 SolarMutexGuard aGuard
;
3568 const sal_Int32 nRowCount
= m_pImpl
->GetRowCount();
3569 const sal_Int32 nColCount
= m_pImpl
->GetColumnCount();
3570 if(!nRowCount
|| !nColCount
)
3571 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3572 if (m_pImpl
->m_bFirstColumnAsLabel
|| m_pImpl
->m_bFirstRowAsLabel
)
3574 uno::Reference
<chart::XChartDataArray
> const xDataRange(
3575 getCellRangeByPosition((m_pImpl
->m_bFirstColumnAsLabel
) ? 1 : 0,
3576 (m_pImpl
->m_bFirstRowAsLabel
) ? 1 : 0,
3577 nColCount
-1, nRowCount
-1), uno::UNO_QUERY_THROW
);
3578 return xDataRange
->getData();
3580 uno::Sequence
< uno::Sequence
< double > > vRows(nRowCount
);
3581 auto vCells(GetCells());
3582 auto pCurrentCell(vCells
.begin());
3583 for(auto& rRow
: asNonConstRange(vRows
))
3585 rRow
= uno::Sequence
<double>(nColCount
);
3586 for(auto& rValue
: asNonConstRange(rRow
))
3588 if(!(*pCurrentCell
))
3589 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3590 rValue
= (*pCurrentCell
)->getValue();
3598 SwXCellRange::setData(const uno::Sequence
< uno::Sequence
<double> >& rData
)
3600 SolarMutexGuard aGuard
;
3601 const sal_Int32 nRowCount
= m_pImpl
->GetRowCount();
3602 const sal_Int32 nColCount
= m_pImpl
->GetColumnCount();
3603 if(!nRowCount
|| !nColCount
)
3604 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3605 if (m_pImpl
->m_bFirstColumnAsLabel
|| m_pImpl
->m_bFirstRowAsLabel
)
3607 uno::Reference
<chart::XChartDataArray
> const xDataRange(
3608 getCellRangeByPosition((m_pImpl
->m_bFirstColumnAsLabel
) ? 1 : 0,
3609 (m_pImpl
->m_bFirstRowAsLabel
) ? 1 : 0,
3610 nColCount
-1, nRowCount
-1), uno::UNO_QUERY_THROW
);
3611 return xDataRange
->setData(rData
);
3613 lcl_EnsureCoreConnected(m_pImpl
->GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
3614 if(rData
.getLength() != nRowCount
)
3615 throw uno::RuntimeException("Row count mismatch. expected: " + OUString::number(nRowCount
) + " got: " + OUString::number(rData
.getLength()), static_cast<cppu::OWeakObject
*>(this));
3616 auto vCells(GetCells());
3617 auto pCurrentCell(vCells
.begin());
3618 for(const auto& rRow
: rData
)
3620 if(rRow
.getLength() != nColCount
)
3621 throw uno::RuntimeException("Column count mismatch. expected: " + OUString::number(nColCount
) + " got: " + OUString::number(rRow
.getLength()), static_cast<cppu::OWeakObject
*>(this));
3622 for(const auto& rValue
: rRow
)
3624 uno::Reference
<table::XCell
>(*pCurrentCell
, uno::UNO_SET_THROW
)->setValue(rValue
);
3630 std::tuple
<sal_uInt32
, sal_uInt32
, sal_uInt32
, sal_uInt32
>
3631 SwXCellRange::Impl::GetLabelCoordinates(bool bRow
)
3633 sal_uInt32 nLeft
, nTop
, nRight
, nBottom
;
3634 nLeft
= nTop
= nRight
= nBottom
= 0;
3637 nTop
= m_bFirstRowAsLabel
? 1 : 0;
3638 nBottom
= GetRowCount() - 1;
3642 nLeft
= m_bFirstColumnAsLabel
? 1 : 0;
3643 nRight
= GetColumnCount() - 1;
3645 return std::make_tuple(nLeft
, nTop
, nRight
, nBottom
);
3648 uno::Sequence
<OUString
>
3649 SwXCellRange::Impl::GetLabelDescriptions(SwXCellRange
& rThis
, bool bRow
)
3651 SolarMutexGuard aGuard
;
3652 sal_uInt32 nLeft
, nTop
, nRight
, nBottom
;
3653 std::tie(nLeft
, nTop
, nRight
, nBottom
) = GetLabelCoordinates(bRow
);
3654 if(!nRight
&& !nBottom
)
3655 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(&rThis
));
3656 lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(&rThis
));
3657 if (!(bRow
? m_bFirstColumnAsLabel
: m_bFirstRowAsLabel
))
3658 return {}; // without labels we have no descriptions
3659 auto xLabelRange(rThis
.getCellRangeByPosition(nLeft
, nTop
, nRight
, nBottom
));
3660 auto vCells(static_cast<SwXCellRange
*>(xLabelRange
.get())->GetCells());
3661 uno::Sequence
<OUString
> vResult(vCells
.size());
3662 std::transform(vCells
.begin(), vCells
.end(), vResult
.getArray(),
3663 [](uno::Reference
<table::XCell
> xCell
) -> OUString
{ return uno::Reference
<text::XText
>(xCell
, uno::UNO_QUERY_THROW
)->getString(); });
3667 uno::Sequence
<OUString
> SAL_CALL
SwXCellRange::getRowDescriptions()
3669 return m_pImpl
->GetLabelDescriptions(*this, true);
3672 uno::Sequence
<OUString
> SAL_CALL
SwXCellRange::getColumnDescriptions()
3674 return m_pImpl
->GetLabelDescriptions(*this, false);
3677 void SwXCellRange::Impl::SetLabelDescriptions(SwXCellRange
& rThis
,
3678 const uno::Sequence
<OUString
>& rDesc
, bool bRow
)
3680 SolarMutexGuard aGuard
;
3681 lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(&rThis
));
3682 if (!(bRow
? m_bFirstColumnAsLabel
: m_bFirstRowAsLabel
))
3683 return; // if there are no labels we cannot set descriptions
3684 sal_uInt32 nLeft
, nTop
, nRight
, nBottom
;
3685 std::tie(nLeft
, nTop
, nRight
, nBottom
) = GetLabelCoordinates(bRow
);
3686 if(!nRight
&& !nBottom
)
3687 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(&rThis
));
3688 auto xLabelRange(rThis
.getCellRangeByPosition(nLeft
, nTop
, nRight
, nBottom
));
3689 if (!xLabelRange
.is())
3690 throw uno::RuntimeException("Missing Cell Range", static_cast<cppu::OWeakObject
*>(&rThis
));
3691 auto vCells(static_cast<SwXCellRange
*>(xLabelRange
.get())->GetCells());
3692 if (sal::static_int_cast
<sal_uInt32
>(rDesc
.getLength()) != vCells
.size())
3693 throw uno::RuntimeException("Too few or too many descriptions", static_cast<cppu::OWeakObject
*>(&rThis
));
3694 auto pDescIterator(rDesc
.begin());
3695 for(auto& xCell
: vCells
)
3696 uno::Reference
<text::XText
>(xCell
, uno::UNO_QUERY_THROW
)->setString(*pDescIterator
++);
3699 void SAL_CALL
SwXCellRange::setRowDescriptions(
3700 const uno::Sequence
<OUString
>& rRowDesc
)
3702 m_pImpl
->SetLabelDescriptions(*this, rRowDesc
, true);
3705 void SAL_CALL
SwXCellRange::setColumnDescriptions(
3706 const uno::Sequence
<OUString
>& rColumnDesc
)
3708 m_pImpl
->SetLabelDescriptions(*this, rColumnDesc
, false);
3711 void SAL_CALL
SwXCellRange::addChartDataChangeEventListener(
3712 const uno::Reference
<chart::XChartDataChangeEventListener
> & xListener
)
3714 // no need to lock here as m_pImpl is const and container threadsafe
3715 std::unique_lock
aGuard(m_pImpl
->m_Mutex
);
3716 m_pImpl
->m_ChartListeners
.addInterface(aGuard
, xListener
);
3719 void SAL_CALL
SwXCellRange::removeChartDataChangeEventListener(
3720 const uno::Reference
<chart::XChartDataChangeEventListener
> & xListener
)
3722 // no need to lock here as m_pImpl is const and container threadsafe
3723 std::unique_lock
aGuard(m_pImpl
->m_Mutex
);
3724 m_pImpl
->m_ChartListeners
.removeInterface(aGuard
, xListener
);
3727 sal_Bool
SwXCellRange::isNotANumber(double /*fNumber*/)
3728 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3730 double SwXCellRange::getNotANumber()
3731 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3733 uno::Sequence
< beans::PropertyValue
> SwXCellRange::createSortDescriptor()
3735 SolarMutexGuard aGuard
;
3736 return SwUnoCursorHelper::CreateSortDescriptor(true);
3739 void SAL_CALL
SwXCellRange::sort(const uno::Sequence
< beans::PropertyValue
>& rDescriptor
)
3741 SolarMutexGuard aGuard
;
3742 SwSortOptions aSortOpt
;
3743 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3744 if(pFormat
&& SwUnoCursorHelper::ConvertSortProperties(rDescriptor
, aSortOpt
))
3746 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(*m_pImpl
->m_pTableCursor
);
3747 rTableCursor
.MakeBoxSels();
3748 UnoActionContext
aContext(pFormat
->GetDoc());
3749 pFormat
->GetDoc()->SortTable(rTableCursor
.GetSelectedBoxes(), aSortOpt
);
3753 sal_Int32
SwXCellRange::Impl::GetColumnCount() const
3755 return m_RangeDescriptor
.nRight
- m_RangeDescriptor
.nLeft
+ 1;
3758 sal_Int32
SwXCellRange::Impl::GetRowCount() const
3760 return m_RangeDescriptor
.nBottom
- m_RangeDescriptor
.nTop
+ 1;
3763 const SwUnoCursor
* SwXCellRange::GetTableCursor() const
3765 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3766 return pFormat
? &(*m_pImpl
->m_pTableCursor
) : nullptr;
3769 void SwXCellRange::Impl::Notify( const SfxHint
& rHint
)
3771 uno::Reference
<uno::XInterface
> const xThis(m_wThis
);
3772 if(rHint
.GetId() == SfxHintId::Dying
)
3774 m_pFrameFormat
= nullptr;
3775 m_pTableCursor
.reset(nullptr);
3778 { // fdo#72695: if UNO object is already dead, don't revive it with event
3781 std::unique_lock
aGuard(m_Mutex
);
3782 lcl_SendChartEvent(aGuard
, xThis
, m_ChartListeners
);
3786 std::unique_lock
aGuard(m_Mutex
);
3787 m_ChartListeners
.disposeAndClear(aGuard
, lang::EventObject(xThis
));
3792 class SwXTableRows::Impl
: public SvtListener
3795 SwFrameFormat
* m_pFrameFormat
;
3798 explicit Impl(SwFrameFormat
& rFrameFormat
) : m_pFrameFormat(&rFrameFormat
)
3800 StartListening(rFrameFormat
.GetNotifier());
3802 SwFrameFormat
* GetFrameFormat() { return m_pFrameFormat
; }
3803 virtual void Notify(const SfxHint
&) override
;
3808 OUString
SwXTableRows::getImplementationName()
3809 { return "SwXTableRows"; }
3811 sal_Bool
SwXTableRows::supportsService(const OUString
& rServiceName
)
3812 { return cppu::supportsService(this, rServiceName
); }
3814 uno::Sequence
< OUString
> SwXTableRows::getSupportedServiceNames()
3815 { return { "com.sun.star.text.TableRows" }; }
3818 SwXTableRows::SwXTableRows(SwFrameFormat
& rFrameFormat
) :
3819 m_pImpl(new SwXTableRows::Impl(rFrameFormat
))
3822 SwXTableRows::~SwXTableRows()
3825 SwFrameFormat
* SwXTableRows::GetFrameFormat()
3827 return m_pImpl
->GetFrameFormat();
3830 sal_Int32
SwXTableRows::getCount()
3832 SolarMutexGuard aGuard
;
3833 SwFrameFormat
* pFrameFormat
= GetFrameFormat();
3835 throw uno::RuntimeException();
3836 SwTable
* pTable
= SwTable::FindTable(pFrameFormat
);
3837 return pTable
->GetTabLines().size();
3840 ///@see SwXCell::CreateXCell (TODO: seems to be copy and paste programming here)
3841 uno::Any
SwXTableRows::getByIndex(sal_Int32 nIndex
)
3843 SolarMutexGuard aGuard
;
3844 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
3846 throw lang::IndexOutOfBoundsException();
3847 SwTable
* pTable
= SwTable::FindTable( pFrameFormat
);
3848 if(o3tl::make_unsigned(nIndex
) >= pTable
->GetTabLines().size())
3849 throw lang::IndexOutOfBoundsException();
3850 SwTableLine
* pLine
= pTable
->GetTabLines()[nIndex
];
3851 FindUnoInstanceHint
<SwTableLine
,SwXTextTableRow
> aHint
{pLine
};
3852 pFrameFormat
->GetNotifier().Broadcast(aHint
);
3853 if(!aHint
.m_pResult
)
3854 aHint
.m_pResult
= new SwXTextTableRow(pFrameFormat
, pLine
);
3855 uno::Reference
<beans::XPropertySet
> xRet
= static_cast<beans::XPropertySet
*>(aHint
.m_pResult
.get());
3856 return uno::Any(xRet
);
3859 uno::Type SAL_CALL
SwXTableRows::getElementType()
3861 return cppu::UnoType
<beans::XPropertySet
>::get();
3864 sal_Bool
SwXTableRows::hasElements()
3866 SolarMutexGuard aGuard
;
3867 SwFrameFormat
* pFrameFormat
= GetFrameFormat();
3869 throw uno::RuntimeException();
3870 // a table always has rows
3874 void SwXTableRows::insertByIndex(sal_Int32 nIndex
, sal_Int32 nCount
)
3876 SolarMutexGuard aGuard
;
3879 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
3880 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFrameFormat
), static_cast<cppu::OWeakObject
*>(this));
3881 const size_t nRowCount
= pTable
->GetTabLines().size();
3882 if (nCount
<= 0 || 0 > nIndex
|| o3tl::make_unsigned(nIndex
) > nRowCount
)
3883 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
3884 const OUString sTLName
= sw_GetCellName(0, nIndex
);
3885 const SwTableBox
* pTLBox
= pTable
->GetTableBox(sTLName
);
3886 bool bAppend
= false;
3890 // to append at the end the cursor must be in the last line
3891 SwTableLines
& rLines
= pTable
->GetTabLines();
3892 SwTableLine
* pLine
= rLines
.back();
3893 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
3894 pTLBox
= rBoxes
.front();
3897 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
3898 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
3899 SwPosition
aPos(*pSttNd
);
3900 // set cursor to the upper-left cell of the range
3901 UnoActionContext
aAction(pFrameFormat
->GetDoc());
3902 std::shared_ptr
<SwUnoTableCursor
> const pUnoCursor(
3903 std::dynamic_pointer_cast
<SwUnoTableCursor
>(
3904 pFrameFormat
->GetDoc()->CreateUnoCursor(aPos
, true)));
3905 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
3907 // remove actions - TODO: why?
3908 UnoActionRemoveContext
aRemoveContext(&pUnoCursor
->GetDoc());
3910 pFrameFormat
->GetDoc()->InsertRow(*pUnoCursor
, o3tl::narrowing
<sal_uInt16
>(nCount
), bAppend
);
3913 void SwXTableRows::removeByIndex(sal_Int32 nIndex
, sal_Int32 nCount
)
3915 SolarMutexGuard aGuard
;
3918 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
3919 if(nIndex
< 0 || nCount
<=0 )
3920 throw uno::RuntimeException();
3921 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFrameFormat
), static_cast<cppu::OWeakObject
*>(this));
3922 OUString sTLName
= sw_GetCellName(0, nIndex
);
3923 const SwTableBox
* pTLBox
= pTable
->GetTableBox(sTLName
);
3925 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
3926 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
3927 SwPosition
aPos(*pSttNd
);
3928 // set cursor to the upper-left cell of the range
3929 auto pUnoCursor(pFrameFormat
->GetDoc()->CreateUnoCursor(aPos
, true));
3930 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
3931 pUnoCursor
->SetRemainInSection( false );
3932 const OUString sBLName
= sw_GetCellName(0, nIndex
+ nCount
- 1);
3933 const SwTableBox
* pBLBox
= pTable
->GetTableBox( sBLName
);
3935 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
3936 pUnoCursor
->SetMark();
3937 pUnoCursor
->GetPoint()->Assign( *pBLBox
->GetSttNd() );
3938 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
3939 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
3941 // HACK: remove pending actions for selecting old style tables
3942 UnoActionRemoveContext
aRemoveContext(rCursor
);
3944 rCursor
.MakeBoxSels();
3945 { // these braces are important
3946 UnoActionContext
aAction(pFrameFormat
->GetDoc());
3947 pFrameFormat
->GetDoc()->DeleteRow(*pUnoCursor
);
3951 // invalidate all actions - TODO: why?
3952 UnoActionRemoveContext
aRemoveContext(pFrameFormat
->GetDoc());
3956 void SwXTableRows::Impl::Notify( const SfxHint
& rHint
)
3958 if(rHint
.GetId() == SfxHintId::Dying
)
3959 m_pFrameFormat
= nullptr;
3964 class SwXTableColumns::Impl
: public SvtListener
3966 SwFrameFormat
* m_pFrameFormat
;
3968 explicit Impl(SwFrameFormat
& rFrameFormat
) : m_pFrameFormat(&rFrameFormat
)
3970 StartListening(rFrameFormat
.GetNotifier());
3972 SwFrameFormat
* GetFrameFormat() { return m_pFrameFormat
; }
3973 virtual void Notify(const SfxHint
&) override
;
3976 OUString
SwXTableColumns::getImplementationName()
3977 { return "SwXTableColumns"; }
3979 sal_Bool
SwXTableColumns::supportsService(const OUString
& rServiceName
)
3980 { return cppu::supportsService(this, rServiceName
); }
3982 uno::Sequence
< OUString
> SwXTableColumns::getSupportedServiceNames()
3983 { return { "com.sun.star.text.TableColumns"}; }
3986 SwXTableColumns::SwXTableColumns(SwFrameFormat
& rFrameFormat
) :
3987 m_pImpl(new SwXTableColumns::Impl(rFrameFormat
))
3990 SwXTableColumns::~SwXTableColumns()
3993 SwFrameFormat
* SwXTableColumns::GetFrameFormat() const
3995 return m_pImpl
->GetFrameFormat();
3998 sal_Int32
SwXTableColumns::getCount()
4000 SolarMutexGuard aGuard
;
4001 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
4002 SwTable
* pTable
= SwTable::FindTable( pFrameFormat
);
4003 // if(!pTable->IsTableComplex())
4004 // throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject*>(this));
4005 SwTableLines
& rLines
= pTable
->GetTabLines();
4006 SwTableLine
* pLine
= rLines
.front();
4007 return pLine
->GetTabBoxes().size();
4010 uno::Any
SwXTableColumns::getByIndex(sal_Int32 nIndex
)
4012 SolarMutexGuard aGuard
;
4013 if(nIndex
< 0 || getCount() <= nIndex
)
4014 throw lang::IndexOutOfBoundsException();
4015 return uno::Any(uno::Reference
<uno::XInterface
>()); // i#21699 not supported
4018 uno::Type SAL_CALL
SwXTableColumns::getElementType()
4020 return cppu::UnoType
<uno::XInterface
>::get();
4023 sal_Bool
SwXTableColumns::hasElements()
4025 SolarMutexGuard aGuard
;
4026 lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
4030 ///@see SwXTableRows::insertByIndex (TODO: seems to be copy and paste programming here)
4031 void SwXTableColumns::insertByIndex(sal_Int32 nIndex
, sal_Int32 nCount
)
4033 SolarMutexGuard aGuard
;
4036 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
4037 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFrameFormat
), static_cast<cppu::OWeakObject
*>(this));
4038 SwTableLines
& rLines
= pTable
->GetTabLines();
4039 SwTableLine
* pLine
= rLines
.front();
4040 const size_t nColCount
= pLine
->GetTabBoxes().size();
4041 if (nCount
<= 0 || 0 > nIndex
|| o3tl::make_unsigned(nIndex
) > nColCount
)
4042 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
4043 const OUString sTLName
= sw_GetCellName(nIndex
, 0);
4044 const SwTableBox
* pTLBox
= pTable
->GetTableBox( sTLName
);
4045 bool bAppend
= false;
4049 // to append at the end the cursor must be in the last line
4050 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
4051 pTLBox
= rBoxes
.back();
4054 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
4055 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
4056 SwPosition
aPos(*pSttNd
);
4057 UnoActionContext
aAction(pFrameFormat
->GetDoc());
4058 auto pUnoCursor(pFrameFormat
->GetDoc()->CreateUnoCursor(aPos
, true));
4059 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
4062 // remove actions - TODO: why?
4063 UnoActionRemoveContext
aRemoveContext(&pUnoCursor
->GetDoc());
4066 pFrameFormat
->GetDoc()->InsertCol(*pUnoCursor
, o3tl::narrowing
<sal_uInt16
>(nCount
), bAppend
);
4069 ///@see SwXTableRows::removeByIndex (TODO: seems to be copy and paste programming here)
4070 void SwXTableColumns::removeByIndex(sal_Int32 nIndex
, sal_Int32 nCount
)
4072 SolarMutexGuard aGuard
;
4075 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
4076 if(nIndex
< 0 || nCount
<=0 )
4077 throw uno::RuntimeException();
4078 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFrameFormat
), static_cast<cppu::OWeakObject
*>(this));
4079 const OUString sTLName
= sw_GetCellName(nIndex
, 0);
4080 const SwTableBox
* pTLBox
= pTable
->GetTableBox( sTLName
);
4082 throw uno::RuntimeException("Cell not found", static_cast<cppu::OWeakObject
*>(this));
4083 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
4084 SwPosition
aPos(*pSttNd
);
4085 // set cursor to the upper-left cell of the range
4086 auto pUnoCursor(pFrameFormat
->GetDoc()->CreateUnoCursor(aPos
, true));
4087 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
4088 pUnoCursor
->SetRemainInSection(false);
4089 const OUString sTRName
= sw_GetCellName(nIndex
+ nCount
- 1, 0);
4090 const SwTableBox
* pTRBox
= pTable
->GetTableBox(sTRName
);
4092 throw uno::RuntimeException("Cell not found", static_cast<cppu::OWeakObject
*>(this));
4093 pUnoCursor
->SetMark();
4094 pUnoCursor
->GetPoint()->Assign( *pTRBox
->GetSttNd() );
4095 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
4096 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
4098 // HACK: remove pending actions for selecting old style tables
4099 UnoActionRemoveContext
aRemoveContext(rCursor
);
4101 rCursor
.MakeBoxSels();
4102 { // these braces are important
4103 UnoActionContext
aAction(pFrameFormat
->GetDoc());
4104 pFrameFormat
->GetDoc()->DeleteCol(*pUnoCursor
);
4108 // invalidate all actions - TODO: why?
4109 UnoActionRemoveContext
aRemoveContext(pFrameFormat
->GetDoc());
4113 void SwXTableColumns::Impl::Notify(const SfxHint
& rHint
)
4115 if(rHint
.GetId() == SfxHintId::Dying
)
4116 m_pFrameFormat
= nullptr;
4119 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */