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 <o3tl/any.hxx>
28 #include <svx/svxids.hrc>
29 #include <editeng/memberids.h>
31 #include <swtypes.hxx>
36 #include <unostyle.hxx>
37 #include <section.hxx>
38 #include <unocrsr.hxx>
39 #include <svx/unomid.hxx>
41 #include <swtblfmt.hxx>
43 #include <IDocumentUndoRedo.hxx>
44 #include <IDocumentContentOperations.hxx>
45 #include <IDocumentFieldsAccess.hxx>
46 #include <IDocumentState.hxx>
47 #include <IDocumentLayoutAccess.hxx>
48 #include <shellres.hxx>
53 #include <vcl/svapp.hxx>
54 #include <fmtfsize.hxx>
55 #include <tblafmt.hxx>
57 #include <cellatr.hxx>
58 #include <fmtpdsc.hxx>
59 #include <pagedesc.hxx>
61 #include <rootfrm.hxx>
63 #include <redline.hxx>
64 #include <unoport.hxx>
65 #include <unoprnms.hxx>
66 #include <unocrsrhelper.hxx>
67 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
68 #include <com/sun/star/text/WrapTextMode.hpp>
69 #include <com/sun/star/text/TextContentAnchorType.hpp>
70 #include <com/sun/star/text/TableColumnSeparator.hpp>
71 #include <com/sun/star/text/VertOrientation.hpp>
72 #include <com/sun/star/text/XTextSection.hpp>
73 #include <com/sun/star/table/ShadowFormat.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/BorderLineStyle.hpp>
78 #include <com/sun/star/table/TableBorderDistances.hpp>
79 #include <com/sun/star/style/PageStyleLayout.hpp>
80 #include <com/sun/star/style/BreakType.hpp>
81 #include <com/sun/star/style/GraphicLocation.hpp>
82 #include <com/sun/star/beans/PropertyAttribute.hpp>
83 #include <com/sun/star/chart/XChartDataChangeEventListener.hpp>
84 #include <com/sun/star/chart/ChartDataChangeEvent.hpp>
85 #include <com/sun/star/chart2/data/XDataSequence.hpp>
86 #include <com/sun/star/chart2/data/XLabeledDataSequence.hpp>
87 #include <com/sun/star/table/CellContentType.hpp>
88 #include <unotextrange.hxx>
89 #include <unotextcursor.hxx>
90 #include <unoparagraph.hxx>
91 #include <svl/zforlist.hxx>
92 #include <editeng/formatbreakitem.hxx>
93 #include <editeng/shaditem.hxx>
94 #include <editeng/lrspitem.hxx>
95 #include <editeng/ulspitem.hxx>
96 #include <fmtornt.hxx>
97 #include <editeng/keepitem.hxx>
98 #include <fmtlsplt.hxx>
100 #include <osl/mutex.hxx>
101 #include <SwStyleNameMapper.hxx>
102 #include <frmatr.hxx>
103 #include <unochart.hxx>
104 #include <sortopt.hxx>
105 #include <rtl/math.hxx>
106 #include <sal/log.hxx>
107 #include <editeng/frmdiritem.hxx>
108 #include <comphelper/interfacecontainer2.hxx>
109 #include <comphelper/servicehelper.hxx>
110 #include <comphelper/string.hxx>
111 #include <cppuhelper/supportsservice.hxx>
112 #include <comphelper/sequence.hxx>
113 #include <comphelper/sequenceashashmap.hxx>
114 #include <swtable.hxx>
117 #include <itabenum.hxx>
119 using namespace ::com::sun::star
;
120 using ::editeng::SvxBorderLine
;
124 template<typename Tcoretype
, typename Tunotype
>
125 struct FindUnoInstanceHint final
: SfxHint
127 FindUnoInstanceHint(Tcoretype
* pCore
) : m_pCore(pCore
), m_pResult(nullptr) {};
128 const Tcoretype
* const m_pCore
;
129 mutable Tunotype
* m_pResult
;
131 SwFrameFormat
* lcl_EnsureCoreConnected(SwFrameFormat
* pFormat
, cppu::OWeakObject
* pObject
)
134 throw uno::RuntimeException("Lost connection to core objects", pObject
);
137 SwTable
* lcl_EnsureTableNotComplex(SwTable
* pTable
, cppu::OWeakObject
* pObject
)
139 if(pTable
->IsTableComplex())
140 throw uno::RuntimeException("Table too complex", pObject
);
144 chart::ChartDataChangeEvent
createChartEvent(uno::Reference
<uno::XInterface
> const& xSource
)
146 //TODO: find appropriate settings of the Event
147 chart::ChartDataChangeEvent event
;
148 event
.Source
= xSource
;
149 event
.Type
= chart::ChartDataChangeType_ALL
;
150 event
.StartColumn
= 0;
157 void lcl_SendChartEvent(
158 uno::Reference
<uno::XInterface
> const& xSource
,
159 ::comphelper::OInterfaceContainerHelper2
& rListeners
)
161 rListeners
.notifyEach(
162 &chart::XChartDataChangeEventListener::chartDataChanged
,
163 createChartEvent(xSource
));
166 void lcl_SendChartEvent(
167 uno::Reference
<uno::XInterface
> const& xSource
,
168 ::cppu::OMultiTypeInterfaceContainerHelper
const& rListeners
)
170 auto pContainer(rListeners
.getContainer(cppu::UnoType
<chart::XChartDataChangeEventListener
>::get()));
172 pContainer
->notifyEach(
173 &chart::XChartDataChangeEventListener::chartDataChanged
,
174 createChartEvent(xSource
));
178 #define UNO_TABLE_COLUMN_SUM 10000
181 static bool lcl_LineToSvxLine(const table::BorderLine
& rLine
, SvxBorderLine
& rSvxLine
)
183 rSvxLine
.SetColor(Color(rLine
.Color
));
185 rSvxLine
.GuessLinesWidths( SvxBorderLineStyle::NONE
,
186 convertMm100ToTwip( rLine
.OuterLineWidth
),
187 convertMm100ToTwip( rLine
.InnerLineWidth
),
188 convertMm100ToTwip( rLine
.LineDistance
) );
190 return rLine
.InnerLineWidth
> 0 || rLine
.OuterLineWidth
> 0;
193 /// @throws lang::IllegalArgumentException
194 /// @throws uno::RuntimeException
195 static void lcl_SetSpecialProperty(SwFrameFormat
* pFormat
,
196 const SfxItemPropertySimpleEntry
* pEntry
,
197 const uno::Any
& aValue
)
199 // special treatment for "non-items"
202 case FN_TABLE_HEADLINE_REPEAT
:
203 case FN_TABLE_HEADLINE_COUNT
:
205 SwTable
* pTable
= SwTable::FindTable( pFormat
);
206 UnoActionContext
aAction(pFormat
->GetDoc());
207 if( pEntry
->nWID
== FN_TABLE_HEADLINE_REPEAT
)
209 pFormat
->GetDoc()->SetRowsToRepeat( *pTable
, aValue
.get
<bool>() ? 1 : 0 );
213 sal_Int32 nRepeat
= 0;
215 if( nRepeat
>= 0 && nRepeat
< SAL_MAX_UINT16
)
216 pFormat
->GetDoc()->SetRowsToRepeat( *pTable
, static_cast<sal_uInt16
>(nRepeat
) );
221 case FN_TABLE_IS_RELATIVE_WIDTH
:
223 case FN_TABLE_RELATIVE_WIDTH
:
225 SwFormatFrameSize
aSz( pFormat
->GetFrameSize() );
226 if(FN_TABLE_WIDTH
== pEntry
->nWID
)
228 sal_Int32 nWidth
= 0;
230 aSz
.SetWidthPercent(0);
231 aSz
.SetWidth ( convertMm100ToTwip ( nWidth
) );
233 else if(FN_TABLE_RELATIVE_WIDTH
== pEntry
->nWID
)
237 if(nSet
&& nSet
<=100)
238 aSz
.SetWidthPercent( static_cast<sal_uInt8
>(nSet
) );
240 else if(FN_TABLE_IS_RELATIVE_WIDTH
== pEntry
->nWID
)
242 if(!aValue
.get
<bool>())
243 aSz
.SetWidthPercent(0);
246 lang::IllegalArgumentException aExcept
;
247 aExcept
.Message
= "relative width cannot be switched on with this property";
251 pFormat
->GetDoc()->SetAttr(aSz
, *pFormat
);
258 aValue
>>= sPageStyle
;
259 const SwPageDesc
* pDesc
= nullptr;
260 if (!sPageStyle
.isEmpty())
262 SwStyleNameMapper::FillUIName(sPageStyle
, sPageStyle
, SwGetPoolIdFromName::PageDesc
);
263 pDesc
= SwPageDesc::GetByName(*pFormat
->GetDoc(), sPageStyle
);
265 SwFormatPageDesc
aDesc( pDesc
);
266 pFormat
->GetDoc()->SetAttr(aDesc
, *pFormat
);
271 throw lang::IllegalArgumentException();
275 static uno::Any
lcl_GetSpecialProperty(SwFrameFormat
* pFormat
, const SfxItemPropertySimpleEntry
* pEntry
)
279 case FN_TABLE_HEADLINE_REPEAT
:
280 case FN_TABLE_HEADLINE_COUNT
:
282 SwTable
* pTable
= SwTable::FindTable( pFormat
);
283 const sal_uInt16 nRepeat
= pTable
->GetRowsToRepeat();
284 if(pEntry
->nWID
== FN_TABLE_HEADLINE_REPEAT
)
285 return uno::makeAny
<bool>(nRepeat
> 0);
286 return uno::makeAny
<sal_Int32
>(nRepeat
);
290 case FN_TABLE_IS_RELATIVE_WIDTH
:
291 case FN_TABLE_RELATIVE_WIDTH
:
294 const SwFormatFrameSize
& rSz
= pFormat
->GetFrameSize();
295 if(FN_TABLE_WIDTH
== pEntry
->nWID
)
296 rSz
.QueryValue(aRet
, MID_FRMSIZE_WIDTH
|CONVERT_TWIPS
);
297 else if(FN_TABLE_RELATIVE_WIDTH
== pEntry
->nWID
)
298 rSz
.QueryValue(aRet
, MID_FRMSIZE_REL_WIDTH
);
300 aRet
<<= (0 != rSz
.GetWidthPercent());
306 const SfxItemSet
& rSet
= pFormat
->GetAttrSet();
307 const SfxPoolItem
* pItem
;
308 if(SfxItemState::SET
== rSet
.GetItemState(RES_PAGEDESC
, false, &pItem
))
310 const SwPageDesc
* pDsc
= static_cast<const SwFormatPageDesc
*>(pItem
)->GetPageDesc();
312 return uno::makeAny
<OUString
>(SwStyleNameMapper::GetProgName(pDsc
->GetName(), SwGetPoolIdFromName::PageDesc
));
314 return uno::makeAny(OUString());
318 return uno::makeAny(text::TextContentAnchorType_AT_PARAGRAPH
);
320 case FN_UNO_ANCHOR_TYPES
:
322 uno::Sequence
<text::TextContentAnchorType
> aTypes
{text::TextContentAnchorType_AT_PARAGRAPH
};
323 return uno::makeAny(aTypes
);
327 return uno::makeAny(text::WrapTextMode_NONE
);
329 case FN_PARAM_LINK_DISPLAY_NAME
:
330 return uno::makeAny(pFormat
->GetName());
332 case FN_UNO_REDLINE_NODE_START
:
333 case FN_UNO_REDLINE_NODE_END
:
335 SwTable
* pTable
= SwTable::FindTable( pFormat
);
336 SwNode
* pTableNode
= pTable
->GetTableNode();
337 if(FN_UNO_REDLINE_NODE_END
== pEntry
->nWID
)
338 pTableNode
= pTableNode
->EndOfSectionNode();
339 for(const SwRangeRedline
* pRedline
: pFormat
->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable())
341 const SwNode
& rRedPointNode
= pRedline
->GetNode();
342 const SwNode
& rRedMarkNode
= pRedline
->GetNode(false);
343 if(&rRedPointNode
== pTableNode
|| &rRedMarkNode
== pTableNode
)
345 const SwNode
& rStartOfRedline
= SwNodeIndex(rRedPointNode
) <= SwNodeIndex(rRedMarkNode
) ?
346 rRedPointNode
: rRedMarkNode
;
347 bool bIsStart
= &rStartOfRedline
== pTableNode
;
348 return uno::makeAny(SwXRedlinePortion::CreateRedlineProperties(*pRedline
, bIsStart
));
356 /** get position of a cell with a given name
358 * If everything was OK, the indices for column and row are changed (both >= 0).
359 * In case of errors, at least one of them is < 0.
361 * Also since the implementations of tables does not really have columns using
362 * this function is appropriate only for tables that are not complex (i.e.
363 * where IsTableComplex() returns false).
365 * @param rCellName e.g. A1..Z1, a1..z1, AA1..AZ1, Aa1..Az1, BA1..BZ1, Ba1..Bz1, ...
366 * @param [IN,OUT] o_rColumn (0-based)
367 * @param [IN,OUT] o_rRow (0-based)
369 //TODO: potential for throwing proper exceptions instead of having every caller to check for errors
370 void SwXTextTable::GetCellPosition(const OUString
& rCellName
, sal_Int32
& o_rColumn
, sal_Int32
& o_rRow
)
372 o_rColumn
= o_rRow
= -1; // default return values indicating failure
373 const sal_Int32 nLen
= rCellName
.getLength();
376 SAL_WARN("sw.uno", "failed to get column or row index");
379 sal_Int32 nRowPos
= 0;
382 if (rCellName
[nRowPos
]>='0' && rCellName
[nRowPos
]<='9')
388 if (nRowPos
>0 && nRowPos
<nLen
)
390 sal_Int32 nColIdx
= 0;
391 for (sal_Int32 i
= 0; i
< nRowPos
; ++i
)
396 const sal_Unicode cChar
= rCellName
[i
];
397 if ('A' <= cChar
&& cChar
<= 'Z')
398 nColIdx
+= cChar
- 'A';
399 else if ('a' <= cChar
&& cChar
<= 'z')
400 nColIdx
+= 26 + cChar
- 'a';
403 nColIdx
= -1; // sth failed
409 o_rRow
= rCellName
.copy(nRowPos
).toInt32() - 1; // - 1 because indices ought to be 0 based
413 /** compare position of two cells (check rows first)
415 * @note this function probably also make sense only
416 * for cell names of non-complex tables
418 * @param rCellName1 e.g. "A1" (non-empty string with valid cell name)
419 * @param rCellName2 e.g. "A1" (non-empty string with valid cell name)
420 * @return -1 if cell_1 < cell_2; 0 if both cells are equal; +1 if cell_1 > cell_2
422 int sw_CompareCellsByRowFirst( const OUString
&rCellName1
, const OUString
&rCellName2
)
424 sal_Int32 nCol1
= -1, nRow1
= -1, nCol2
= -1, nRow2
= -1;
425 SwXTextTable::GetCellPosition( rCellName1
, nCol1
, nRow1
);
426 SwXTextTable::GetCellPosition( rCellName2
, nCol2
, nRow2
);
428 if (nRow1
< nRow2
|| (nRow1
== nRow2
&& nCol1
< nCol2
))
430 else if (nCol1
== nCol2
&& nRow1
== nRow2
)
436 /** compare position of two cells (check columns first)
438 * @note this function probably also make sense only
439 * for cell names of non-complex tables
441 * @param rCellName1 e.g. "A1" (non-empty string with valid cell name)
442 * @param rCellName2 e.g. "A1" (non-empty string with valid cell name)
443 * @return -1 if cell_1 < cell_2; 0 if both cells are equal; +1 if cell_1 > cell_2
445 int sw_CompareCellsByColFirst( const OUString
&rCellName1
, const OUString
&rCellName2
)
447 sal_Int32 nCol1
= -1, nRow1
= -1, nCol2
= -1, nRow2
= -1;
448 SwXTextTable::GetCellPosition( rCellName1
, nCol1
, nRow1
);
449 SwXTextTable::GetCellPosition( rCellName2
, nCol2
, nRow2
);
451 if (nCol1
< nCol2
|| (nCol1
== nCol2
&& nRow1
< nRow2
))
453 else if (nRow1
== nRow2
&& nCol1
== nCol2
)
459 /** compare position of two cell ranges
461 * @note this function probably also make sense only
462 * for cell names of non-complex tables
464 * @param rRange1StartCell e.g. "A1" (non-empty string with valid cell name)
465 * @param rRange1EndCell e.g. "A1" (non-empty string with valid cell name)
466 * @param rRange2StartCell e.g. "A1" (non-empty string with valid cell name)
467 * @param rRange2EndCell e.g. "A1" (non-empty string with valid cell name)
468 * @param bCmpColsFirst if <true> position in columns will be compared first before rows
470 * @return -1 if cell_range_1 < cell_range_2; 0 if both cell ranges are equal; +1 if cell_range_1 > cell_range_2
472 int sw_CompareCellRanges(
473 const OUString
&rRange1StartCell
, const OUString
&rRange1EndCell
,
474 const OUString
&rRange2StartCell
, const OUString
&rRange2EndCell
,
477 int (*pCompareCells
)( const OUString
&, const OUString
& ) =
478 bCmpColsFirst
? &sw_CompareCellsByColFirst
: &sw_CompareCellsByRowFirst
;
480 int nCmpResStartCells
= pCompareCells( rRange1StartCell
, rRange2StartCell
);
481 if ((-1 == nCmpResStartCells
) ||
482 ( 0 == nCmpResStartCells
&&
483 -1 == pCompareCells( rRange1EndCell
, rRange2EndCell
) ))
485 else if (0 == nCmpResStartCells
&&
486 0 == pCompareCells( rRange1EndCell
, rRange2EndCell
))
492 /** get cell name at a specified coordinate
494 * @param nColumn column index (0-based)
495 * @param nRow row index (0-based)
496 * @return the cell name
498 OUString
sw_GetCellName( sal_Int32 nColumn
, sal_Int32 nRow
)
500 if (nColumn
< 0 || nRow
< 0)
503 sw_GetTableBoxColStr( static_cast< sal_uInt16
>(nColumn
), sCellName
);
504 return sCellName
+ OUString::number( nRow
+ 1 );
507 /** Find the top left or bottom right corner box in given table.
508 Consider nested lines when finding the box.
510 @param rTableLines the table
511 @param i_bTopLeft if true, find top left box, otherwise find bottom
514 static const SwTableBox
* lcl_FindCornerTableBox(const SwTableLines
& rTableLines
, const bool i_bTopLeft
)
516 const SwTableLines
* pLines(&rTableLines
);
519 assert(!pLines
->empty());
522 const SwTableLine
* pLine(i_bTopLeft
? pLines
->front() : pLines
->back());
524 const SwTableBoxes
& rBoxes(pLine
->GetTabBoxes());
525 assert(rBoxes
.size() != 0);
526 const SwTableBox
* pBox
= i_bTopLeft
? rBoxes
.front() : rBoxes
.back();
528 if (pBox
->GetSttNd())
530 pLines
= &pBox
->GetTabLines();
534 /** cleanup order in a range
536 * Sorts the input to a uniform format. I.e. for the four possible representation
537 * A1:C5, C5:A1, A5:C1, C1:A5
538 * the result will be always A1:C5.
540 * @param [IN,OUT] rCell1 cell name (will be modified to upper-left corner), e.g. "A1" (non-empty string with valid cell name)
541 * @param [IN,OUT] rCell2 cell name (will be modified to lower-right corner), e.g. "A1" (non-empty string with valid cell name)
543 void sw_NormalizeRange(OUString
&rCell1
, OUString
&rCell2
)
545 sal_Int32 nCol1
= -1, nRow1
= -1, nCol2
= -1, nRow2
= -1;
546 SwXTextTable::GetCellPosition( rCell1
, nCol1
, nRow1
);
547 SwXTextTable::GetCellPosition( rCell2
, nCol2
, nRow2
);
548 if (nCol2
< nCol1
|| nRow2
< nRow1
)
550 rCell1
= sw_GetCellName( std::min(nCol1
, nCol2
), std::min(nRow1
, nRow2
) );
551 rCell2
= sw_GetCellName( std::max(nCol1
, nCol2
), std::max(nRow1
, nRow2
) );
555 void SwRangeDescriptor::Normalize()
558 std::swap(nBottom
, nTop
);
560 std::swap(nLeft
, nRight
);
563 static SwXCell
* lcl_CreateXCell(SwFrameFormat
* pFormat
, sal_Int32 nColumn
, sal_Int32 nRow
)
565 const OUString sCellName
= sw_GetCellName(nColumn
, nRow
);
566 SwTable
* pTable
= SwTable::FindTable(pFormat
);
567 SwTableBox
* pBox
= const_cast<SwTableBox
*>(pTable
->GetTableBox(sCellName
));
570 return SwXCell::CreateXCell(pFormat
, pBox
, pTable
);
573 static void lcl_InspectLines(SwTableLines
& rLines
, std::vector
<OUString
>& rAllNames
)
575 for(auto pLine
: rLines
)
577 for(auto pBox
: pLine
->GetTabBoxes())
579 if(!pBox
->GetName().isEmpty() && pBox
->getRowSpan() > 0)
580 rAllNames
.push_back(pBox
->GetName());
581 SwTableLines
& rBoxLines
= pBox
->GetTabLines();
582 if(!rBoxLines
.empty())
583 lcl_InspectLines(rBoxLines
, rAllNames
);
588 static bool lcl_FormatTable(SwFrameFormat
const * pTableFormat
)
590 bool bHasFrames
= false;
591 SwIterator
<SwFrame
,SwFormat
> aIter( *pTableFormat
);
592 for(SwFrame
* pFrame
= aIter
.First(); pFrame
; pFrame
= aIter
.Next())
594 vcl::RenderContext
* pRenderContext
= pFrame
->getRootFrame()->GetCurrShell()->GetOut();
595 // mba: no TYPEINFO for SwTabFrame
596 if(!pFrame
->IsTabFrame())
598 DisableCallbackAction
a(*pFrame
->getRootFrame());
599 SwTabFrame
* pTabFrame
= static_cast<SwTabFrame
*>(pFrame
);
600 if(pTabFrame
->isFrameAreaDefinitionValid())
601 pTabFrame
->InvalidatePos();
602 pTabFrame
->SetONECalcLowers();
603 pTabFrame
->Calc(pRenderContext
);
609 static void lcl_CursorSelect(SwPaM
& rCursor
, bool bExpand
)
613 if(!rCursor
.HasMark())
616 else if(rCursor
.HasMark())
617 rCursor
.DeleteMark();
620 static void lcl_GetTableSeparators(uno::Any
& rRet
, SwTable
const * pTable
, SwTableBox
const * pBox
, bool bRow
)
623 aCols
.SetLeftMin ( 0 );
625 aCols
.SetRight ( UNO_TABLE_COLUMN_SUM
);
626 aCols
.SetRightMax( UNO_TABLE_COLUMN_SUM
);
628 pTable
->GetTabCols( aCols
, pBox
, false, bRow
);
630 const size_t nSepCount
= aCols
.Count();
631 uno::Sequence
< text::TableColumnSeparator
> aColSeq(nSepCount
);
632 text::TableColumnSeparator
* pArray
= aColSeq
.getArray();
634 for(size_t i
= 0; i
< nSepCount
; ++i
)
636 pArray
[i
].Position
= static_cast< sal_Int16
>(aCols
[i
]);
637 pArray
[i
].IsVisible
= !aCols
.IsHidden(i
);
638 if(!bRow
&& !pArray
[i
].IsVisible
)
649 static void lcl_SetTableSeparators(const uno::Any
& rVal
, SwTable
* pTable
, SwTableBox
const * pBox
, bool bRow
, SwDoc
* pDoc
)
653 aOldCols
.SetLeftMin ( 0 );
654 aOldCols
.SetLeft ( 0 );
655 aOldCols
.SetRight ( UNO_TABLE_COLUMN_SUM
);
656 aOldCols
.SetRightMax( UNO_TABLE_COLUMN_SUM
);
658 pTable
->GetTabCols( aOldCols
, pBox
, false, bRow
);
659 const size_t nOldCount
= aOldCols
.Count();
660 // there is no use in setting tab cols if there is only one column
665 o3tl::tryAccess
<uno::Sequence
<text::TableColumnSeparator
>>(rVal
);
666 if(!pSepSeq
|| static_cast<size_t>(pSepSeq
->getLength()) != nOldCount
)
668 SwTabCols
aCols(aOldCols
);
669 const text::TableColumnSeparator
* pArray
= pSepSeq
->getConstArray();
671 //sal_Int32 nTableWidth = aCols.GetRight() - aCols.GetLeft();
672 for(size_t i
= 0; i
< nOldCount
; ++i
)
674 aCols
[i
] = pArray
[i
].Position
;
675 if(bool(pArray
[i
].IsVisible
) == aCols
.IsHidden(i
) ||
676 (!bRow
&& aCols
.IsHidden(i
)) ||
677 aCols
[i
] < nLastValue
||
678 UNO_TABLE_COLUMN_SUM
< aCols
[i
] )
679 return; // probably this should assert()
680 nLastValue
= aCols
[i
];
682 pDoc
->SetTabCols(*pTable
, aCols
, aOldCols
, pBox
, bRow
);
685 /* non UNO function call to set string in SwXCell */
686 void sw_setString( SwXCell
&rCell
, const OUString
&rText
,
687 bool bKeepNumberFormat
= false )
691 SwFrameFormat
* pBoxFormat
= rCell
.m_pBox
->ClaimFrameFormat();
692 pBoxFormat
->LockModify();
693 pBoxFormat
->ResetFormatAttr( RES_BOXATR_FORMULA
);
694 pBoxFormat
->ResetFormatAttr( RES_BOXATR_VALUE
);
695 if (!bKeepNumberFormat
)
696 pBoxFormat
->SetFormatAttr( SwTableBoxNumFormat(/*default Text*/) );
697 pBoxFormat
->UnlockModify();
699 rCell
.SwXText::setString(rText
);
703 /* non UNO function call to set value in SwXCell */
704 void sw_setValue( SwXCell
&rCell
, double nVal
)
708 // first this text (maybe) needs to be deleted
709 sal_uLong nNdPos
= rCell
.m_pBox
->IsValidNumTextNd();
710 if(ULONG_MAX
!= nNdPos
)
711 sw_setString( rCell
, OUString(), true ); // true == keep number format
712 SwDoc
* pDoc
= rCell
.GetDoc();
713 UnoActionContext
aAction(pDoc
);
714 SwFrameFormat
* pBoxFormat
= rCell
.m_pBox
->ClaimFrameFormat();
715 SfxItemSet
aSet(pDoc
->GetAttrPool(), svl::Items
<RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
>{});
716 const SfxPoolItem
* pItem
;
718 //!! do we need to set a new number format? Yes, if
719 // - there is no current number format
720 // - the current number format is not a number format according to the number formatter, but rather a text format
721 if(SfxItemState::SET
!= pBoxFormat
->GetAttrSet().GetItemState(RES_BOXATR_FORMAT
, true, &pItem
)
722 || pDoc
->GetNumberFormatter()->IsTextFormat(static_cast<const SwTableBoxNumFormat
*>(pItem
)->GetValue()))
724 aSet
.Put(SwTableBoxNumFormat(0));
727 SwTableBoxValue
aVal(nVal
);
729 pDoc
->SetTableBoxFormulaAttrs( *rCell
.m_pBox
, aSet
);
731 SwTableFormulaUpdate
aTableUpdate( SwTable::FindTable( rCell
.GetFrameFormat() ));
732 pDoc
->getIDocumentFieldsAccess().UpdateTableFields( &aTableUpdate
);
736 SwXCell::SwXCell(SwFrameFormat
* pTableFormat
, SwTableBox
* pBx
, size_t const nPos
) :
737 SwXText(pTableFormat
->GetDoc(), CursorType::TableText
),
738 m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TABLE_CELL
)),
740 m_pStartNode(nullptr),
741 m_pTableFormat(pTableFormat
),
744 StartListening(pTableFormat
->GetNotifier());
747 SwXCell::SwXCell(SwFrameFormat
* pTableFormat
, const SwStartNode
& rStartNode
) :
748 SwXText(pTableFormat
->GetDoc(), CursorType::TableText
),
749 m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TABLE_CELL
)),
751 m_pStartNode(&rStartNode
),
752 m_pTableFormat(pTableFormat
),
755 StartListening(pTableFormat
->GetNotifier());
760 SolarMutexGuard aGuard
;
766 class theSwXCellUnoTunnelId
: public rtl::Static
< UnoTunnelIdInit
, theSwXCellUnoTunnelId
> {};
769 const uno::Sequence
< sal_Int8
> & SwXCell::getUnoTunnelId()
771 return theSwXCellUnoTunnelId::get().getSeq();
774 sal_Int64 SAL_CALL
SwXCell::getSomething( const uno::Sequence
< sal_Int8
>& rId
)
776 if( rId
.getLength() == 16
777 && 0 == memcmp( getUnoTunnelId().getConstArray(),
778 rId
.getConstArray(), 16 ) )
780 return sal::static_int_cast
< sal_Int64
>( reinterpret_cast< sal_IntPtr
>(this) );
783 return SwXText::getSomething(rId
);
786 uno::Sequence
< uno::Type
> SAL_CALL
SwXCell::getTypes( )
788 return comphelper::concatSequences(
789 SwXCellBaseClass::getTypes(),
794 uno::Sequence
< sal_Int8
> SAL_CALL
SwXCell::getImplementationId( )
796 return css::uno::Sequence
<sal_Int8
>();
799 void SAL_CALL
SwXCell::acquire( ) throw()
801 SwXCellBaseClass::acquire();
804 void SAL_CALL
SwXCell::release( ) throw()
806 SolarMutexGuard aGuard
;
808 SwXCellBaseClass::release();
811 uno::Any SAL_CALL
SwXCell::queryInterface( const uno::Type
& aType
)
813 uno::Any aRet
= SwXCellBaseClass::queryInterface(aType
);
814 if(aRet
.getValueType() == cppu::UnoType
<void>::get())
815 aRet
= SwXText::queryInterface(aType
);
819 const SwStartNode
*SwXCell::GetStartNode() const
821 const SwStartNode
* pSttNd
= nullptr;
823 if( m_pStartNode
|| IsValid() )
824 pSttNd
= m_pStartNode
? m_pStartNode
: m_pBox
->GetSttNd();
829 uno::Reference
< text::XTextCursor
>
830 SwXCell::CreateCursor()
832 return createTextCursor();
835 bool SwXCell::IsValid() const
837 // FIXME: this is now a const method, to make SwXText::IsValid invisible
838 // but the const_cast here are still ridiculous. TODO: find a better way.
839 SwFrameFormat
* pTableFormat
= m_pBox
? GetFrameFormat() : nullptr;
842 const_cast<SwXCell
*>(this)->m_pBox
= nullptr;
846 SwTable
* pTable
= SwTable::FindTable( pTableFormat
);
847 SwTableBox
const*const pFoundBox
=
848 const_cast<SwXCell
*>(this)->FindBox(pTable
, m_pBox
);
851 const_cast<SwXCell
*>(this)->m_pBox
= nullptr;
854 return nullptr != m_pBox
;
857 OUString
SwXCell::getFormula()
859 SolarMutexGuard aGuard
;
862 SwTableBoxFormula
aFormula( m_pBox
->GetFrameFormat()->GetTableBoxFormula() );
863 SwTable
* pTable
= SwTable::FindTable( GetFrameFormat() );
864 aFormula
.PtrToBoxNm( pTable
);
865 return aFormula
.GetFormula();
868 ///@see sw_setValue (TODO: seems to be copy and paste programming here)
869 void SwXCell::setFormula(const OUString
& rFormula
)
871 SolarMutexGuard aGuard
;
874 // first this text (maybe) needs to be deleted
875 sal_uInt32 nNdPos
= m_pBox
->IsValidNumTextNd();
876 if(USHRT_MAX
== nNdPos
)
877 sw_setString( *this, OUString(), true );
878 OUString
sFormula(comphelper::string::stripStart(rFormula
, ' '));
879 if( !sFormula
.isEmpty() && '=' == sFormula
[0] )
880 sFormula
= sFormula
.copy( 1 );
881 SwTableBoxFormula
aFormula( sFormula
);
882 SwDoc
* pMyDoc
= GetDoc();
883 UnoActionContext
aAction(pMyDoc
);
884 SfxItemSet
aSet(pMyDoc
->GetAttrPool(), svl::Items
<RES_BOXATR_FORMAT
, RES_BOXATR_FORMULA
>{});
885 const SfxPoolItem
* pItem
;
886 SwFrameFormat
* pBoxFormat
= m_pBox
->GetFrameFormat();
887 if(SfxItemState::SET
!= pBoxFormat
->GetAttrSet().GetItemState(RES_BOXATR_FORMAT
, true, &pItem
)
888 || pMyDoc
->GetNumberFormatter()->IsTextFormat(static_cast<const SwTableBoxNumFormat
*>(pItem
)->GetValue()))
890 aSet
.Put(SwTableBoxNumFormat(0));
893 GetDoc()->SetTableBoxFormulaAttrs( *m_pBox
, aSet
);
895 SwTableFormulaUpdate
aTableUpdate( SwTable::FindTable( GetFrameFormat() ));
896 pMyDoc
->getIDocumentFieldsAccess().UpdateTableFields( &aTableUpdate
);
899 double SwXCell::getValue()
901 SolarMutexGuard aGuard
;
902 // #i112652# a table cell may contain NaN as a value, do not filter that
904 if(IsValid() && !getString().isEmpty())
905 fRet
= m_pBox
->GetFrameFormat()->GetTableBoxValue().GetValue();
907 ::rtl::math::setNan( &fRet
);
911 void SwXCell::setValue(double rValue
)
913 SolarMutexGuard aGuard
;
914 sw_setValue( *this, rValue
);
917 table::CellContentType
SwXCell::getType()
919 SolarMutexGuard aGuard
;
921 table::CellContentType nRes
= table::CellContentType_EMPTY
;
922 sal_uInt32 nNdPos
= m_pBox
->IsFormulaOrValueBox();
925 case 0 : nRes
= table::CellContentType_TEXT
; break;
926 case USHRT_MAX
: nRes
= table::CellContentType_EMPTY
; break;
927 case RES_BOXATR_VALUE
: nRes
= table::CellContentType_VALUE
; break;
928 case RES_BOXATR_FORMULA
: nRes
= table::CellContentType_FORMULA
; break;
930 OSL_FAIL( "unexpected case" );
935 void SwXCell::setString(const OUString
& aString
)
937 SolarMutexGuard aGuard
;
938 sw_setString( *this, aString
);
941 sal_Int32
SwXCell::getError()
943 SolarMutexGuard aGuard
;
944 OUString sContent
= getString();
945 return sal_Int32(sContent
== SwViewShell::GetShellRes()->aCalc_Error
);
948 uno::Reference
<text::XTextCursor
> SwXCell::createTextCursor()
950 SolarMutexGuard aGuard
;
951 if(!m_pStartNode
&& !IsValid())
952 throw uno::RuntimeException();
953 const SwStartNode
* pSttNd
= m_pStartNode
? m_pStartNode
: m_pBox
->GetSttNd();
954 SwPosition
aPos(*pSttNd
);
955 SwXTextCursor
* const pXCursor
=
956 new SwXTextCursor(*GetDoc(), this, CursorType::TableText
, aPos
);
957 auto& rUnoCursor(pXCursor
->GetCursor());
958 rUnoCursor
.Move(fnMoveForward
, GoInNode
);
959 return static_cast<text::XWordCursor
*>(pXCursor
);
962 uno::Reference
<text::XTextCursor
> SwXCell::createTextCursorByRange(const uno::Reference
< text::XTextRange
> & xTextPosition
)
964 SolarMutexGuard aGuard
;
965 SwUnoInternalPaM
aPam(*GetDoc());
966 if((!m_pStartNode
&& !IsValid()) || !::sw::XTextRangeToSwPaM(aPam
, xTextPosition
))
967 throw uno::RuntimeException();
968 const SwStartNode
* pSttNd
= m_pStartNode
? m_pStartNode
: m_pBox
->GetSttNd();
970 SwStartNode
* p1
= aPam
.GetNode().StartOfSectionNode();
971 while(p1
->IsSectionNode())
972 p1
= p1
->StartOfSectionNode();
975 return static_cast<text::XWordCursor
*>(
976 new SwXTextCursor(*GetDoc(), this, CursorType::TableText
,
977 *aPam
.GetPoint(), aPam
.GetMark()));
980 uno::Reference
< beans::XPropertySetInfo
> SwXCell::getPropertySetInfo()
982 static uno::Reference
< beans::XPropertySetInfo
> xRef
= m_pPropSet
->getPropertySetInfo();
986 void SwXCell::setPropertyValue(const OUString
& rPropertyName
, const uno::Any
& aValue
)
988 SolarMutexGuard aGuard
;
991 // Hack to support hidden property to transfer textDirection
992 if(rPropertyName
== "FRMDirection")
994 SvxFrameDirectionItem
aItem(SvxFrameDirection::Environment
, RES_FRAMEDIR
);
995 aItem
.PutValue(aValue
, 0);
996 m_pBox
->GetFrameFormat()->SetFormatAttr(aItem
);
998 else if(rPropertyName
== "TableRedlineParams")
1000 // Get the table row properties
1001 uno::Sequence
<beans::PropertyValue
> tableCellProperties
= aValue
.get
< uno::Sequence
< beans::PropertyValue
> >();
1002 comphelper::SequenceAsHashMap
aPropMap(tableCellProperties
);
1003 OUString sRedlineType
;
1004 if(!(aPropMap
.getValue("RedlineType") >>= sRedlineType
))
1005 throw beans::UnknownPropertyException("No redline type property: ", static_cast<cppu::OWeakObject
*>(this));
1007 // Create a 'Table Cell Redline' object
1008 SwUnoCursorHelper::makeTableCellRedline(*m_pBox
, sRedlineType
, tableCellProperties
);
1014 auto pEntry(m_pPropSet
->getPropertyMap().getByName(rPropertyName
));
1017 // not a table property: if it is a paragraph/character property, consider applying it to the underlying text.
1018 const SfxItemPropertySet
& rParaPropSet
= *aSwMapProvider
.GetPropertySet(PROPERTY_MAP_PARAGRAPH
);
1019 pEntry
= rParaPropSet
.getPropertyMap().getByName(rPropertyName
);
1023 SwNodeIndex
aIdx( *GetStartNode(), 1 );
1024 const SwNode
* pEndNd
= aIdx
.GetNode().EndOfSectionNode();
1025 while ( &aIdx
.GetNode() != pEndNd
)
1027 const SwTextNode
* pNd
= aIdx
.GetNode().GetTextNode();
1030 //point and mark selecting the whole paragraph
1031 SwPaM
aPaM(*pNd
, 0, *pNd
, pNd
->GetText().getLength());
1032 const bool bHasAttrSet
= pNd
->HasSwAttrSet();
1033 const SfxItemSet
& aSet
= pNd
->GetSwAttrSet();
1034 // isPARATR: replace DEFAULT_VALUE properties only
1035 // isCHRATR: change the base/auto SwAttr property, but don't remove the DIRECT hints
1036 if ( !bHasAttrSet
|| SfxItemState::DEFAULT
== aSet
.GetItemState(pEntry
->nWID
, /*bSrchInParent=*/false) )
1037 SwUnoCursorHelper::SetPropertyValue(aPaM
, rParaPropSet
, rPropertyName
, aValue
, SetAttrMode::DONTREPLACE
);
1046 throw beans::UnknownPropertyException(rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
1047 if(pEntry
->nWID
!= FN_UNO_CELL_ROW_SPAN
)
1049 SwFrameFormat
* pBoxFormat
= m_pBox
->ClaimFrameFormat();
1050 SwAttrSet
aSet(pBoxFormat
->GetAttrSet());
1051 m_pPropSet
->setPropertyValue(rPropertyName
, aValue
, aSet
);
1052 pBoxFormat
->GetDoc()->SetAttr(aSet
, *pBoxFormat
);
1054 else if(aValue
.isExtractableTo(cppu::UnoType
<sal_Int32
>::get()))
1055 m_pBox
->setRowSpan(aValue
.get
<sal_Int32
>());
1059 uno::Any
SwXCell::getPropertyValue(const OUString
& rPropertyName
)
1061 SolarMutexGuard aGuard
;
1064 auto pEntry(m_pPropSet
->getPropertyMap().getByName(rPropertyName
));
1066 throw beans::UnknownPropertyException(rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
1067 switch(pEntry
->nWID
)
1069 case FN_UNO_CELL_ROW_SPAN
:
1070 return uno::makeAny(m_pBox
->getRowSpan());
1072 case FN_UNO_TEXT_SECTION
:
1074 SwFrameFormat
* pTableFormat
= GetFrameFormat();
1075 SwTable
* pTable
= SwTable::FindTable(pTableFormat
);
1076 SwTableNode
* pTableNode
= pTable
->GetTableNode();
1077 SwSectionNode
* pSectionNode
= pTableNode
->FindSectionNode();
1080 SwSection
& rSect
= pSectionNode
->GetSection();
1081 return uno::makeAny(SwXTextSections::GetObject(*rSect
.GetFormat()));
1084 case FN_UNO_CELL_NAME
:
1085 return uno::makeAny(m_pBox
->GetName());
1087 case FN_UNO_REDLINE_NODE_START
:
1088 case FN_UNO_REDLINE_NODE_END
:
1090 //redline can only be returned if it's a living object
1091 return SwXText::getPropertyValue(rPropertyName
);
1094 case FN_UNO_PARENT_TEXT
:
1096 if (!m_xParentText
.is())
1098 const SwStartNode
* pSttNd
= m_pBox
->GetSttNd();
1102 const SwTableNode
* pTableNode
= pSttNd
->FindTableNode();
1106 SwPosition
aPos(*pTableNode
);
1107 SwDoc
* pDoc
= aPos
.GetDoc();
1111 m_xParentText
= sw::CreateParentXText(*pDoc
, aPos
);
1114 return uno::makeAny(m_xParentText
);
1119 const SwAttrSet
& rSet
= m_pBox
->GetFrameFormat()->GetAttrSet();
1121 m_pPropSet
->getPropertyValue(rPropertyName
, rSet
, aResult
);
1127 void SwXCell::addPropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1128 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1130 void SwXCell::removePropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1131 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1133 void SwXCell::addVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1134 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1136 void SwXCell::removeVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1137 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1139 uno::Reference
<container::XEnumeration
> SwXCell::createEnumeration()
1141 SolarMutexGuard aGuard
;
1143 return uno::Reference
<container::XEnumeration
>();
1144 const SwStartNode
* pSttNd
= m_pBox
->GetSttNd();
1145 SwPosition
aPos(*pSttNd
);
1146 auto pUnoCursor(GetDoc()->CreateUnoCursor(aPos
));
1147 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
1148 // remember table and start node for later travelling
1149 // (used in export of tables in tables)
1150 SwTable
const*const pTable(&pSttNd
->FindTableNode()->GetTable());
1151 return SwXParagraphEnumeration::Create(this, pUnoCursor
, CursorType::TableText
, pSttNd
, pTable
);
1154 uno::Type SAL_CALL
SwXCell::getElementType()
1156 return cppu::UnoType
<text::XTextRange
>::get();
1159 sal_Bool
SwXCell::hasElements()
1164 void SwXCell::Notify(const SfxHint
& rHint
)
1166 if(rHint
.GetId() == SfxHintId::Dying
)
1168 m_pTableFormat
= nullptr;
1170 else if(auto pFindHint
= dynamic_cast<const FindUnoInstanceHint
<SwTableBox
, SwXCell
>*>(&rHint
))
1172 if(!pFindHint
->m_pResult
&& pFindHint
->m_pCore
== GetTableBox())
1173 pFindHint
->m_pResult
= this;
1177 SwXCell
* SwXCell::CreateXCell(SwFrameFormat
* pTableFormat
, SwTableBox
* pBox
, SwTable
*pTable
)
1179 if(!pTableFormat
|| !pBox
)
1182 pTable
= SwTable::FindTable(pTableFormat
);
1183 SwTableSortBoxes::const_iterator it
= pTable
->GetTabSortBoxes().find(pBox
);
1184 if(it
== pTable
->GetTabSortBoxes().end())
1186 size_t const nPos
= it
- pTable
->GetTabSortBoxes().begin();
1187 FindUnoInstanceHint
<SwTableBox
, SwXCell
> aHint
{pBox
};
1188 pTableFormat
->GetNotifier().Broadcast(aHint
);
1189 return aHint
.m_pResult
? aHint
.m_pResult
: new SwXCell(pTableFormat
, pBox
, nPos
);
1192 /** search if a box exists in a table
1194 * @param pTable the table to search in
1195 * @param pBox2 box model to find
1196 * @return the box if existent in pTable, 0 (!!!) if not found
1198 SwTableBox
* SwXCell::FindBox(SwTable
* pTable
, SwTableBox
* pBox2
)
1200 // check if nFndPos happens to point to the right table box
1201 if( m_nFndPos
< pTable
->GetTabSortBoxes().size() &&
1202 pBox2
== pTable
->GetTabSortBoxes()[ m_nFndPos
] )
1205 // if not, seek the entry (and return, if successful)
1206 SwTableSortBoxes::const_iterator it
= pTable
->GetTabSortBoxes().find( pBox2
);
1207 if( it
!= pTable
->GetTabSortBoxes().end() )
1209 m_nFndPos
= it
- pTable
->GetTabSortBoxes().begin();
1213 // box not found: reset nFndPos pointer
1214 m_nFndPos
= NOTFOUND
;
1218 double SwXCell::GetForcedNumericalValue() const
1220 if(table::CellContentType_TEXT
!= const_cast<SwXCell
*>(this)->getType())
1222 // now we'll try to get a useful numerical value
1223 // from the text in the cell...
1225 SvNumberFormatter
* pNumFormatter(const_cast<SvNumberFormatter
*>(GetDoc()->GetNumberFormatter()));
1226 // look for SwTableBoxNumFormat value in parents as well
1227 const SfxPoolItem
* pItem
;
1228 auto pBoxFormat(GetTableBox()->GetFrameFormat());
1229 SfxItemState eState
= pBoxFormat
->GetAttrSet().GetItemState(RES_BOXATR_FORMAT
, true, &pItem
);
1231 if (eState
== SfxItemState::SET
)
1233 // please note that the language of the numberformat
1234 // is implicitly coded into the below value as well
1235 nFIndex
= static_cast<const SwTableBoxNumFormat
*>(pItem
)->GetValue();
1237 // since the current value indicates a text format but the call
1238 // to 'IsNumberFormat' below won't work for text formats
1239 // we need to get rid of the part that indicates the text format.
1240 // According to ER this can be done like this:
1241 nFIndex
-= (nFIndex
% SV_COUNTRY_LANGUAGE_OFFSET
);
1245 // system language is probably not the best possible choice
1246 // but since we have to guess anyway (because the language of at
1247 // the text is NOT the one used for the number format!)
1248 // it is at least conform to what is used in
1249 // SwTableShell::Execute when
1250 // SID_ATTR_NUMBERFORMAT_VALUE is set...
1251 LanguageType eLang
= LANGUAGE_SYSTEM
;
1252 nFIndex
= pNumFormatter
->GetStandardIndex( eLang
);
1255 if (!const_cast<SwDoc
*>(GetDoc())->IsNumberFormat(const_cast<SwXCell
*>(this)->getString(), nFIndex
, fTmp
))
1256 ::rtl::math::setNan(&fTmp
);
1260 uno::Any
SwXCell::GetAny() const
1263 throw uno::RuntimeException();
1264 // check if table box value item is set
1265 auto pBoxFormat(m_pBox
->GetFrameFormat());
1266 const bool bIsNum
= pBoxFormat
->GetItemState(RES_BOXATR_VALUE
, false) == SfxItemState::SET
;
1267 return bIsNum
? uno::makeAny(getValue()) : uno::makeAny(const_cast<SwXCell
*>(this)->getString());
1270 OUString
SwXCell::getImplementationName()
1271 { return "SwXCell"; }
1273 sal_Bool
SwXCell::supportsService(const OUString
& rServiceName
)
1274 { return cppu::supportsService(this, rServiceName
); }
1276 uno::Sequence
< OUString
> SwXCell::getSupportedServiceNames()
1277 { return {"com.sun.star.text.CellProperties"}; }
1279 OUString
SwXTextTableRow::getImplementationName()
1280 { return "SwXTextTableRow"; }
1282 sal_Bool
SwXTextTableRow::supportsService(const OUString
& rServiceName
)
1283 { return cppu::supportsService(this, rServiceName
); }
1285 uno::Sequence
< OUString
> SwXTextTableRow::getSupportedServiceNames()
1286 { return {"com.sun.star.text.TextTableRow"}; }
1289 SwXTextTableRow::SwXTextTableRow(SwFrameFormat
* pFormat
, SwTableLine
* pLn
) :
1292 m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TEXT_TABLE_ROW
))
1294 StartListening(m_pFormat
->GetNotifier());
1297 SwXTextTableRow::~SwXTextTableRow()
1299 SolarMutexGuard aGuard
;
1303 uno::Reference
< beans::XPropertySetInfo
> SwXTextTableRow::getPropertySetInfo()
1305 static uno::Reference
<beans::XPropertySetInfo
> xRef
= m_pPropSet
->getPropertySetInfo();
1309 void SwXTextTableRow::setPropertyValue(const OUString
& rPropertyName
, const uno::Any
& aValue
)
1311 SolarMutexGuard aGuard
;
1312 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
1313 SwTable
* pTable
= SwTable::FindTable( pFormat
);
1314 SwTableLine
* pLn
= SwXTextTableRow::FindLine(pTable
, pLine
);
1317 // Check for a specific property
1318 if ( rPropertyName
== "TableRedlineParams" )
1320 // Get the table row properties
1321 uno::Sequence
< beans::PropertyValue
> tableRowProperties
= aValue
.get
< uno::Sequence
< beans::PropertyValue
> >();
1322 comphelper::SequenceAsHashMap
aPropMap( tableRowProperties
);
1323 OUString sRedlineType
;
1324 if( !(aPropMap
.getValue("RedlineType") >>= sRedlineType
) )
1326 throw beans::UnknownPropertyException("No redline type property: ", static_cast < cppu::OWeakObject
* > ( this ) );
1329 // Create a 'Table Row Redline' object
1330 SwUnoCursorHelper::makeTableRowRedline( *pLn
, sRedlineType
, tableRowProperties
);
1335 const SfxItemPropertySimpleEntry
* pEntry
=
1336 m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
1337 SwDoc
* pDoc
= pFormat
->GetDoc();
1339 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
1340 if ( pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
1341 throw beans::PropertyVetoException("Property is read-only: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
1343 switch(pEntry
->nWID
)
1345 case FN_UNO_ROW_HEIGHT
:
1346 case FN_UNO_ROW_AUTO_HEIGHT
:
1348 SwFormatFrameSize
aFrameSize(pLn
->GetFrameFormat()->GetFrameSize());
1349 if(FN_UNO_ROW_AUTO_HEIGHT
== pEntry
->nWID
)
1351 bool bSet
= *o3tl::doAccess
<bool>(aValue
);
1352 aFrameSize
.SetHeightSizeType(bSet
? ATT_VAR_SIZE
: ATT_FIX_SIZE
);
1356 sal_Int32 nHeight
= 0;
1358 Size
aSz(aFrameSize
.GetSize());
1359 aSz
.setHeight( convertMm100ToTwip(nHeight
) );
1360 aFrameSize
.SetSize(aSz
);
1362 pDoc
->SetAttr(aFrameSize
, *pLn
->ClaimFrameFormat());
1366 case FN_UNO_TABLE_COLUMN_SEPARATORS
:
1368 UnoActionContext
aContext(pDoc
);
1369 SwTable
* pTable2
= SwTable::FindTable( pFormat
);
1370 lcl_SetTableSeparators(aValue
, pTable2
, pLine
->GetTabBoxes()[0], true, pDoc
);
1376 SwFrameFormat
* pLnFormat
= pLn
->ClaimFrameFormat();
1377 SwAttrSet
aSet(pLnFormat
->GetAttrSet());
1378 m_pPropSet
->setPropertyValue(*pEntry
, aValue
, aSet
);
1379 pDoc
->SetAttr(aSet
, *pLnFormat
);
1386 uno::Any
SwXTextTableRow::getPropertyValue(const OUString
& rPropertyName
)
1388 SolarMutexGuard aGuard
;
1390 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
1391 SwTable
* pTable
= SwTable::FindTable( pFormat
);
1392 SwTableLine
* pLn
= SwXTextTableRow::FindLine(pTable
, pLine
);
1395 const SfxItemPropertySimpleEntry
* pEntry
=
1396 m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
1398 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
1400 switch(pEntry
->nWID
)
1402 case FN_UNO_ROW_HEIGHT
:
1403 case FN_UNO_ROW_AUTO_HEIGHT
:
1405 const SwFormatFrameSize
& rSize
= pLn
->GetFrameFormat()->GetFrameSize();
1406 if(FN_UNO_ROW_AUTO_HEIGHT
== pEntry
->nWID
)
1408 aRet
<<= ATT_VAR_SIZE
== rSize
.GetHeightSizeType();
1411 aRet
<<= static_cast<sal_Int32
>(convertTwipToMm100(rSize
.GetSize().Height()));
1415 case FN_UNO_TABLE_COLUMN_SEPARATORS
:
1417 lcl_GetTableSeparators(aRet
, pTable
, pLine
->GetTabBoxes()[0], true);
1423 const SwAttrSet
& rSet
= pLn
->GetFrameFormat()->GetAttrSet();
1424 m_pPropSet
->getPropertyValue(*pEntry
, rSet
, aRet
);
1431 void SwXTextTableRow::addPropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1432 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1434 void SwXTextTableRow::removePropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1435 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1437 void SwXTextTableRow::addVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1438 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1440 void SwXTextTableRow::removeVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1441 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1443 void SwXTextTableRow::Notify(const SfxHint
& rHint
)
1445 if(rHint
.GetId() == SfxHintId::Dying
)
1447 m_pFormat
= nullptr;
1448 } else if(auto pFindHint
= dynamic_cast<const FindUnoInstanceHint
<SwTableLine
, SwXTextTableRow
>*>(&rHint
))
1450 if(!pFindHint
->m_pCore
&& pFindHint
->m_pCore
== pLine
)
1451 pFindHint
->m_pResult
= this;
1455 SwTableLine
* SwXTextTableRow::FindLine(SwTable
* pTable
, SwTableLine
const * pLine
)
1457 for(const auto& pCurrentLine
: pTable
->GetTabLines())
1458 if(pCurrentLine
== pLine
)
1459 return pCurrentLine
;
1463 // SwXTextTableCursor
1465 OUString
SwXTextTableCursor::getImplementationName()
1466 { return "SwXTextTableCursor"; }
1468 sal_Bool
SwXTextTableCursor::supportsService(const OUString
& rServiceName
)
1469 { return cppu::supportsService(this, rServiceName
); }
1471 void SwXTextTableCursor::acquire() throw()
1473 SwXTextTableCursor_Base::acquire();
1476 void SwXTextTableCursor::release() throw()
1478 SolarMutexGuard aGuard
;
1479 SwXTextTableCursor_Base::release();
1482 css::uno::Any SAL_CALL
1483 SwXTextTableCursor::queryInterface( const css::uno::Type
& _rType
)
1485 css::uno::Any aReturn
= SwXTextTableCursor_Base::queryInterface( _rType
);
1486 if ( !aReturn
.hasValue() )
1487 aReturn
= OTextCursorHelper::queryInterface( _rType
);
1491 const SwPaM
* SwXTextTableCursor::GetPaM() const { return &GetCursor(); }
1492 SwPaM
* SwXTextTableCursor::GetPaM() { return &GetCursor(); }
1493 const SwDoc
* SwXTextTableCursor::GetDoc() const { return GetFrameFormat()->GetDoc(); }
1494 SwDoc
* SwXTextTableCursor::GetDoc() { return GetFrameFormat()->GetDoc(); }
1495 const SwUnoCursor
& SwXTextTableCursor::GetCursor() const { return *m_pUnoCursor
; }
1496 SwUnoCursor
& SwXTextTableCursor::GetCursor() { return *m_pUnoCursor
; }
1498 uno::Sequence
<OUString
> SwXTextTableCursor::getSupportedServiceNames()
1499 { return {"com.sun.star.text.TextTableCursor"}; }
1501 SwXTextTableCursor::SwXTextTableCursor(SwFrameFormat
* pFrameFormat
, SwTableBox
const* pBox
)
1502 : m_pFrameFormat(pFrameFormat
)
1503 , m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TEXT_TABLE_CURSOR
))
1505 StartListening(m_pFrameFormat
->GetNotifier());
1506 SwDoc
* pDoc
= m_pFrameFormat
->GetDoc();
1507 const SwStartNode
* pSttNd
= pBox
->GetSttNd();
1508 SwPosition
aPos(*pSttNd
);
1509 m_pUnoCursor
= pDoc
->CreateUnoCursor(aPos
, true);
1510 m_pUnoCursor
->Move( fnMoveForward
, GoInNode
);
1511 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(*m_pUnoCursor
);
1512 rTableCursor
.MakeBoxSels();
1515 SwXTextTableCursor::SwXTextTableCursor(SwFrameFormat
& rTableFormat
, const SwTableCursor
* pTableSelection
)
1516 : m_pFrameFormat(&rTableFormat
)
1517 , m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TEXT_TABLE_CURSOR
))
1519 StartListening(m_pFrameFormat
->GetNotifier());
1520 m_pUnoCursor
= pTableSelection
->GetDoc()->CreateUnoCursor(*pTableSelection
->GetPoint(), true);
1521 if(pTableSelection
->HasMark())
1523 m_pUnoCursor
->SetMark();
1524 *m_pUnoCursor
->GetMark() = *pTableSelection
->GetMark();
1526 const SwSelBoxes
& rBoxes
= pTableSelection
->GetSelectedBoxes();
1527 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(*m_pUnoCursor
);
1528 for(auto pBox
: rBoxes
)
1529 rTableCursor
.InsertBox(*pBox
);
1530 rTableCursor
.MakeBoxSels();
1533 OUString
SwXTextTableCursor::getRangeName()
1535 SolarMutexGuard aGuard
;
1536 SwUnoCursor
& rUnoCursor
= GetCursor();
1537 SwUnoTableCursor
* pTableCursor
= dynamic_cast<SwUnoTableCursor
*>(&rUnoCursor
);
1538 //!! see also SwChartDataSequence::getSourceRangeRepresentation
1541 pTableCursor
->MakeBoxSels();
1542 const SwStartNode
* pNode
= pTableCursor
->GetPoint()->nNode
.GetNode().FindTableBoxStartNode();
1543 const SwTable
* pTable
= SwTable::FindTable(GetFrameFormat());
1544 const SwTableBox
* pEndBox
= pTable
->GetTableBox(pNode
->GetIndex());
1545 if(pTableCursor
->HasMark())
1547 pNode
= pTableCursor
->GetMark()->nNode
.GetNode().FindTableBoxStartNode();
1548 const SwTableBox
* pStartBox
= pTable
->GetTableBox(pNode
->GetIndex());
1549 if(pEndBox
!= pStartBox
)
1551 // need to switch start and end?
1552 if(*pTableCursor
->GetPoint() < *pTableCursor
->GetMark())
1553 std::swap(pStartBox
, pEndBox
);
1554 return pStartBox
->GetName() + ":" + pEndBox
->GetName();
1557 return pEndBox
->GetName();
1560 sal_Bool
SwXTextTableCursor::gotoCellByName(const OUString
& sCellName
, sal_Bool bExpand
)
1562 SolarMutexGuard aGuard
;
1563 SwUnoCursor
& rUnoCursor
= GetCursor();
1564 auto& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1565 lcl_CursorSelect(rTableCursor
, bExpand
);
1566 return rTableCursor
.GotoTableBox(sCellName
);
1569 sal_Bool
SwXTextTableCursor::goLeft(sal_Int16 Count
, sal_Bool bExpand
)
1571 SolarMutexGuard aGuard
;
1572 SwUnoCursor
& rUnoCursor
= GetCursor();
1573 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1574 lcl_CursorSelect(rTableCursor
, bExpand
);
1575 return rTableCursor
.Left(Count
);
1578 sal_Bool
SwXTextTableCursor::goRight(sal_Int16 Count
, sal_Bool bExpand
)
1580 SolarMutexGuard aGuard
;
1581 SwUnoCursor
& rUnoCursor
= GetCursor();
1582 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1583 lcl_CursorSelect(rTableCursor
, bExpand
);
1584 return rTableCursor
.Right(Count
);
1587 sal_Bool
SwXTextTableCursor::goUp(sal_Int16 Count
, sal_Bool bExpand
)
1589 SolarMutexGuard aGuard
;
1590 SwUnoCursor
& rUnoCursor
= GetCursor();
1591 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1592 lcl_CursorSelect(rTableCursor
, bExpand
);
1593 return rTableCursor
.UpDown(true, Count
, nullptr, 0,
1594 *rUnoCursor
.GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout());
1597 sal_Bool
SwXTextTableCursor::goDown(sal_Int16 Count
, sal_Bool bExpand
)
1599 SolarMutexGuard aGuard
;
1600 SwUnoCursor
& rUnoCursor
= GetCursor();
1601 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1602 lcl_CursorSelect(rTableCursor
, bExpand
);
1603 return rTableCursor
.UpDown(false, Count
, nullptr, 0,
1604 *rUnoCursor
.GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout());
1607 void SwXTextTableCursor::gotoStart(sal_Bool bExpand
)
1609 SolarMutexGuard aGuard
;
1610 SwUnoCursor
& rUnoCursor
= GetCursor();
1611 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1612 lcl_CursorSelect(rTableCursor
, bExpand
);
1613 rTableCursor
.MoveTable(GotoCurrTable
, fnTableStart
);
1616 void SwXTextTableCursor::gotoEnd(sal_Bool bExpand
)
1618 SolarMutexGuard aGuard
;
1619 SwUnoCursor
& rUnoCursor
= GetCursor();
1620 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1621 lcl_CursorSelect(rTableCursor
, bExpand
);
1622 rTableCursor
.MoveTable(GotoCurrTable
, fnTableEnd
);
1625 sal_Bool
SwXTextTableCursor::mergeRange()
1627 SolarMutexGuard aGuard
;
1628 SwUnoCursor
& rUnoCursor
= GetCursor();
1630 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1632 // HACK: remove pending actions for selecting old style tables
1633 UnoActionRemoveContext
aRemoveContext(rTableCursor
);
1635 rTableCursor
.MakeBoxSels();
1638 UnoActionContext
aContext(rUnoCursor
.GetDoc());
1639 bResult
= TableMergeErr::Ok
== rTableCursor
.GetDoc()->MergeTable(rTableCursor
);
1643 size_t nCount
= rTableCursor
.GetSelectedBoxesCount();
1645 rTableCursor
.DeleteBox(nCount
);
1647 rTableCursor
.MakeBoxSels();
1651 sal_Bool
SwXTextTableCursor::splitRange(sal_Int16 Count
, sal_Bool Horizontal
)
1653 SolarMutexGuard aGuard
;
1655 throw uno::RuntimeException("Illegal first argument: needs to be > 0", static_cast<cppu::OWeakObject
*>(this));
1656 SwUnoCursor
& rUnoCursor
= GetCursor();
1657 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1659 // HACK: remove pending actions for selecting old style tables
1660 UnoActionRemoveContext
aRemoveContext(rTableCursor
);
1662 rTableCursor
.MakeBoxSels();
1665 UnoActionContext
aContext(rUnoCursor
.GetDoc());
1666 bResult
= rTableCursor
.GetDoc()->SplitTable(rTableCursor
.GetSelectedBoxes(), !Horizontal
, Count
);
1668 rTableCursor
.MakeBoxSels();
1672 uno::Reference
< beans::XPropertySetInfo
> SwXTextTableCursor::getPropertySetInfo()
1674 static uno::Reference
< beans::XPropertySetInfo
> xRef
= m_pPropSet
->getPropertySetInfo();
1678 void SwXTextTableCursor::setPropertyValue(const OUString
& rPropertyName
, const uno::Any
& aValue
)
1680 SolarMutexGuard aGuard
;
1681 SwUnoCursor
& rUnoCursor
= GetCursor();
1682 auto pEntry(m_pPropSet
->getPropertyMap().getByName(rPropertyName
));
1684 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
1685 if(pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
1686 throw beans::PropertyVetoException("Property is read-only: " + rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
1688 auto pSttNode
= rUnoCursor
.GetNode().StartOfSectionNode();
1689 const SwTableNode
* pTableNode
= pSttNode
->FindTableNode();
1690 lcl_FormatTable(pTableNode
->GetTable().GetFrameFormat());
1692 auto& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1693 rTableCursor
.MakeBoxSels();
1694 SwDoc
* pDoc
= rUnoCursor
.GetDoc();
1695 switch(pEntry
->nWID
)
1697 case FN_UNO_TABLE_CELL_BACKGROUND
:
1699 std::shared_ptr
<SfxPoolItem
> aBrush(std::make_shared
<SvxBrushItem
>(RES_BACKGROUND
));
1700 SwDoc::GetBoxAttr(rUnoCursor
, aBrush
);
1701 aBrush
->PutValue(aValue
, pEntry
->nMemberId
);
1702 pDoc
->SetBoxAttr(rUnoCursor
, *aBrush
);
1706 case RES_BOXATR_FORMAT
:
1708 SfxUInt32Item
aNumberFormat(RES_BOXATR_FORMAT
);
1709 aNumberFormat
.PutValue(aValue
, 0);
1710 pDoc
->SetBoxAttr(rUnoCursor
, aNumberFormat
);
1713 case FN_UNO_PARA_STYLE
:
1714 SwUnoCursorHelper::SetTextFormatColl(aValue
, rUnoCursor
);
1718 SfxItemSet
aItemSet(pDoc
->GetAttrPool(), {{pEntry
->nWID
, pEntry
->nWID
}});
1719 SwUnoCursorHelper::GetCursorAttr(rTableCursor
.GetSelRing(),
1722 if (!SwUnoCursorHelper::SetCursorPropertyValue(
1723 *pEntry
, aValue
, rTableCursor
.GetSelRing(), aItemSet
))
1725 m_pPropSet
->setPropertyValue(*pEntry
, aValue
, aItemSet
);
1727 SwUnoCursorHelper::SetCursorAttr(rTableCursor
.GetSelRing(),
1728 aItemSet
, SetAttrMode::DEFAULT
, true);
1733 uno::Any
SwXTextTableCursor::getPropertyValue(const OUString
& rPropertyName
)
1735 SolarMutexGuard aGuard
;
1736 SwUnoCursor
& rUnoCursor
= GetCursor();
1738 auto pSttNode
= rUnoCursor
.GetNode().StartOfSectionNode();
1739 const SwTableNode
* pTableNode
= pSttNode
->FindTableNode();
1740 lcl_FormatTable(pTableNode
->GetTable().GetFrameFormat());
1742 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(rUnoCursor
);
1743 auto pEntry(m_pPropSet
->getPropertyMap().getByName(rPropertyName
));
1745 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
1746 rTableCursor
.MakeBoxSels();
1748 switch(pEntry
->nWID
)
1750 case FN_UNO_TABLE_CELL_BACKGROUND
:
1752 std::shared_ptr
<SfxPoolItem
> aBrush(std::make_shared
<SvxBrushItem
>(RES_BACKGROUND
));
1753 if (SwDoc::GetBoxAttr(rUnoCursor
, aBrush
))
1754 aBrush
->QueryValue(aResult
, pEntry
->nMemberId
);
1757 case RES_BOXATR_FORMAT
:
1758 // TODO: GetAttr for table selections in a Doc is missing
1759 throw uno::RuntimeException("Unknown property: " + rPropertyName
, static_cast<cppu::OWeakObject
*>(this));
1761 case FN_UNO_PARA_STYLE
:
1763 auto pFormat(SwUnoCursorHelper::GetCurTextFormatColl(rUnoCursor
, false));
1765 aResult
<<= pFormat
->GetName();
1770 SfxItemSet
aSet(rTableCursor
.GetDoc()->GetAttrPool(),
1771 svl::Items
<RES_CHRATR_BEGIN
, RES_FRMATR_END
-1,
1772 RES_UNKNOWNATR_CONTAINER
, RES_UNKNOWNATR_CONTAINER
>{});
1773 SwUnoCursorHelper::GetCursorAttr(rTableCursor
.GetSelRing(), aSet
);
1774 m_pPropSet
->getPropertyValue(*pEntry
, aSet
, aResult
);
1780 void SwXTextTableCursor::addPropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1781 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1783 void SwXTextTableCursor::removePropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
1784 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1786 void SwXTextTableCursor::addVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1787 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1789 void SwXTextTableCursor::removeVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
1790 { throw uno::RuntimeException("not implemented", static_cast<cppu::OWeakObject
*>(this)); };
1792 void SwXTextTableCursor::Notify( const SfxHint
& rHint
)
1794 if(rHint
.GetId() == SfxHintId::Dying
)
1795 m_pFrameFormat
= nullptr;
1799 // SwXTextTable ===========================================================
1801 class SwTableProperties_Impl
1803 SwUnoCursorHelper::SwAnyMapHelper aAnyMap
;
1805 SwTableProperties_Impl();
1807 void SetProperty(sal_uInt16 nWhichId
, sal_uInt16 nMemberId
, const uno::Any
& aVal
);
1808 bool GetProperty(sal_uInt16 nWhichId
, sal_uInt16 nMemberId
, const uno::Any
*& rpAny
);
1809 template<typename Tpoolitem
>
1810 inline void AddItemToSet(SfxItemSet
& rSet
, std::function
<Tpoolitem()> aItemFactory
, sal_uInt16 nWhich
, std::initializer_list
<sal_uInt16
> vMember
, bool bAddTwips
= false);
1812 void ApplyTableAttr(const SwTable
& rTable
, SwDoc
& rDoc
);
1815 SwTableProperties_Impl::SwTableProperties_Impl()
1818 void SwTableProperties_Impl::SetProperty(sal_uInt16 nWhichId
, sal_uInt16 nMemberId
, const uno::Any
& rVal
)
1819 { aAnyMap
.SetValue( nWhichId
, nMemberId
, rVal
); }
1821 bool SwTableProperties_Impl::GetProperty(sal_uInt16 nWhichId
, sal_uInt16 nMemberId
, const uno::Any
*& rpAny
)
1822 { return aAnyMap
.FillValue( nWhichId
, nMemberId
, rpAny
); }
1824 template<typename Tpoolitem
>
1825 void SwTableProperties_Impl::AddItemToSet(SfxItemSet
& rSet
, std::function
<Tpoolitem()> aItemFactory
, sal_uInt16 nWhich
, std::initializer_list
<sal_uInt16
> vMember
, bool bAddTwips
)
1827 std::vector
< std::pair
<sal_uInt16
, const uno::Any
* > > vMemberAndAny
;
1828 for(sal_uInt16 nMember
: vMember
)
1830 const uno::Any
* pAny
= nullptr;
1831 GetProperty(nWhich
, nMember
, pAny
);
1833 vMemberAndAny
.emplace_back(nMember
, pAny
);
1835 if(!vMemberAndAny
.empty())
1837 Tpoolitem aItem
= aItemFactory();
1838 for(const auto& aMemberAndAny
: vMemberAndAny
)
1839 aItem
->PutValue(*aMemberAndAny
.second
, aMemberAndAny
.first
| (bAddTwips
? CONVERT_TWIPS
: 0) );
1843 void SwTableProperties_Impl::ApplyTableAttr(const SwTable
& rTable
, SwDoc
& rDoc
)
1848 RES_FRM_SIZE
, RES_BREAK
,
1849 RES_HORI_ORIENT
, RES_HORI_ORIENT
,
1850 RES_BACKGROUND
, RES_BACKGROUND
,
1851 RES_SHADOW
, RES_SHADOW
,
1853 RES_LAYOUT_SPLIT
, RES_LAYOUT_SPLIT
>{});
1854 const uno::Any
* pRepHead
;
1855 const SwFrameFormat
&rFrameFormat
= *rTable
.GetFrameFormat();
1856 if(GetProperty(FN_TABLE_HEADLINE_REPEAT
, 0xff, pRepHead
))
1858 bool bVal(pRepHead
->get
<bool>());
1859 const_cast<SwTable
&>(rTable
).SetRowsToRepeat( bVal
? 1 : 0 ); // TODO: MULTIHEADER
1862 AddItemToSet
<std::shared_ptr
<SvxBrushItem
>>(aSet
, [&rFrameFormat
]() { return rFrameFormat
.makeBackgroundBrushItem(); }, RES_BACKGROUND
, {
1864 MID_GRAPHIC_TRANSPARENT
,
1865 MID_GRAPHIC_POSITION
,
1867 MID_GRAPHIC_FILTER
});
1869 bool bPutBreak
= true;
1870 const uno::Any
* pPage
;
1871 if(GetProperty(FN_UNO_PAGE_STYLE
, 0, pPage
) || GetProperty(RES_PAGEDESC
, 0xff, pPage
))
1873 OUString sPageStyle
= pPage
->get
<OUString
>();
1874 if(!sPageStyle
.isEmpty())
1876 SwStyleNameMapper::FillUIName(sPageStyle
, sPageStyle
, SwGetPoolIdFromName::PageDesc
);
1877 const SwPageDesc
* pDesc
= SwPageDesc::GetByName(rDoc
, sPageStyle
);
1880 SwFormatPageDesc
aDesc(pDesc
);
1881 const uno::Any
* pPgNo
;
1882 if(GetProperty(RES_PAGEDESC
, MID_PAGEDESC_PAGENUMOFFSET
, pPgNo
))
1884 aDesc
.SetNumOffset(pPgNo
->get
<sal_Int16
>());
1894 AddItemToSet
<std::shared_ptr
<SvxFormatBreakItem
>>(aSet
, [&rFrameFormat
]() { return std::shared_ptr
<SvxFormatBreakItem
>(static_cast<SvxFormatBreakItem
*>(rFrameFormat
.GetBreak().Clone())); }, RES_BREAK
, {0});
1895 AddItemToSet
<std::shared_ptr
<SvxShadowItem
>>(aSet
, [&rFrameFormat
]() { return std::shared_ptr
<SvxShadowItem
>(static_cast<SvxShadowItem
*>(rFrameFormat
.GetShadow().Clone())); }, RES_SHADOW
, {0}, true);
1896 AddItemToSet
<std::shared_ptr
<SvxFormatKeepItem
>>(aSet
, [&rFrameFormat
]() { return std::shared_ptr
<SvxFormatKeepItem
>(static_cast<SvxFormatKeepItem
*>(rFrameFormat
.GetKeep().Clone())); }, RES_KEEP
, {0});
1897 AddItemToSet
<std::shared_ptr
<SwFormatHoriOrient
>>(aSet
, [&rFrameFormat
]() { return std::shared_ptr
<SwFormatHoriOrient
>(static_cast<SwFormatHoriOrient
*>(rFrameFormat
.GetHoriOrient().Clone())); }, RES_HORI_ORIENT
, {MID_HORIORIENT_ORIENT
}, true);
1899 const uno::Any
* pSzRel(nullptr);
1900 GetProperty(FN_TABLE_IS_RELATIVE_WIDTH
, 0xff, pSzRel
);
1901 const uno::Any
* pRelWidth(nullptr);
1902 GetProperty(FN_TABLE_RELATIVE_WIDTH
, 0xff, pRelWidth
);
1903 const uno::Any
* pWidth(nullptr);
1904 GetProperty(FN_TABLE_WIDTH
, 0xff, pWidth
);
1906 bool bPutSize
= pWidth
!= nullptr;
1907 SwFormatFrameSize
aSz(ATT_VAR_SIZE
);
1910 aSz
.PutValue(*pWidth
, MID_FRMSIZE_WIDTH
);
1913 if(pSzRel
&& pSzRel
->get
<bool>() && pRelWidth
)
1915 aSz
.PutValue(*pRelWidth
, MID_FRMSIZE_REL_WIDTH
|CONVERT_TWIPS
);
1921 aSz
.SetWidth(MINLAY
);
1924 AddItemToSet
<std::shared_ptr
<SvxLRSpaceItem
>>(aSet
, [&rFrameFormat
]() { return std::shared_ptr
<SvxLRSpaceItem
>(static_cast<SvxLRSpaceItem
*>(rFrameFormat
.GetLRSpace().Clone())); }, RES_LR_SPACE
, {
1925 MID_L_MARGIN
|CONVERT_TWIPS
,
1926 MID_R_MARGIN
|CONVERT_TWIPS
});
1927 AddItemToSet
<std::shared_ptr
<SvxULSpaceItem
>>(aSet
, [&rFrameFormat
]() { return std::shared_ptr
<SvxULSpaceItem
>(static_cast<SvxULSpaceItem
*>(rFrameFormat
.GetULSpace().Clone())); }, RES_UL_SPACE
, {
1928 MID_UP_MARGIN
|CONVERT_TWIPS
,
1929 MID_LO_MARGIN
|CONVERT_TWIPS
});
1930 const::uno::Any
* pSplit(nullptr);
1931 if(GetProperty(RES_LAYOUT_SPLIT
, 0, pSplit
))
1933 SwFormatLayoutSplit
aSp(pSplit
->get
<bool>());
1938 rDoc
.SetAttr(aSet
, *rTable
.GetFrameFormat());
1942 class SwXTextTable::Impl
1943 : public SvtListener
1946 SwFrameFormat
* m_pFrameFormat
;
1947 ::osl::Mutex m_Mutex
; // just for OInterfaceContainerHelper2
1950 uno::WeakReference
<uno::XInterface
> m_wThis
;
1951 ::cppu::OMultiTypeInterfaceContainerHelper m_Listeners
;
1953 const SfxItemPropertySet
* m_pPropSet
;
1955 css::uno::WeakReference
<css::table::XTableRows
> m_xRows
;
1956 css::uno::WeakReference
<css::table::XTableColumns
> m_xColumns
;
1958 bool m_bFirstRowAsLabel
;
1959 bool m_bFirstColumnAsLabel
;
1961 // Descriptor-interface
1962 std::unique_ptr
<SwTableProperties_Impl
> m_pTableProps
;
1963 OUString m_sTableName
;
1964 unsigned short m_nRows
;
1965 unsigned short m_nColumns
;
1967 explicit Impl(SwFrameFormat
* const pFrameFormat
)
1968 : m_pFrameFormat(pFrameFormat
)
1969 , m_Listeners(m_Mutex
)
1970 , m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TEXT_TABLE
))
1971 , m_bFirstRowAsLabel(false)
1972 , m_bFirstColumnAsLabel(false)
1973 , m_pTableProps(pFrameFormat
? nullptr : new SwTableProperties_Impl
)
1974 , m_nRows(pFrameFormat
? 0 : 2)
1975 , m_nColumns(pFrameFormat
? 0 : 2)
1978 StartListening(m_pFrameFormat
->GetNotifier());
1981 SwFrameFormat
* GetFrameFormat() { return m_pFrameFormat
; }
1982 void SetFrameFormat(SwFrameFormat
& rFrameFormat
)
1985 m_pFrameFormat
= &rFrameFormat
;
1986 StartListening(m_pFrameFormat
->GetNotifier());
1989 bool IsDescriptor() { return m_pTableProps
!= nullptr; }
1991 // note: lock mutex before calling this to avoid concurrent update
1992 static std::pair
<sal_uInt16
, sal_uInt16
> ThrowIfComplex(SwXTextTable
&rThis
)
1994 sal_uInt16
const nRowCount(rThis
.m_pImpl
->GetRowCount());
1995 sal_uInt16
const nColCount(rThis
.m_pImpl
->GetColumnCount());
1996 if (!nRowCount
|| !nColCount
)
1998 throw uno::RuntimeException("Table too complex",
1999 static_cast<cppu::OWeakObject
*>(&rThis
));
2001 return std::make_pair(nRowCount
, nColCount
);
2004 sal_uInt16
GetRowCount();
2005 sal_uInt16
GetColumnCount();
2007 virtual void Notify(const SfxHint
&) override
;
2013 class theSwXTextTableUnoTunnelId
: public rtl::Static
< UnoTunnelIdInit
, theSwXTextTableUnoTunnelId
> {};
2016 const uno::Sequence
< sal_Int8
> & SwXTextTable::getUnoTunnelId()
2017 { return theSwXTextTableUnoTunnelId::get().getSeq(); }
2019 sal_Int64 SAL_CALL
SwXTextTable::getSomething( const uno::Sequence
< sal_Int8
>& rId
)
2021 if(rId
.getLength() == 16
2022 && 0 == memcmp(getUnoTunnelId().getConstArray(), rId
.getConstArray(), 16))
2024 return sal::static_int_cast
<sal_Int64
>(reinterpret_cast<sal_IntPtr
>(this));
2030 SwXTextTable::SwXTextTable()
2031 : m_pImpl(new Impl(nullptr))
2035 SwXTextTable::SwXTextTable(SwFrameFormat
& rFrameFormat
)
2036 : m_pImpl(new Impl(&rFrameFormat
))
2040 SwXTextTable::~SwXTextTable()
2044 uno::Reference
<text::XTextTable
> SwXTextTable::CreateXTextTable(SwFrameFormat
* const pFrameFormat
)
2046 uno::Reference
<text::XTextTable
> xTable
;
2048 xTable
.set(pFrameFormat
->GetXObject(), uno::UNO_QUERY
); // cached?
2051 SwXTextTable
* const pNew( pFrameFormat
? new SwXTextTable(*pFrameFormat
) : new SwXTextTable());
2054 pFrameFormat
->SetXObject(xTable
);
2055 // need a permanent Reference to initialize m_wThis
2056 pNew
->m_pImpl
->m_wThis
= xTable
;
2060 SwFrameFormat
* SwXTextTable::GetFrameFormat()
2062 return m_pImpl
->GetFrameFormat();
2065 void SwXTextTable::initialize(sal_Int32 nR
, sal_Int32 nC
)
2067 if (!m_pImpl
->IsDescriptor() || nR
<= 0 || nC
<= 0 || nR
>= SAL_MAX_UINT16
|| nC
>= SAL_MAX_UINT16
)
2068 throw uno::RuntimeException();
2069 m_pImpl
->m_nRows
= static_cast<sal_uInt16
>(nR
);
2070 m_pImpl
->m_nColumns
= static_cast<sal_uInt16
>(nC
);
2073 uno::Reference
<table::XTableRows
> SAL_CALL
SwXTextTable::getRows()
2075 SolarMutexGuard aGuard
;
2076 uno::Reference
<table::XTableRows
> xResult(m_pImpl
->m_xRows
);
2079 if(SwFrameFormat
* pFormat
= GetFrameFormat())
2080 m_pImpl
->m_xRows
= xResult
= new SwXTableRows(*pFormat
);
2082 throw uno::RuntimeException();
2086 uno::Reference
<table::XTableColumns
> SAL_CALL
SwXTextTable::getColumns()
2088 SolarMutexGuard aGuard
;
2089 uno::Reference
<table::XTableColumns
> xResult(m_pImpl
->m_xColumns
);
2092 if(SwFrameFormat
* pFormat
= GetFrameFormat())
2093 m_pImpl
->m_xColumns
= xResult
= new SwXTableColumns(*pFormat
);
2095 throw uno::RuntimeException();
2099 uno::Reference
<table::XCell
> SwXTextTable::getCellByName(const OUString
& sCellName
)
2101 SolarMutexGuard aGuard
;
2102 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
2103 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2104 SwTableBox
* pBox
= const_cast<SwTableBox
*>(pTable
->GetTableBox(sCellName
));
2107 return SwXCell::CreateXCell(pFormat
, pBox
);
2110 uno::Sequence
<OUString
> SwXTextTable::getCellNames()
2112 SolarMutexGuard aGuard
;
2113 SwFrameFormat
* pFormat(GetFrameFormat());
2116 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2117 // exists at the table and at all boxes
2118 SwTableLines
& rTableLines
= pTable
->GetTabLines();
2119 std::vector
<OUString
> aAllNames
;
2120 lcl_InspectLines(rTableLines
, aAllNames
);
2121 return comphelper::containerToSequence(aAllNames
);
2124 uno::Reference
<text::XTextTableCursor
> SwXTextTable::createCursorByCellName(const OUString
& sCellName
)
2126 SolarMutexGuard aGuard
;
2127 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
2128 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2129 SwTableBox
* pBox
= const_cast<SwTableBox
*>(pTable
->GetTableBox(sCellName
));
2130 if(!pBox
|| pBox
->getRowSpan() == 0)
2131 throw uno::RuntimeException();
2132 return new SwXTextTableCursor(pFormat
, pBox
);
2136 SwXTextTable::attach(const uno::Reference
<text::XTextRange
> & xTextRange
)
2138 SolarMutexGuard aGuard
;
2140 // attach() must only be called once
2141 if (!m_pImpl
->IsDescriptor()) /* already attached ? */
2142 throw uno::RuntimeException("SwXTextTable: already attached to range.", static_cast<cppu::OWeakObject
*>(this));
2144 uno::Reference
<XUnoTunnel
> xRangeTunnel(xTextRange
, uno::UNO_QUERY
);
2145 SwXTextRange
* pRange(nullptr);
2146 OTextCursorHelper
* pCursor(nullptr);
2147 if(xRangeTunnel
.is())
2149 pRange
= reinterpret_cast<SwXTextRange
*>(
2150 sal::static_int_cast
<sal_IntPtr
>(xRangeTunnel
->getSomething(SwXTextRange::getUnoTunnelId())));
2151 pCursor
= reinterpret_cast<OTextCursorHelper
*>(
2152 sal::static_int_cast
<sal_IntPtr
>(xRangeTunnel
->getSomething(OTextCursorHelper::getUnoTunnelId())));
2154 SwDoc
* pDoc
= pRange
? &pRange
->GetDoc() : pCursor
? pCursor
->GetDoc() : nullptr;
2155 if (!pDoc
|| !m_pImpl
->m_nRows
|| !m_pImpl
->m_nColumns
)
2156 throw lang::IllegalArgumentException();
2157 SwUnoInternalPaM
aPam(*pDoc
);
2158 // this now needs to return TRUE
2159 ::sw::XTextRangeToSwPaM(aPam
, xTextRange
);
2161 UnoActionContext
aCont(pDoc
);
2163 pDoc
->GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY
, nullptr);
2164 const SwTable
* pTable(nullptr);
2165 if( 0 != aPam
.Start()->nContent
.GetIndex() )
2167 pDoc
->getIDocumentContentOperations().SplitNode(*aPam
.Start(), false);
2169 //TODO: if it is the last paragraph than add another one!
2172 pDoc
->getIDocumentContentOperations().DeleteAndJoin(aPam
);
2175 pTable
= pDoc
->InsertTable(SwInsertTableOptions( SwInsertTableFlags::Headline
| SwInsertTableFlags::DefaultBorder
| SwInsertTableFlags::SplitLayout
, 0 ),
2178 m_pImpl
->m_nColumns
,
2179 text::HoriOrientation::FULL
);
2182 // here, the properties of the descriptor need to be analyzed
2183 m_pImpl
->m_pTableProps
->ApplyTableAttr(*pTable
, *pDoc
);
2184 SwFrameFormat
* pTableFormat(pTable
->GetFrameFormat());
2185 lcl_FormatTable(pTableFormat
);
2187 m_pImpl
->SetFrameFormat(*pTableFormat
);
2189 if (!m_pImpl
->m_sTableName
.isEmpty())
2191 sal_uInt16 nIndex
= 1;
2192 OUString
sTmpNameIndex(m_pImpl
->m_sTableName
);
2193 while(pDoc
->FindTableFormatByName(sTmpNameIndex
, true) && nIndex
< USHRT_MAX
)
2195 sTmpNameIndex
= m_pImpl
->m_sTableName
+ OUString::number(nIndex
++);
2197 pDoc
->SetTableName( *pTableFormat
, sTmpNameIndex
);
2200 const::uno::Any
* pName
;
2201 if (m_pImpl
->m_pTableProps
->GetProperty(FN_UNO_TABLE_NAME
, 0, pName
))
2202 setName(pName
->get
<OUString
>());
2203 m_pImpl
->m_pTableProps
.reset();
2205 pDoc
->GetIDocumentUndoRedo().EndUndo( SwUndoId::END
, nullptr );
2209 uno::Reference
<text::XTextRange
> SwXTextTable::getAnchor()
2211 SolarMutexGuard aGuard
;
2212 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
2213 return new SwXTextRange(*pFormat
);
2216 void SwXTextTable::dispose()
2218 SolarMutexGuard aGuard
;
2219 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
2220 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2221 SwSelBoxes aSelBoxes
;
2222 for(auto& rBox
: pTable
->GetTabSortBoxes() )
2223 aSelBoxes
.insert(rBox
);
2224 pFormat
->GetDoc()->DeleteRowCol(aSelBoxes
);
2227 void SAL_CALL
SwXTextTable::addEventListener(
2228 const uno::Reference
<lang::XEventListener
> & xListener
)
2230 // no need to lock here as m_pImpl is const and container threadsafe
2231 m_pImpl
->m_Listeners
.addInterface(
2232 cppu::UnoType
<lang::XEventListener
>::get(), xListener
);
2235 void SAL_CALL
SwXTextTable::removeEventListener(
2236 const uno::Reference
< lang::XEventListener
> & xListener
)
2238 // no need to lock here as m_pImpl is const and container threadsafe
2239 m_pImpl
->m_Listeners
.removeInterface(
2240 cppu::UnoType
<lang::XEventListener
>::get(), xListener
);
2243 uno::Reference
<table::XCell
> SwXTextTable::getCellByPosition(sal_Int32 nColumn
, sal_Int32 nRow
)
2245 SolarMutexGuard aGuard
;
2246 SwFrameFormat
* pFormat(GetFrameFormat());
2247 // sheet is unimportant
2248 if(nColumn
>= 0 && nRow
>= 0 && pFormat
)
2250 auto pXCell
= lcl_CreateXCell(pFormat
, nColumn
, nRow
);
2254 throw lang::IndexOutOfBoundsException();
2259 uno::Reference
<table::XCellRange
> GetRangeByName(
2260 SwFrameFormat
* pFormat
, SwTable
const * pTable
,
2261 const OUString
& rTLName
, const OUString
& rBRName
,
2262 SwRangeDescriptor
const & rDesc
)
2264 const SwTableBox
* pTLBox
= pTable
->GetTableBox(rTLName
);
2267 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
2268 SwPosition
aPos(*pSttNd
);
2269 // set cursor to the upper-left cell of the range
2270 auto pUnoCursor(pFormat
->GetDoc()->CreateUnoCursor(aPos
, true));
2271 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
2272 pUnoCursor
->SetRemainInSection(false);
2273 const SwTableBox
* pBRBox(pTable
->GetTableBox(rBRName
));
2276 pUnoCursor
->SetMark();
2277 pUnoCursor
->GetPoint()->nNode
= *pBRBox
->GetSttNd();
2278 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
2279 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
2280 // HACK: remove pending actions for selecting old style tables
2281 UnoActionRemoveContext
aRemoveContext(rCursor
);
2282 rCursor
.MakeBoxSels();
2283 // pUnoCursor will be provided and will not be deleted
2284 return SwXCellRange::CreateXCellRange(pUnoCursor
, *pFormat
, rDesc
).get();
2289 uno::Reference
<table::XCellRange
> SwXTextTable::getCellRangeByPosition(sal_Int32 nLeft
, sal_Int32 nTop
, sal_Int32 nRight
, sal_Int32 nBottom
)
2291 SolarMutexGuard aGuard
;
2292 SwFrameFormat
* pFormat(GetFrameFormat());
2294 nLeft
<= nRight
&& nTop
<= nBottom
&&
2295 nLeft
>= 0 && nRight
>= 0 && nTop
>= 0 && nBottom
>= 0 )
2297 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2298 if(!pTable
->IsTableComplex())
2300 SwRangeDescriptor aDesc
;
2302 aDesc
.nBottom
= nBottom
;
2303 aDesc
.nLeft
= nLeft
;
2304 aDesc
.nRight
= nRight
;
2305 const OUString sTLName
= sw_GetCellName(aDesc
.nLeft
, aDesc
.nTop
);
2306 const OUString sBRName
= sw_GetCellName(aDesc
.nRight
, aDesc
.nBottom
);
2307 // please note that according to the 'if' statement at the begin
2308 // sTLName:sBRName already denotes the normalized range string
2309 return GetRangeByName(pFormat
, pTable
, sTLName
, sBRName
, aDesc
);
2312 throw lang::IndexOutOfBoundsException();
2315 uno::Reference
<table::XCellRange
> SwXTextTable::getCellRangeByName(const OUString
& sRange
)
2317 SolarMutexGuard aGuard
;
2318 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
2319 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFormat
), static_cast<cppu::OWeakObject
*>(this));
2321 const OUString
sTLName(sRange
.getToken(0, ':', nPos
));
2322 const OUString
sBRName(sRange
.getToken(0, ':', nPos
));
2323 if(sTLName
.isEmpty() || sBRName
.isEmpty())
2324 throw uno::RuntimeException();
2325 SwRangeDescriptor aDesc
;
2326 aDesc
.nTop
= aDesc
.nLeft
= aDesc
.nBottom
= aDesc
.nRight
= -1;
2327 SwXTextTable::GetCellPosition(sTLName
, aDesc
.nLeft
, aDesc
.nTop
);
2328 SwXTextTable::GetCellPosition(sBRName
, aDesc
.nRight
, aDesc
.nBottom
);
2330 // we should normalize the range now (e.g. A5:C1 will become A1:C5)
2331 // since (depending on what is done later) it will be troublesome
2332 // elsewhere when the cursor in the implementation does not
2333 // point to the top-left and bottom-right cells
2335 return GetRangeByName(pFormat
, pTable
, sTLName
, sBRName
, aDesc
);
2338 uno::Sequence
< uno::Sequence
< uno::Any
> > SAL_CALL
SwXTextTable::getDataArray()
2340 SolarMutexGuard aGuard
;
2341 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2342 uno::Reference
<sheet::XCellRangeData
> const xAllRange(
2343 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2344 uno::UNO_QUERY_THROW
);
2345 return xAllRange
->getDataArray();
2348 void SAL_CALL
SwXTextTable::setDataArray(const uno::Sequence
< uno::Sequence
< uno::Any
> >& rArray
)
2350 SolarMutexGuard aGuard
;
2351 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2352 uno::Reference
<sheet::XCellRangeData
> const xAllRange(
2353 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2354 uno::UNO_QUERY_THROW
);
2355 return xAllRange
->setDataArray(rArray
);
2358 uno::Sequence
< uno::Sequence
< double > > SwXTextTable::getData()
2360 SolarMutexGuard aGuard
;
2361 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2362 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2363 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2364 uno::UNO_QUERY_THROW
);
2365 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2366 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2367 return xAllRange
->getData();
2370 void SwXTextTable::setData(const uno::Sequence
< uno::Sequence
< double > >& rData
)
2372 SolarMutexGuard aGuard
;
2373 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2374 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2375 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2376 uno::UNO_QUERY_THROW
);
2377 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2378 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2379 xAllRange
->setData(rData
);
2380 // this is rather inconsistent: setData on XTextTable sends events, but e.g. CellRanges do not
2381 lcl_SendChartEvent(*this, m_pImpl
->m_Listeners
);
2384 uno::Sequence
<OUString
> SwXTextTable::getRowDescriptions()
2386 SolarMutexGuard aGuard
;
2387 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2388 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2389 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2390 uno::UNO_QUERY_THROW
);
2391 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2392 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2393 return xAllRange
->getRowDescriptions();
2396 void SwXTextTable::setRowDescriptions(const uno::Sequence
<OUString
>& rRowDesc
)
2398 SolarMutexGuard aGuard
;
2399 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2400 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2401 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2402 uno::UNO_QUERY_THROW
);
2403 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2404 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2405 xAllRange
->setRowDescriptions(rRowDesc
);
2408 uno::Sequence
<OUString
> SwXTextTable::getColumnDescriptions()
2410 SolarMutexGuard aGuard
;
2411 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2412 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2413 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2414 uno::UNO_QUERY_THROW
);
2415 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2416 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2417 return xAllRange
->getColumnDescriptions();
2420 void SwXTextTable::setColumnDescriptions(const uno::Sequence
<OUString
>& rColumnDesc
)
2422 SolarMutexGuard aGuard
;
2423 std::pair
<sal_uInt16
, sal_uInt16
> const RowsAndColumns(SwXTextTable::Impl::ThrowIfComplex(*this));
2424 uno::Reference
<chart::XChartDataArray
> const xAllRange(
2425 getCellRangeByPosition(0, 0, RowsAndColumns
.second
-1, RowsAndColumns
.first
-1),
2426 uno::UNO_QUERY_THROW
);
2427 static_cast<SwXCellRange
*>(xAllRange
.get())->SetLabels(
2428 m_pImpl
->m_bFirstRowAsLabel
, m_pImpl
->m_bFirstColumnAsLabel
);
2429 return xAllRange
->setColumnDescriptions(rColumnDesc
);
2432 void SAL_CALL
SwXTextTable::addChartDataChangeEventListener(
2433 const uno::Reference
<chart::XChartDataChangeEventListener
> & xListener
)
2435 // no need to lock here as m_pImpl is const and container threadsafe
2436 m_pImpl
->m_Listeners
.addInterface(
2437 cppu::UnoType
<chart::XChartDataChangeEventListener
>::get(), xListener
);
2440 void SAL_CALL
SwXTextTable::removeChartDataChangeEventListener(
2441 const uno::Reference
<chart::XChartDataChangeEventListener
> & xListener
)
2443 // no need to lock here as m_pImpl is const and container threadsafe
2444 m_pImpl
->m_Listeners
.removeInterface(
2445 cppu::UnoType
<chart::XChartDataChangeEventListener
>::get(), xListener
);
2448 sal_Bool
SwXTextTable::isNotANumber(double nNumber
)
2450 // We use DBL_MIN because starcalc does (which uses it because chart
2451 // wants it that way!)
2452 return ( nNumber
== DBL_MIN
);
2455 double SwXTextTable::getNotANumber()
2457 // We use DBL_MIN because starcalc does (which uses it because chart
2458 // wants it that way!)
2462 uno::Sequence
< beans::PropertyValue
> SwXTextTable::createSortDescriptor()
2464 SolarMutexGuard aGuard
;
2466 return SwUnoCursorHelper::CreateSortDescriptor(true);
2469 void SwXTextTable::sort(const uno::Sequence
< beans::PropertyValue
>& rDescriptor
)
2471 SolarMutexGuard aGuard
;
2472 SwSortOptions aSortOpt
;
2473 SwFrameFormat
* pFormat
= GetFrameFormat();
2475 SwUnoCursorHelper::ConvertSortProperties(rDescriptor
, aSortOpt
))
2477 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2479 const SwTableSortBoxes
& rTBoxes
= pTable
->GetTabSortBoxes();
2480 for (size_t n
= 0; n
< rTBoxes
.size(); ++n
)
2482 SwTableBox
* pBox
= rTBoxes
[ n
];
2483 aBoxes
.insert( pBox
);
2485 UnoActionContext
aContext( pFormat
->GetDoc() );
2486 pFormat
->GetDoc()->SortTable(aBoxes
, aSortOpt
);
2490 void SwXTextTable::autoFormat(const OUString
& sAutoFormatName
)
2492 SolarMutexGuard aGuard
;
2493 SwFrameFormat
* pFormat
= lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
2494 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFormat
), static_cast<cppu::OWeakObject
*>(this));
2495 SwTableAutoFormatTable aAutoFormatTable
;
2496 aAutoFormatTable
.Load();
2497 for (size_t i
= aAutoFormatTable
.size(); i
;)
2498 if( sAutoFormatName
== aAutoFormatTable
[ --i
].GetName() )
2501 const SwTableSortBoxes
& rTBoxes
= pTable
->GetTabSortBoxes();
2502 for (size_t n
= 0; n
< rTBoxes
.size(); ++n
)
2504 SwTableBox
* pBox
= rTBoxes
[ n
];
2505 aBoxes
.insert( pBox
);
2507 UnoActionContext
aContext( pFormat
->GetDoc() );
2508 pFormat
->GetDoc()->SetTableAutoFormat( aBoxes
, aAutoFormatTable
[i
] );
2513 uno::Reference
< beans::XPropertySetInfo
> SwXTextTable::getPropertySetInfo()
2515 static uno::Reference
<beans::XPropertySetInfo
> xRef
= m_pImpl
->m_pPropSet
->getPropertySetInfo();
2519 void SwXTextTable::setPropertyValue(const OUString
& rPropertyName
, const uno::Any
& aValue
)
2521 SolarMutexGuard aGuard
;
2522 SwFrameFormat
* pFormat
= GetFrameFormat();
2523 if(!aValue
.hasValue())
2524 throw lang::IllegalArgumentException();
2525 const SfxItemPropertySimpleEntry
* pEntry
=
2526 m_pImpl
->m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
2528 throw lang::IllegalArgumentException();
2531 if ( pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
2532 throw beans::PropertyVetoException("Property is read-only: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
2534 if(0xBF == pEntry
->nMemberId
)
2536 lcl_SetSpecialProperty(pFormat
, pEntry
, aValue
);
2540 switch(pEntry
->nWID
)
2542 case FN_UNO_TABLE_NAME
:
2550 case FN_UNO_RANGE_ROW_LABEL
:
2552 bool bTmp
= *o3tl::doAccess
<bool>(aValue
);
2553 if (m_pImpl
->m_bFirstRowAsLabel
!= bTmp
)
2555 lcl_SendChartEvent(*this, m_pImpl
->m_Listeners
);
2556 m_pImpl
->m_bFirstRowAsLabel
= bTmp
;
2561 case FN_UNO_RANGE_COL_LABEL
:
2563 bool bTmp
= *o3tl::doAccess
<bool>(aValue
);
2564 if (m_pImpl
->m_bFirstColumnAsLabel
!= bTmp
)
2566 lcl_SendChartEvent(*this, m_pImpl
->m_Listeners
);
2567 m_pImpl
->m_bFirstColumnAsLabel
= bTmp
;
2572 case FN_UNO_TABLE_BORDER
:
2573 case FN_UNO_TABLE_BORDER2
:
2575 table::TableBorder oldBorder
;
2576 table::TableBorder2 aBorder
;
2577 SvxBorderLine aTopLine
;
2578 SvxBorderLine aBottomLine
;
2579 SvxBorderLine aLeftLine
;
2580 SvxBorderLine aRightLine
;
2581 SvxBorderLine aHoriLine
;
2582 SvxBorderLine aVertLine
;
2583 if (aValue
>>= oldBorder
)
2585 aBorder
.IsTopLineValid
= oldBorder
.IsTopLineValid
;
2586 aBorder
.IsBottomLineValid
= oldBorder
.IsBottomLineValid
;
2587 aBorder
.IsLeftLineValid
= oldBorder
.IsLeftLineValid
;
2588 aBorder
.IsRightLineValid
= oldBorder
.IsRightLineValid
;
2589 aBorder
.IsHorizontalLineValid
= oldBorder
.IsHorizontalLineValid
;
2590 aBorder
.IsVerticalLineValid
= oldBorder
.IsVerticalLineValid
;
2591 aBorder
.Distance
= oldBorder
.Distance
;
2592 aBorder
.IsDistanceValid
= oldBorder
.IsDistanceValid
;
2594 oldBorder
.TopLine
, aTopLine
);
2596 oldBorder
.BottomLine
, aBottomLine
);
2598 oldBorder
.LeftLine
, aLeftLine
);
2600 oldBorder
.RightLine
, aRightLine
);
2602 oldBorder
.HorizontalLine
, aHoriLine
);
2604 oldBorder
.VerticalLine
, aVertLine
);
2606 else if (aValue
>>= aBorder
)
2608 SvxBoxItem::LineToSvxLine(
2609 aBorder
.TopLine
, aTopLine
, true);
2610 SvxBoxItem::LineToSvxLine(
2611 aBorder
.BottomLine
, aBottomLine
, true);
2612 SvxBoxItem::LineToSvxLine(
2613 aBorder
.LeftLine
, aLeftLine
, true);
2614 SvxBoxItem::LineToSvxLine(
2615 aBorder
.RightLine
, aRightLine
, true);
2616 SvxBoxItem::LineToSvxLine(
2617 aBorder
.HorizontalLine
, aHoriLine
, true);
2618 SvxBoxItem::LineToSvxLine(
2619 aBorder
.VerticalLine
, aVertLine
, true);
2623 break; // something else
2625 SwDoc
* pDoc
= pFormat
->GetDoc();
2626 if(!lcl_FormatTable(pFormat
))
2628 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2629 SwTableLines
&rLines
= pTable
->GetTabLines();
2631 const SwTableBox
* pTLBox
= lcl_FindCornerTableBox(rLines
, true);
2632 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
2633 SwPosition
aPos(*pSttNd
);
2634 // set cursor to top left cell
2635 auto pUnoCursor(pDoc
->CreateUnoCursor(aPos
, true));
2636 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
2637 pUnoCursor
->SetRemainInSection( false );
2639 const SwTableBox
* pBRBox
= lcl_FindCornerTableBox(rLines
, false);
2640 pUnoCursor
->SetMark();
2641 pUnoCursor
->GetPoint()->nNode
= *pBRBox
->GetSttNd();
2642 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
2643 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
2644 // HACK: remove pending actions for selecting old style tables
2645 UnoActionRemoveContext
aRemoveContext(rCursor
);
2646 rCursor
.MakeBoxSels();
2648 SfxItemSet
aSet(pDoc
->GetAttrPool(),
2649 svl::Items
<RES_BOX
, RES_BOX
,
2650 SID_ATTR_BORDER_INNER
, SID_ATTR_BORDER_INNER
>{});
2652 SvxBoxItem
aBox( RES_BOX
);
2653 SvxBoxInfoItem
aBoxInfo( SID_ATTR_BORDER_INNER
);
2655 aBox
.SetLine(aTopLine
.isEmpty() ? nullptr : &aTopLine
, SvxBoxItemLine::TOP
);
2656 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::TOP
, aBorder
.IsTopLineValid
);
2658 aBox
.SetLine(aBottomLine
.isEmpty() ? nullptr : &aBottomLine
, SvxBoxItemLine::BOTTOM
);
2659 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::BOTTOM
, aBorder
.IsBottomLineValid
);
2661 aBox
.SetLine(aLeftLine
.isEmpty() ? nullptr : &aLeftLine
, SvxBoxItemLine::LEFT
);
2662 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::LEFT
, aBorder
.IsLeftLineValid
);
2664 aBox
.SetLine(aRightLine
.isEmpty() ? nullptr : &aRightLine
, SvxBoxItemLine::RIGHT
);
2665 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::RIGHT
, aBorder
.IsRightLineValid
);
2667 aBoxInfo
.SetLine(aHoriLine
.isEmpty() ? nullptr : &aHoriLine
, SvxBoxInfoItemLine::HORI
);
2668 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::HORI
, aBorder
.IsHorizontalLineValid
);
2670 aBoxInfo
.SetLine(aVertLine
.isEmpty() ? nullptr : &aVertLine
, SvxBoxInfoItemLine::VERT
);
2671 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::VERT
, aBorder
.IsVerticalLineValid
);
2673 aBox
.SetAllDistances(static_cast<sal_uInt16
>(convertMm100ToTwip(aBorder
.Distance
)));
2674 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::DISTANCE
, aBorder
.IsDistanceValid
);
2679 pDoc
->SetTabBorders(rCursor
, aSet
);
2683 case FN_UNO_TABLE_BORDER_DISTANCES
:
2685 table::TableBorderDistances aTableBorderDistances
;
2686 if( !(aValue
>>= aTableBorderDistances
) ||
2687 (!aTableBorderDistances
.IsLeftDistanceValid
&&
2688 !aTableBorderDistances
.IsRightDistanceValid
&&
2689 !aTableBorderDistances
.IsTopDistanceValid
&&
2690 !aTableBorderDistances
.IsBottomDistanceValid
))
2693 const sal_uInt16 nLeftDistance
= convertMm100ToTwip(aTableBorderDistances
.LeftDistance
);
2694 const sal_uInt16 nRightDistance
= convertMm100ToTwip(aTableBorderDistances
.RightDistance
);
2695 const sal_uInt16 nTopDistance
= convertMm100ToTwip(aTableBorderDistances
.TopDistance
);
2696 const sal_uInt16 nBottomDistance
= convertMm100ToTwip(aTableBorderDistances
.BottomDistance
);
2697 SwDoc
* pDoc
= pFormat
->GetDoc();
2698 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2699 SwTableLines
&rLines
= pTable
->GetTabLines();
2700 pDoc
->GetIDocumentUndoRedo().StartUndo(SwUndoId::START
, nullptr);
2701 for(size_t i
= 0; i
< rLines
.size(); ++i
)
2703 SwTableLine
* pLine
= rLines
[i
];
2704 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
2705 for(size_t k
= 0; k
< rBoxes
.size(); ++k
)
2707 SwTableBox
* pBox
= rBoxes
[k
];
2708 const SwFrameFormat
* pBoxFormat
= pBox
->GetFrameFormat();
2709 const SvxBoxItem
& rBox
= pBoxFormat
->GetBox();
2711 (aTableBorderDistances
.IsLeftDistanceValid
&& nLeftDistance
!= rBox
.GetDistance( SvxBoxItemLine::LEFT
)) ||
2712 (aTableBorderDistances
.IsRightDistanceValid
&& nRightDistance
!= rBox
.GetDistance( SvxBoxItemLine::RIGHT
)) ||
2713 (aTableBorderDistances
.IsTopDistanceValid
&& nTopDistance
!= rBox
.GetDistance( SvxBoxItemLine::TOP
)) ||
2714 (aTableBorderDistances
.IsBottomDistanceValid
&& nBottomDistance
!= rBox
.GetDistance( SvxBoxItemLine::BOTTOM
)))
2716 SvxBoxItem
aSetBox( rBox
);
2717 SwFrameFormat
* pSetBoxFormat
= pBox
->ClaimFrameFormat();
2718 if( aTableBorderDistances
.IsLeftDistanceValid
)
2719 aSetBox
.SetDistance( nLeftDistance
, SvxBoxItemLine::LEFT
);
2720 if( aTableBorderDistances
.IsRightDistanceValid
)
2721 aSetBox
.SetDistance( nRightDistance
, SvxBoxItemLine::RIGHT
);
2722 if( aTableBorderDistances
.IsTopDistanceValid
)
2723 aSetBox
.SetDistance( nTopDistance
, SvxBoxItemLine::TOP
);
2724 if( aTableBorderDistances
.IsBottomDistanceValid
)
2725 aSetBox
.SetDistance( nBottomDistance
, SvxBoxItemLine::BOTTOM
);
2726 pDoc
->SetAttr( aSetBox
, *pSetBoxFormat
);
2730 pDoc
->GetIDocumentUndoRedo().EndUndo(SwUndoId::END
, nullptr);
2734 case FN_UNO_TABLE_COLUMN_SEPARATORS
:
2736 UnoActionContext
aContext(pFormat
->GetDoc());
2737 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2738 lcl_SetTableSeparators(aValue
, pTable
, pTable
->GetTabLines()[0]->GetTabBoxes()[0], false, pFormat
->GetDoc());
2742 case FN_UNO_TABLE_COLUMN_RELATIVE_SUM
:/*_readonly_*/ break;
2744 case FN_UNO_TABLE_TEMPLATE_NAME
:
2746 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2748 if (!(aValue
>>= sName
))
2750 pTable
->SetTableStyleName(sName
);
2751 SwDoc
* pDoc
= pFormat
->GetDoc();
2752 pDoc
->GetDocShell()->GetFEShell()->UpdateTableStyleFormatting(pTable
->GetTableNode());
2758 SwAttrSet
aSet(pFormat
->GetAttrSet());
2759 m_pImpl
->m_pPropSet
->setPropertyValue(*pEntry
, aValue
, aSet
);
2760 pFormat
->GetDoc()->SetAttr(aSet
, *pFormat
);
2765 else if (m_pImpl
->IsDescriptor())
2767 m_pImpl
->m_pTableProps
->SetProperty(pEntry
->nWID
, pEntry
->nMemberId
, aValue
);
2770 throw uno::RuntimeException();
2773 uno::Any
SwXTextTable::getPropertyValue(const OUString
& rPropertyName
)
2775 SolarMutexGuard aGuard
;
2777 SwFrameFormat
* pFormat
= GetFrameFormat();
2778 const SfxItemPropertySimpleEntry
* pEntry
=
2779 m_pImpl
->m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
2782 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
2786 if(0xBF == pEntry
->nMemberId
)
2788 aRet
= lcl_GetSpecialProperty(pFormat
, pEntry
);
2792 switch(pEntry
->nWID
)
2794 case FN_UNO_TABLE_NAME
:
2800 case FN_UNO_ANCHOR_TYPES
:
2801 case FN_UNO_TEXT_WRAP
:
2802 case FN_UNO_ANCHOR_TYPE
:
2803 ::sw::GetDefaultTextContentValue(
2804 aRet
, OUString(), pEntry
->nWID
);
2807 case FN_UNO_RANGE_ROW_LABEL
:
2809 aRet
<<= m_pImpl
->m_bFirstRowAsLabel
;
2813 case FN_UNO_RANGE_COL_LABEL
:
2814 aRet
<<= m_pImpl
->m_bFirstColumnAsLabel
;
2817 case FN_UNO_TABLE_BORDER
:
2818 case FN_UNO_TABLE_BORDER2
:
2820 SwDoc
* pDoc
= pFormat
->GetDoc();
2821 // tables without layout (invisible header/footer?)
2822 if(!lcl_FormatTable(pFormat
))
2824 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2825 SwTableLines
&rLines
= pTable
->GetTabLines();
2827 const SwTableBox
* pTLBox
= lcl_FindCornerTableBox(rLines
, true);
2828 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
2829 SwPosition
aPos(*pSttNd
);
2830 // set cursor to top left cell
2831 auto pUnoCursor(pDoc
->CreateUnoCursor(aPos
, true));
2832 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
2833 pUnoCursor
->SetRemainInSection( false );
2835 const SwTableBox
* pBRBox
= lcl_FindCornerTableBox(rLines
, false);
2836 pUnoCursor
->SetMark();
2837 const SwStartNode
* pLastNd
= pBRBox
->GetSttNd();
2838 pUnoCursor
->GetPoint()->nNode
= *pLastNd
;
2840 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
2841 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
2842 // HACK: remove pending actions for selecting old style tables
2843 UnoActionRemoveContext
aRemoveContext(rCursor
);
2844 rCursor
.MakeBoxSels();
2846 SfxItemSet
aSet(pDoc
->GetAttrPool(),
2847 svl::Items
<RES_BOX
, RES_BOX
,
2848 SID_ATTR_BORDER_INNER
, SID_ATTR_BORDER_INNER
>{});
2849 aSet
.Put(SvxBoxInfoItem( SID_ATTR_BORDER_INNER
));
2850 SwDoc::GetTabBorders(rCursor
, aSet
);
2851 const SvxBoxInfoItem
& rBoxInfoItem
= aSet
.Get(SID_ATTR_BORDER_INNER
);
2852 const SvxBoxItem
& rBox
= aSet
.Get(RES_BOX
);
2854 if (FN_UNO_TABLE_BORDER
== pEntry
->nWID
)
2856 table::TableBorder aTableBorder
;
2857 aTableBorder
.TopLine
= SvxBoxItem::SvxLineToLine(rBox
.GetTop(), true);
2858 aTableBorder
.IsTopLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::TOP
);
2859 aTableBorder
.BottomLine
= SvxBoxItem::SvxLineToLine(rBox
.GetBottom(), true);
2860 aTableBorder
.IsBottomLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::BOTTOM
);
2861 aTableBorder
.LeftLine
= SvxBoxItem::SvxLineToLine(rBox
.GetLeft(), true);
2862 aTableBorder
.IsLeftLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::LEFT
);
2863 aTableBorder
.RightLine
= SvxBoxItem::SvxLineToLine(rBox
.GetRight(), true);
2864 aTableBorder
.IsRightLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::RIGHT
);
2865 aTableBorder
.HorizontalLine
= SvxBoxItem::SvxLineToLine(rBoxInfoItem
.GetHori(), true);
2866 aTableBorder
.IsHorizontalLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::HORI
);
2867 aTableBorder
.VerticalLine
= SvxBoxItem::SvxLineToLine(rBoxInfoItem
.GetVert(), true);
2868 aTableBorder
.IsVerticalLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::VERT
);
2869 aTableBorder
.Distance
= convertTwipToMm100(rBox
.GetSmallestDistance());
2870 aTableBorder
.IsDistanceValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::DISTANCE
);
2871 aRet
<<= aTableBorder
;
2875 table::TableBorder2 aTableBorder
;
2876 aTableBorder
.TopLine
= SvxBoxItem::SvxLineToLine(rBox
.GetTop(), true);
2877 aTableBorder
.IsTopLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::TOP
);
2878 aTableBorder
.BottomLine
= SvxBoxItem::SvxLineToLine(rBox
.GetBottom(), true);
2879 aTableBorder
.IsBottomLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::BOTTOM
);
2880 aTableBorder
.LeftLine
= SvxBoxItem::SvxLineToLine(rBox
.GetLeft(), true);
2881 aTableBorder
.IsLeftLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::LEFT
);
2882 aTableBorder
.RightLine
= SvxBoxItem::SvxLineToLine(rBox
.GetRight(), true);
2883 aTableBorder
.IsRightLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::RIGHT
);
2884 aTableBorder
.HorizontalLine
= SvxBoxItem::SvxLineToLine(rBoxInfoItem
.GetHori(), true);
2885 aTableBorder
.IsHorizontalLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::HORI
);
2886 aTableBorder
.VerticalLine
= SvxBoxItem::SvxLineToLine(rBoxInfoItem
.GetVert(), true);
2887 aTableBorder
.IsVerticalLineValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::VERT
);
2888 aTableBorder
.Distance
= convertTwipToMm100(rBox
.GetSmallestDistance());
2889 aTableBorder
.IsDistanceValid
= rBoxInfoItem
.IsValid(SvxBoxInfoItemValidFlags::DISTANCE
);
2890 aRet
<<= aTableBorder
;
2895 case FN_UNO_TABLE_BORDER_DISTANCES
:
2897 table::TableBorderDistances
aTableBorderDistances( 0, true, 0, true, 0, true, 0, true ) ;
2898 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2899 const SwTableLines
&rLines
= pTable
->GetTabLines();
2901 sal_uInt16 nLeftDistance
= 0;
2902 sal_uInt16 nRightDistance
= 0;
2903 sal_uInt16 nTopDistance
= 0;
2904 sal_uInt16 nBottomDistance
= 0;
2906 for(size_t i
= 0; i
< rLines
.size(); ++i
)
2908 const SwTableLine
* pLine
= rLines
[i
];
2909 const SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
2910 for(size_t k
= 0; k
< rBoxes
.size(); ++k
)
2912 const SwTableBox
* pBox
= rBoxes
[k
];
2913 SwFrameFormat
* pBoxFormat
= pBox
->GetFrameFormat();
2914 const SvxBoxItem
& rBox
= pBoxFormat
->GetBox();
2917 nLeftDistance
= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::LEFT
));
2918 nRightDistance
= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::RIGHT
));
2919 nTopDistance
= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::TOP
));
2920 nBottomDistance
= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::BOTTOM
));
2925 if( aTableBorderDistances
.IsLeftDistanceValid
&&
2926 nLeftDistance
!= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::LEFT
)))
2927 aTableBorderDistances
.IsLeftDistanceValid
= false;
2928 if( aTableBorderDistances
.IsRightDistanceValid
&&
2929 nRightDistance
!= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::RIGHT
)))
2930 aTableBorderDistances
.IsRightDistanceValid
= false;
2931 if( aTableBorderDistances
.IsTopDistanceValid
&&
2932 nTopDistance
!= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::TOP
)))
2933 aTableBorderDistances
.IsTopDistanceValid
= false;
2934 if( aTableBorderDistances
.IsBottomDistanceValid
&&
2935 nBottomDistance
!= convertTwipToMm100( rBox
.GetDistance( SvxBoxItemLine::BOTTOM
)))
2936 aTableBorderDistances
.IsBottomDistanceValid
= false;
2940 if( !aTableBorderDistances
.IsLeftDistanceValid
&&
2941 !aTableBorderDistances
.IsRightDistanceValid
&&
2942 !aTableBorderDistances
.IsTopDistanceValid
&&
2943 !aTableBorderDistances
.IsBottomDistanceValid
)
2946 if( aTableBorderDistances
.IsLeftDistanceValid
)
2947 aTableBorderDistances
.LeftDistance
= nLeftDistance
;
2948 if( aTableBorderDistances
.IsRightDistanceValid
)
2949 aTableBorderDistances
.RightDistance
= nRightDistance
;
2950 if( aTableBorderDistances
.IsTopDistanceValid
)
2951 aTableBorderDistances
.TopDistance
= nTopDistance
;
2952 if( aTableBorderDistances
.IsBottomDistanceValid
)
2953 aTableBorderDistances
.BottomDistance
= nBottomDistance
;
2955 aRet
<<= aTableBorderDistances
;
2959 case FN_UNO_TABLE_COLUMN_SEPARATORS
:
2961 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2962 lcl_GetTableSeparators(aRet
, pTable
, pTable
->GetTabLines()[0]->GetTabBoxes()[0], false);
2966 case FN_UNO_TABLE_COLUMN_RELATIVE_SUM
:
2967 aRet
<<= sal_Int16(UNO_TABLE_COLUMN_SUM
);
2971 // AnchorType is readonly and might be void (no return value)
2974 case FN_UNO_TEXT_SECTION
:
2976 SwTable
* pTable
= SwTable::FindTable( pFormat
);
2977 SwTableNode
* pTableNode
= pTable
->GetTableNode();
2978 SwSectionNode
* pSectionNode
= pTableNode
->FindSectionNode();
2981 SwSection
& rSect
= pSectionNode
->GetSection();
2982 uno::Reference
< text::XTextSection
> xSect
=
2983 SwXTextSections::GetObject( *rSect
.GetFormat() );
2989 case FN_UNO_TABLE_TEMPLATE_NAME
:
2991 SwTable
* pTable
= SwTable::FindTable(pFormat
);
2992 aRet
<<= pTable
->GetTableStyleName();
2998 const SwAttrSet
& rSet
= pFormat
->GetAttrSet();
2999 m_pImpl
->m_pPropSet
->getPropertyValue(*pEntry
, rSet
, aRet
);
3004 else if (m_pImpl
->IsDescriptor())
3006 const uno::Any
* pAny
= nullptr;
3007 if (!m_pImpl
->m_pTableProps
->GetProperty(pEntry
->nWID
, pEntry
->nMemberId
, pAny
))
3008 throw lang::IllegalArgumentException();
3013 throw uno::RuntimeException();
3017 void SwXTextTable::addPropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
3018 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3020 void SwXTextTable::removePropertyChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*xListener*/)
3021 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3023 void SwXTextTable::addVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
3024 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3026 void SwXTextTable::removeVetoableChangeListener(const OUString
& /*rPropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*xListener*/)
3027 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3029 OUString
SwXTextTable::getName()
3031 SolarMutexGuard aGuard
;
3032 SwFrameFormat
* pFormat
= GetFrameFormat();
3033 if (!pFormat
&& !m_pImpl
->IsDescriptor())
3034 throw uno::RuntimeException();
3037 return pFormat
->GetName();
3039 return m_pImpl
->m_sTableName
;
3042 void SwXTextTable::setName(const OUString
& rName
)
3044 SolarMutexGuard aGuard
;
3045 SwFrameFormat
* pFormat
= GetFrameFormat();
3046 if ((!pFormat
&& !m_pImpl
->IsDescriptor()) ||
3048 rName
.indexOf('.')>=0 ||
3049 rName
.indexOf(' ')>=0 )
3050 throw uno::RuntimeException();
3054 const OUString
aOldName( pFormat
->GetName() );
3055 const SwFrameFormats
* pFrameFormats
= pFormat
->GetDoc()->GetTableFrameFormats();
3056 for (size_t i
= pFrameFormats
->size(); i
;)
3058 const SwFrameFormat
* pTmpFormat
= (*pFrameFormats
)[--i
];
3059 if( !pTmpFormat
->IsDefault() &&
3060 pTmpFormat
->GetName() == rName
&&
3061 pFormat
->GetDoc()->IsUsed( *pTmpFormat
))
3063 throw uno::RuntimeException();
3067 pFormat
->SetName( rName
);
3070 SwNodeIndex
aIdx( *pFormat
->GetDoc()->GetNodes().GetEndOfAutotext().StartOfSectionNode(), 1 );
3071 while ( nullptr != (pStNd
= aIdx
.GetNode().GetStartNode()) )
3074 SwNode
*const pNd
= & aIdx
.GetNode();
3075 if ( pNd
->IsOLENode() &&
3076 aOldName
== static_cast<const SwOLENode
*>(pNd
)->GetChartTableName() )
3078 static_cast<SwOLENode
*>(pNd
)->SetChartTableName( rName
);
3080 SwTable
* pTable
= SwTable::FindTable( pFormat
);
3081 //TL_CHART2: chart needs to be notfied about name changes
3082 pFormat
->GetDoc()->UpdateCharts( pTable
->GetFrameFormat()->GetName() );
3084 aIdx
.Assign( *pStNd
->EndOfSectionNode(), + 1 );
3086 pFormat
->GetDoc()->getIDocumentState().SetModified();
3089 m_pImpl
->m_sTableName
= rName
;
3092 sal_uInt16
SwXTextTable::Impl::GetRowCount()
3094 sal_uInt16 nRet
= 0;
3095 SwFrameFormat
* pFormat
= GetFrameFormat();
3098 SwTable
* pTable
= SwTable::FindTable( pFormat
);
3099 if(!pTable
->IsTableComplex())
3101 nRet
= pTable
->GetTabLines().size();
3107 sal_uInt16
SwXTextTable::Impl::GetColumnCount()
3109 SwFrameFormat
* pFormat
= GetFrameFormat();
3110 sal_uInt16 nRet
= 0;
3113 SwTable
* pTable
= SwTable::FindTable( pFormat
);
3114 if(!pTable
->IsTableComplex())
3116 SwTableLines
& rLines
= pTable
->GetTabLines();
3117 SwTableLine
* pLine
= rLines
.front();
3118 nRet
= pLine
->GetTabBoxes().size();
3124 void SwXTextTable::Impl::Notify(const SfxHint
& rHint
)
3126 if(rHint
.GetId() == SfxHintId::Dying
)
3128 m_pFrameFormat
= nullptr;
3131 uno::Reference
<uno::XInterface
> const xThis(m_wThis
);
3133 { // fdo#72695: if UNO object is already dead, don't revive it with event
3136 lang::EventObject
const ev(xThis
);
3137 m_Listeners
.disposeAndClear(ev
);
3141 lcl_SendChartEvent(xThis
.get(), m_Listeners
);
3146 OUString SAL_CALL
SwXTextTable::getImplementationName()
3147 { return "SwXTextTable"; }
3149 sal_Bool
SwXTextTable::supportsService(const OUString
& rServiceName
)
3150 { return cppu::supportsService(this, rServiceName
); }
3152 uno::Sequence
<OUString
> SwXTextTable::getSupportedServiceNames()
3155 "com.sun.star.document.LinkTarget",
3156 "com.sun.star.text.TextTable",
3157 "com.sun.star.text.TextContent",
3158 "com.sun.star.text.TextSortable" };
3162 class SwXCellRange::Impl
3163 : public SvtListener
3166 ::osl::Mutex m_Mutex
; // just for OInterfaceContainerHelper2
3167 SwFrameFormat
* m_pFrameFormat
;
3170 uno::WeakReference
<uno::XInterface
> m_wThis
;
3171 ::comphelper::OInterfaceContainerHelper2 m_ChartListeners
;
3173 sw::UnoCursorPointer m_pTableCursor
;
3175 SwRangeDescriptor m_RangeDescriptor
;
3176 const SfxItemPropertySet
* m_pPropSet
;
3178 bool m_bFirstRowAsLabel
;
3179 bool m_bFirstColumnAsLabel
;
3181 Impl(sw::UnoCursorPointer
const& pCursor
, SwFrameFormat
& rFrameFormat
, SwRangeDescriptor
const& rDesc
)
3182 : m_pFrameFormat(&rFrameFormat
)
3183 , m_ChartListeners(m_Mutex
)
3184 , m_pTableCursor(pCursor
)
3185 , m_RangeDescriptor(rDesc
)
3186 , m_pPropSet(aSwMapProvider
.GetPropertySet(PROPERTY_MAP_TABLE_RANGE
))
3187 , m_bFirstRowAsLabel(false)
3188 , m_bFirstColumnAsLabel(false)
3190 StartListening(rFrameFormat
.GetNotifier());
3191 m_RangeDescriptor
.Normalize();
3194 SwFrameFormat
* GetFrameFormat()
3196 return m_pFrameFormat
;
3199 std::tuple
<sal_uInt32
, sal_uInt32
, sal_uInt32
, sal_uInt32
> GetLabelCoordinates(bool bRow
);
3201 uno::Sequence
<OUString
> GetLabelDescriptions(SwXCellRange
& rThis
, bool bRow
);
3203 void SetLabelDescriptions(SwXCellRange
& rThis
,
3204 const css::uno::Sequence
<OUString
>& rDesc
, bool bRow
);
3206 sal_Int32
GetRowCount();
3207 sal_Int32
GetColumnCount();
3209 virtual void Notify(const SfxHint
& ) override
;
3215 class theSwXCellRangeUnoTunnelId
: public rtl::Static
< UnoTunnelIdInit
, theSwXCellRangeUnoTunnelId
> {};
3218 const uno::Sequence
< sal_Int8
> & SwXCellRange::getUnoTunnelId()
3220 return theSwXCellRangeUnoTunnelId::get().getSeq();
3223 sal_Int64 SAL_CALL
SwXCellRange::getSomething( const uno::Sequence
< sal_Int8
>& rId
)
3225 if( rId
.getLength() == 16
3226 && 0 == memcmp( getUnoTunnelId().getConstArray(),
3227 rId
.getConstArray(), 16 ) )
3229 return sal::static_int_cast
< sal_Int64
>( reinterpret_cast< sal_IntPtr
>(this) );
3235 OUString
SwXCellRange::getImplementationName()
3236 { return "SwXCellRange"; }
3238 sal_Bool
SwXCellRange::supportsService(const OUString
& rServiceName
)
3239 { return cppu::supportsService(this, rServiceName
); }
3241 uno::Sequence
<OUString
> SwXCellRange::getSupportedServiceNames()
3244 "com.sun.star.text.CellRange",
3245 "com.sun.star.style.CharacterProperties",
3246 "com.sun.star.style.CharacterPropertiesAsian",
3247 "com.sun.star.style.CharacterPropertiesComplex",
3248 "com.sun.star.style.ParagraphProperties",
3249 "com.sun.star.style.ParagraphPropertiesAsian",
3250 "com.sun.star.style.ParagraphPropertiesComplex" };
3253 SwXCellRange::SwXCellRange(sw::UnoCursorPointer
const& pCursor
,
3254 SwFrameFormat
& rFrameFormat
, SwRangeDescriptor
const & rDesc
)
3255 : m_pImpl(new Impl(pCursor
, rFrameFormat
, rDesc
))
3259 SwXCellRange::~SwXCellRange()
3263 rtl::Reference
<SwXCellRange
> SwXCellRange::CreateXCellRange(
3264 sw::UnoCursorPointer
const& pCursor
, SwFrameFormat
& rFrameFormat
,
3265 SwRangeDescriptor
const & rDesc
)
3267 SwXCellRange
*const pCellRange(new SwXCellRange(pCursor
, rFrameFormat
, rDesc
));
3268 uno::Reference
<table::XCellRange
> xCellRange(pCellRange
);
3269 // need a permanent Reference to initialize m_wThis
3270 pCellRange
->m_pImpl
->m_wThis
= xCellRange
;
3274 void SwXCellRange::SetLabels(bool bFirstRowAsLabel
, bool bFirstColumnAsLabel
)
3276 m_pImpl
->m_bFirstRowAsLabel
= bFirstRowAsLabel
;
3277 m_pImpl
->m_bFirstColumnAsLabel
= bFirstColumnAsLabel
;
3280 std::vector
< uno::Reference
< table::XCell
> > SwXCellRange::GetCells()
3282 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3283 const sal_Int32
nRowCount(m_pImpl
->GetRowCount());
3284 const sal_Int32
nColCount(m_pImpl
->GetColumnCount());
3285 std::vector
< uno::Reference
< table::XCell
> > vResult
;
3286 vResult
.reserve(static_cast<size_t>(nRowCount
)*static_cast<size_t>(nColCount
));
3287 for(sal_Int32 nRow
= 0; nRow
< nRowCount
; ++nRow
)
3288 for(sal_Int32 nCol
= 0; nCol
< nColCount
; ++nCol
)
3289 vResult
.emplace_back(lcl_CreateXCell(pFormat
, m_pImpl
->m_RangeDescriptor
.nLeft
+ nCol
, m_pImpl
->m_RangeDescriptor
.nTop
+ nRow
));
3293 uno::Reference
<table::XCell
> SAL_CALL
3294 SwXCellRange::getCellByPosition(sal_Int32 nColumn
, sal_Int32 nRow
)
3296 SolarMutexGuard aGuard
;
3297 uno::Reference
< table::XCell
> aRet
;
3298 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3301 if(nColumn
>= 0 && nRow
>= 0 &&
3302 m_pImpl
->GetColumnCount() > nColumn
&& m_pImpl
->GetRowCount() > nRow
)
3304 SwXCell
* pXCell
= lcl_CreateXCell(pFormat
,
3305 m_pImpl
->m_RangeDescriptor
.nLeft
+ nColumn
,
3306 m_pImpl
->m_RangeDescriptor
.nTop
+ nRow
);
3312 throw lang::IndexOutOfBoundsException();
3316 uno::Reference
<table::XCellRange
> SAL_CALL
3317 SwXCellRange::getCellRangeByPosition(
3318 sal_Int32 nLeft
, sal_Int32 nTop
, sal_Int32 nRight
, sal_Int32 nBottom
)
3320 SolarMutexGuard aGuard
;
3321 uno::Reference
< table::XCellRange
> aRet
;
3322 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3323 if (pFormat
&& m_pImpl
->GetColumnCount() > nRight
3324 && m_pImpl
->GetRowCount() > nBottom
&&
3325 nLeft
<= nRight
&& nTop
<= nBottom
3326 && nLeft
>= 0 && nRight
>= 0 && nTop
>= 0 && nBottom
>= 0 )
3328 SwTable
* pTable
= SwTable::FindTable( pFormat
);
3329 if(!pTable
->IsTableComplex())
3331 SwRangeDescriptor aNewDesc
;
3332 aNewDesc
.nTop
= nTop
+ m_pImpl
->m_RangeDescriptor
.nTop
;
3333 aNewDesc
.nBottom
= nBottom
+ m_pImpl
->m_RangeDescriptor
.nTop
;
3334 aNewDesc
.nLeft
= nLeft
+ m_pImpl
->m_RangeDescriptor
.nLeft
;
3335 aNewDesc
.nRight
= nRight
+ m_pImpl
->m_RangeDescriptor
.nLeft
;
3336 aNewDesc
.Normalize();
3337 const OUString sTLName
= sw_GetCellName(aNewDesc
.nLeft
, aNewDesc
.nTop
);
3338 const OUString sBRName
= sw_GetCellName(aNewDesc
.nRight
, aNewDesc
.nBottom
);
3339 const SwTableBox
* pTLBox
= pTable
->GetTableBox( sTLName
);
3342 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
3343 SwPosition
aPos(*pSttNd
);
3344 // set cursor in the upper-left cell of the range
3345 auto pUnoCursor(pFormat
->GetDoc()->CreateUnoCursor(aPos
, true));
3346 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
3347 pUnoCursor
->SetRemainInSection( false );
3348 const SwTableBox
* pBRBox
= pTable
->GetTableBox( sBRName
);
3351 pUnoCursor
->SetMark();
3352 pUnoCursor
->GetPoint()->nNode
= *pBRBox
->GetSttNd();
3353 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
3354 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
3355 // HACK: remove pending actions for selecting old style tables
3356 UnoActionRemoveContext
aRemoveContext(rCursor
);
3357 rCursor
.MakeBoxSels();
3358 // pUnoCursor will be provided and will not be deleted
3359 aRet
= SwXCellRange::CreateXCellRange(pUnoCursor
, *pFormat
, aNewDesc
).get();
3365 throw lang::IndexOutOfBoundsException();
3369 uno::Reference
<table::XCellRange
> SAL_CALL
3370 SwXCellRange::getCellRangeByName(const OUString
& rRange
)
3372 SolarMutexGuard aGuard
;
3374 const OUString
sTLName(rRange
.getToken(0, ':', nPos
));
3375 const OUString
sBRName(rRange
.getToken(0, ':', nPos
));
3376 if(sTLName
.isEmpty() || sBRName
.isEmpty())
3377 throw uno::RuntimeException();
3378 SwRangeDescriptor aDesc
;
3379 aDesc
.nTop
= aDesc
.nLeft
= aDesc
.nBottom
= aDesc
.nRight
= -1;
3380 SwXTextTable::GetCellPosition( sTLName
, aDesc
.nLeft
, aDesc
.nTop
);
3381 SwXTextTable::GetCellPosition( sBRName
, aDesc
.nRight
, aDesc
.nBottom
);
3383 return getCellRangeByPosition(
3384 aDesc
.nLeft
- m_pImpl
->m_RangeDescriptor
.nLeft
,
3385 aDesc
.nTop
- m_pImpl
->m_RangeDescriptor
.nTop
,
3386 aDesc
.nRight
- m_pImpl
->m_RangeDescriptor
.nLeft
,
3387 aDesc
.nBottom
- m_pImpl
->m_RangeDescriptor
.nTop
);
3390 uno::Reference
< beans::XPropertySetInfo
> SwXCellRange::getPropertySetInfo()
3392 static uno::Reference
<beans::XPropertySetInfo
> xRef
= m_pImpl
->m_pPropSet
->getPropertySetInfo();
3397 SwXCellRange::setPropertyValue(const OUString
& rPropertyName
, const uno::Any
& aValue
)
3399 SolarMutexGuard aGuard
;
3400 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3403 const SfxItemPropertySimpleEntry
*const pEntry
=
3404 m_pImpl
->m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
3406 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
3408 if ( pEntry
->nFlags
& beans::PropertyAttribute::READONLY
)
3409 throw beans::PropertyVetoException("Property is read-only: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
3411 SwDoc
*const pDoc
= m_pImpl
->m_pTableCursor
->GetDoc();
3412 SwUnoTableCursor
& rCursor(dynamic_cast<SwUnoTableCursor
&>(*m_pImpl
->m_pTableCursor
));
3414 // HACK: remove pending actions for selecting old style tables
3415 UnoActionRemoveContext
aRemoveContext(rCursor
);
3417 rCursor
.MakeBoxSels();
3418 switch(pEntry
->nWID
)
3420 case FN_UNO_TABLE_CELL_BACKGROUND
:
3422 std::shared_ptr
<SfxPoolItem
> aBrush(std::make_shared
<SvxBrushItem
>(RES_BACKGROUND
));
3423 SwDoc::GetBoxAttr(*m_pImpl
->m_pTableCursor
, aBrush
);
3424 aBrush
->PutValue(aValue
, pEntry
->nMemberId
);
3425 pDoc
->SetBoxAttr(*m_pImpl
->m_pTableCursor
, *aBrush
);
3431 SfxItemSet
aSet(pDoc
->GetAttrPool(),
3432 svl::Items
<RES_BOX
, RES_BOX
,
3433 SID_ATTR_BORDER_INNER
, SID_ATTR_BORDER_INNER
>{});
3434 SvxBoxInfoItem
aBoxInfo( SID_ATTR_BORDER_INNER
);
3435 aBoxInfo
.SetValid(SvxBoxInfoItemValidFlags::ALL
, false);
3436 SvxBoxInfoItemValidFlags nValid
= SvxBoxInfoItemValidFlags::NONE
;
3437 switch(pEntry
->nMemberId
& ~CONVERT_TWIPS
)
3439 case LEFT_BORDER
: nValid
= SvxBoxInfoItemValidFlags::LEFT
; break;
3440 case RIGHT_BORDER
: nValid
= SvxBoxInfoItemValidFlags::RIGHT
; break;
3441 case TOP_BORDER
: nValid
= SvxBoxInfoItemValidFlags::TOP
; break;
3442 case BOTTOM_BORDER
: nValid
= SvxBoxInfoItemValidFlags::BOTTOM
; break;
3443 case LEFT_BORDER_DISTANCE
:
3444 case RIGHT_BORDER_DISTANCE
:
3445 case TOP_BORDER_DISTANCE
:
3446 case BOTTOM_BORDER_DISTANCE
:
3447 nValid
= SvxBoxInfoItemValidFlags::DISTANCE
;
3450 aBoxInfo
.SetValid(nValid
);
3453 SwDoc::GetTabBorders(rCursor
, aSet
);
3456 SvxBoxItem
aBoxItem(aSet
.Get(RES_BOX
));
3457 static_cast<SfxPoolItem
&>(aBoxItem
).PutValue(aValue
, pEntry
->nMemberId
);
3459 pDoc
->SetTabBorders(*m_pImpl
->m_pTableCursor
, aSet
);
3462 case RES_BOXATR_FORMAT
:
3464 SfxUInt32Item
aNumberFormat(RES_BOXATR_FORMAT
);
3465 static_cast<SfxPoolItem
&>(aNumberFormat
).PutValue(aValue
, 0);
3466 pDoc
->SetBoxAttr(rCursor
, aNumberFormat
);
3469 case FN_UNO_RANGE_ROW_LABEL
:
3471 bool bTmp
= *o3tl::doAccess
<bool>(aValue
);
3472 if (m_pImpl
->m_bFirstRowAsLabel
!= bTmp
)
3474 lcl_SendChartEvent(*this, m_pImpl
->m_ChartListeners
);
3475 m_pImpl
->m_bFirstRowAsLabel
= bTmp
;
3479 case FN_UNO_RANGE_COL_LABEL
:
3481 bool bTmp
= *o3tl::doAccess
<bool>(aValue
);
3482 if (m_pImpl
->m_bFirstColumnAsLabel
!= bTmp
)
3484 lcl_SendChartEvent(*this, m_pImpl
->m_ChartListeners
);
3485 m_pImpl
->m_bFirstColumnAsLabel
= bTmp
;
3489 case RES_VERT_ORIENT
:
3491 sal_Int16 nAlign
= -1;
3493 if( nAlign
>= text::VertOrientation::NONE
&& nAlign
<= text::VertOrientation::BOTTOM
)
3494 pDoc
->SetBoxAlign( rCursor
, nAlign
);
3499 SfxItemSet
aItemSet( pDoc
->GetAttrPool(), {{pEntry
->nWID
, pEntry
->nWID
}} );
3500 SwUnoCursorHelper::GetCursorAttr(rCursor
.GetSelRing(),
3503 if (!SwUnoCursorHelper::SetCursorPropertyValue(
3504 *pEntry
, aValue
, rCursor
.GetSelRing(), aItemSet
))
3506 m_pImpl
->m_pPropSet
->setPropertyValue(*pEntry
, aValue
, aItemSet
);
3508 SwUnoCursorHelper::SetCursorAttr(rCursor
.GetSelRing(),
3509 aItemSet
, SetAttrMode::DEFAULT
, true);
3516 uno::Any SAL_CALL
SwXCellRange::getPropertyValue(const OUString
& rPropertyName
)
3518 SolarMutexGuard aGuard
;
3520 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3523 const SfxItemPropertySimpleEntry
*const pEntry
=
3524 m_pImpl
->m_pPropSet
->getPropertyMap().getByName(rPropertyName
);
3526 throw beans::UnknownPropertyException("Unknown property: " + rPropertyName
, static_cast < cppu::OWeakObject
* > ( this ) );
3528 switch(pEntry
->nWID
)
3530 case FN_UNO_TABLE_CELL_BACKGROUND
:
3532 std::shared_ptr
<SfxPoolItem
> aBrush(std::make_shared
<SvxBrushItem
>(RES_BACKGROUND
));
3533 if (SwDoc::GetBoxAttr(*m_pImpl
->m_pTableCursor
, aBrush
))
3534 aBrush
->QueryValue(aRet
, pEntry
->nMemberId
);
3540 SwDoc
*const pDoc
= m_pImpl
->m_pTableCursor
->GetDoc();
3541 SfxItemSet
aSet(pDoc
->GetAttrPool(),
3542 svl::Items
<RES_BOX
, RES_BOX
,
3543 SID_ATTR_BORDER_INNER
, SID_ATTR_BORDER_INNER
>{});
3544 aSet
.Put(SvxBoxInfoItem( SID_ATTR_BORDER_INNER
));
3545 SwDoc::GetTabBorders(*m_pImpl
->m_pTableCursor
, aSet
);
3546 const SvxBoxItem
& rBoxItem
= aSet
.Get(RES_BOX
);
3547 rBoxItem
.QueryValue(aRet
, pEntry
->nMemberId
);
3550 case RES_BOXATR_FORMAT
:
3551 OSL_FAIL("not implemented");
3553 case FN_UNO_PARA_STYLE
:
3555 SwFormatColl
*const pTmpFormat
=
3556 SwUnoCursorHelper::GetCurTextFormatColl(*m_pImpl
->m_pTableCursor
, false);
3559 sRet
= pTmpFormat
->GetName();
3563 case FN_UNO_RANGE_ROW_LABEL
:
3564 aRet
<<= m_pImpl
->m_bFirstRowAsLabel
;
3566 case FN_UNO_RANGE_COL_LABEL
:
3567 aRet
<<= m_pImpl
->m_bFirstColumnAsLabel
;
3569 case RES_VERT_ORIENT
:
3571 std::shared_ptr
<SfxPoolItem
> aVertOrient
;
3572 if (SwDoc::GetBoxAttr(*m_pImpl
->m_pTableCursor
, aVertOrient
))
3574 aVertOrient
->QueryValue( aRet
, pEntry
->nMemberId
);
3581 m_pImpl
->m_pTableCursor
->GetDoc()->GetAttrPool(),
3583 RES_CHRATR_BEGIN
, RES_FRMATR_END
- 1,
3584 RES_UNKNOWNATR_CONTAINER
,
3585 RES_UNKNOWNATR_CONTAINER
>{});
3586 // first look at the attributes of the cursor
3587 SwUnoTableCursor
*const pCursor
=
3588 dynamic_cast<SwUnoTableCursor
*>(&(*m_pImpl
->m_pTableCursor
));
3589 SwUnoCursorHelper::GetCursorAttr(pCursor
->GetSelRing(), aSet
);
3590 m_pImpl
->m_pPropSet
->getPropertyValue(*pEntry
, aSet
, aRet
);
3598 void SwXCellRange::addPropertyChangeListener(const OUString
& /*PropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*aListener*/)
3599 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3601 void SwXCellRange::removePropertyChangeListener(const OUString
& /*PropertyName*/, const uno::Reference
< beans::XPropertyChangeListener
> & /*aListener*/)
3602 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3604 void SwXCellRange::addVetoableChangeListener(const OUString
& /*PropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*aListener*/)
3605 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3607 void SwXCellRange::removeVetoableChangeListener(const OUString
& /*PropertyName*/, const uno::Reference
< beans::XVetoableChangeListener
> & /*aListener*/)
3608 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3610 ///@see SwXCellRange::getData
3611 uno::Sequence
<uno::Sequence
<uno::Any
>> SAL_CALL
SwXCellRange::getDataArray()
3613 SolarMutexGuard aGuard
;
3614 const sal_Int32 nRowCount
= m_pImpl
->GetRowCount();
3615 const sal_Int32 nColCount
= m_pImpl
->GetColumnCount();
3616 if(!nRowCount
|| !nColCount
)
3617 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3618 lcl_EnsureCoreConnected(m_pImpl
->GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
3619 uno::Sequence
< uno::Sequence
< uno::Any
> > aRowSeq(nRowCount
);
3620 auto vCells(GetCells());
3621 auto pCurrentCell(vCells
.begin());
3622 for(auto& rRow
: aRowSeq
)
3624 rRow
= uno::Sequence
< uno::Any
>(nColCount
);
3625 for(auto& rCellAny
: rRow
)
3627 auto pCell(static_cast<SwXCell
*>(pCurrentCell
->get()));
3629 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3630 rCellAny
= pCell
->GetAny();
3637 ///@see SwXCellRange::setData
3638 void SAL_CALL
SwXCellRange::setDataArray(const uno::Sequence
< uno::Sequence
< uno::Any
> >& rArray
)
3640 SolarMutexGuard aGuard
;
3641 const sal_Int32 nRowCount
= m_pImpl
->GetRowCount();
3642 const sal_Int32 nColCount
= m_pImpl
->GetColumnCount();
3643 if(!nRowCount
|| !nColCount
)
3644 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3645 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3648 if(rArray
.getLength() != nRowCount
)
3649 throw uno::RuntimeException("Row count mismatch. expected: " + OUString::number(nRowCount
) + " got: " + OUString::number(rArray
.getLength()), static_cast<cppu::OWeakObject
*>(this));
3650 auto vCells(GetCells());
3651 auto pCurrentCell(vCells
.begin());
3652 for(const auto& rColSeq
: rArray
)
3654 if(rColSeq
.getLength() != nColCount
)
3655 throw uno::RuntimeException("Column count mismatch. expected: " + OUString::number(nColCount
) + " got: " + OUString::number(rColSeq
.getLength()), static_cast<cppu::OWeakObject
*>(this));
3656 for(const auto& aValue
: rColSeq
)
3658 auto pCell(static_cast<SwXCell
*>(pCurrentCell
->get()));
3659 if(!pCell
|| !pCell
->GetTableBox())
3660 throw uno::RuntimeException("Box for cell missing", static_cast<cppu::OWeakObject
*>(this));
3661 if(aValue
.isExtractableTo(cppu::UnoType
<OUString
>::get()))
3662 sw_setString(*pCell
, aValue
.get
<OUString
>());
3663 else if(aValue
.isExtractableTo(cppu::UnoType
<double>::get()))
3664 sw_setValue(*pCell
, aValue
.get
<double>());
3666 sw_setString(*pCell
, OUString(), true);
3672 uno::Sequence
<uno::Sequence
<double>> SAL_CALL
3673 SwXCellRange::getData()
3675 SolarMutexGuard aGuard
;
3676 const sal_Int32 nRowCount
= m_pImpl
->GetRowCount();
3677 const sal_Int32 nColCount
= m_pImpl
->GetColumnCount();
3678 if(!nRowCount
|| !nColCount
)
3679 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3680 if (m_pImpl
->m_bFirstColumnAsLabel
|| m_pImpl
->m_bFirstRowAsLabel
)
3682 uno::Reference
<chart::XChartDataArray
> const xDataRange(
3683 getCellRangeByPosition((m_pImpl
->m_bFirstColumnAsLabel
) ? 1 : 0,
3684 (m_pImpl
->m_bFirstRowAsLabel
) ? 1 : 0,
3685 nColCount
-1, nRowCount
-1), uno::UNO_QUERY_THROW
);
3686 return xDataRange
->getData();
3688 uno::Sequence
< uno::Sequence
< double > > vRows(nRowCount
);
3689 auto vCells(GetCells());
3690 auto pCurrentCell(vCells
.begin());
3691 for(auto& rRow
: vRows
)
3693 rRow
= uno::Sequence
<double>(nColCount
);
3694 for(auto& rValue
: rRow
)
3696 if(!(*pCurrentCell
))
3697 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3698 rValue
= (*pCurrentCell
)->getValue();
3706 SwXCellRange::setData(const uno::Sequence
< uno::Sequence
<double> >& rData
)
3708 SolarMutexGuard aGuard
;
3709 const sal_Int32 nRowCount
= m_pImpl
->GetRowCount();
3710 const sal_Int32 nColCount
= m_pImpl
->GetColumnCount();
3711 if(!nRowCount
|| !nColCount
)
3712 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(this));
3713 if (m_pImpl
->m_bFirstColumnAsLabel
|| m_pImpl
->m_bFirstRowAsLabel
)
3715 uno::Reference
<chart::XChartDataArray
> const xDataRange(
3716 getCellRangeByPosition((m_pImpl
->m_bFirstColumnAsLabel
) ? 1 : 0,
3717 (m_pImpl
->m_bFirstRowAsLabel
) ? 1 : 0,
3718 nColCount
-1, nRowCount
-1), uno::UNO_QUERY_THROW
);
3719 return xDataRange
->setData(rData
);
3721 lcl_EnsureCoreConnected(m_pImpl
->GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
3722 if(rData
.getLength() != nRowCount
)
3723 throw uno::RuntimeException("Row count mismatch. expected: " + OUString::number(nRowCount
) + " got: " + OUString::number(rData
.getLength()), static_cast<cppu::OWeakObject
*>(this));
3724 auto vCells(GetCells());
3725 auto pCurrentCell(vCells
.begin());
3726 for(const auto& rRow
: rData
)
3728 if(rRow
.getLength() != nColCount
)
3729 throw uno::RuntimeException("Column count mismatch. expected: " + OUString::number(nColCount
) + " got: " + OUString::number(rRow
.getLength()), static_cast<cppu::OWeakObject
*>(this));
3730 for(const auto& rValue
: rRow
)
3732 uno::Reference
<table::XCell
>(*pCurrentCell
, uno::UNO_SET_THROW
)->setValue(rValue
);
3738 std::tuple
<sal_uInt32
, sal_uInt32
, sal_uInt32
, sal_uInt32
>
3739 SwXCellRange::Impl::GetLabelCoordinates(bool bRow
)
3741 sal_uInt32 nLeft
, nTop
, nRight
, nBottom
;
3742 nLeft
= nTop
= nRight
= nBottom
= 0;
3745 nTop
= m_bFirstRowAsLabel
? 1 : 0;
3746 nBottom
= GetRowCount() - 1;
3750 nLeft
= m_bFirstColumnAsLabel
? 1 : 0;
3751 nRight
= GetColumnCount() - 1;
3753 return std::make_tuple(nLeft
, nTop
, nRight
, nBottom
);
3756 uno::Sequence
<OUString
>
3757 SwXCellRange::Impl::GetLabelDescriptions(SwXCellRange
& rThis
, bool bRow
)
3759 SolarMutexGuard aGuard
;
3760 sal_uInt32 nLeft
, nTop
, nRight
, nBottom
;
3761 std::tie(nLeft
, nTop
, nRight
, nBottom
) = GetLabelCoordinates(bRow
);
3762 if(!nRight
&& !nBottom
)
3763 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(&rThis
));
3764 lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(&rThis
));
3765 if (!(bRow
? m_bFirstColumnAsLabel
: m_bFirstRowAsLabel
))
3766 return {}; // without labels we have no descriptions
3767 auto xLabelRange(rThis
.getCellRangeByPosition(nLeft
, nTop
, nRight
, nBottom
));
3768 auto vCells(static_cast<SwXCellRange
*>(xLabelRange
.get())->GetCells());
3769 uno::Sequence
<OUString
> vResult(vCells
.size());
3770 std::transform(vCells
.begin(), vCells
.end(), vResult
.begin(),
3771 [](uno::Reference
<table::XCell
> xCell
) -> OUString
{ return uno::Reference
<text::XText
>(xCell
, uno::UNO_QUERY_THROW
)->getString(); });
3775 uno::Sequence
<OUString
> SAL_CALL
SwXCellRange::getRowDescriptions()
3777 return m_pImpl
->GetLabelDescriptions(*this, true);
3780 uno::Sequence
<OUString
> SAL_CALL
SwXCellRange::getColumnDescriptions()
3782 return m_pImpl
->GetLabelDescriptions(*this, false);
3785 void SwXCellRange::Impl::SetLabelDescriptions(SwXCellRange
& rThis
,
3786 const uno::Sequence
<OUString
>& rDesc
, bool bRow
)
3788 SolarMutexGuard aGuard
;
3789 lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(&rThis
));
3790 if (!(bRow
? m_bFirstColumnAsLabel
: m_bFirstRowAsLabel
))
3791 return; // if there are no labels we cannot set descriptions
3792 sal_uInt32 nLeft
, nTop
, nRight
, nBottom
;
3793 std::tie(nLeft
, nTop
, nRight
, nBottom
) = GetLabelCoordinates(bRow
);
3794 if(!nRight
&& !nBottom
)
3795 throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject
*>(&rThis
));
3796 auto xLabelRange(rThis
.getCellRangeByPosition(nLeft
, nTop
, nRight
, nBottom
));
3797 if (!xLabelRange
.is())
3798 throw uno::RuntimeException("Missing Cell Range", static_cast<cppu::OWeakObject
*>(&rThis
));
3799 auto vCells(static_cast<SwXCellRange
*>(xLabelRange
.get())->GetCells());
3800 if (sal::static_int_cast
<sal_uInt32
>(rDesc
.getLength()) != vCells
.size())
3801 throw uno::RuntimeException("Too few or too many descriptions", static_cast<cppu::OWeakObject
*>(&rThis
));
3802 auto pDescIterator(rDesc
.begin());
3803 for(auto& xCell
: vCells
)
3804 uno::Reference
<text::XText
>(xCell
, uno::UNO_QUERY_THROW
)->setString(*pDescIterator
++);
3807 void SAL_CALL
SwXCellRange::setRowDescriptions(
3808 const uno::Sequence
<OUString
>& rRowDesc
)
3810 m_pImpl
->SetLabelDescriptions(*this, rRowDesc
, true);
3813 void SAL_CALL
SwXCellRange::setColumnDescriptions(
3814 const uno::Sequence
<OUString
>& rColumnDesc
)
3816 m_pImpl
->SetLabelDescriptions(*this, rColumnDesc
, false);
3819 void SAL_CALL
SwXCellRange::addChartDataChangeEventListener(
3820 const uno::Reference
<chart::XChartDataChangeEventListener
> & xListener
)
3822 // no need to lock here as m_pImpl is const and container threadsafe
3823 m_pImpl
->m_ChartListeners
.addInterface(xListener
);
3826 void SAL_CALL
SwXCellRange::removeChartDataChangeEventListener(
3827 const uno::Reference
<chart::XChartDataChangeEventListener
> & xListener
)
3829 // no need to lock here as m_pImpl is const and container threadsafe
3830 m_pImpl
->m_ChartListeners
.removeInterface(xListener
);
3833 sal_Bool
SwXCellRange::isNotANumber(double /*fNumber*/)
3834 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3836 double SwXCellRange::getNotANumber()
3837 { throw uno::RuntimeException("Not implemented", static_cast<cppu::OWeakObject
*>(this)); }
3839 uno::Sequence
< beans::PropertyValue
> SwXCellRange::createSortDescriptor()
3841 SolarMutexGuard aGuard
;
3842 return SwUnoCursorHelper::CreateSortDescriptor(true);
3845 void SAL_CALL
SwXCellRange::sort(const uno::Sequence
< beans::PropertyValue
>& rDescriptor
)
3847 SolarMutexGuard aGuard
;
3848 SwSortOptions aSortOpt
;
3849 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3850 if(pFormat
&& SwUnoCursorHelper::ConvertSortProperties(rDescriptor
, aSortOpt
))
3852 SwUnoTableCursor
& rTableCursor
= dynamic_cast<SwUnoTableCursor
&>(*m_pImpl
->m_pTableCursor
);
3853 rTableCursor
.MakeBoxSels();
3854 UnoActionContext
aContext(pFormat
->GetDoc());
3855 pFormat
->GetDoc()->SortTable(rTableCursor
.GetSelectedBoxes(), aSortOpt
);
3859 sal_Int32
SwXCellRange::Impl::GetColumnCount()
3861 return m_RangeDescriptor
.nRight
- m_RangeDescriptor
.nLeft
+ 1;
3864 sal_Int32
SwXCellRange::Impl::GetRowCount()
3866 return m_RangeDescriptor
.nBottom
- m_RangeDescriptor
.nTop
+ 1;
3869 const SwUnoCursor
* SwXCellRange::GetTableCursor() const
3871 SwFrameFormat
*const pFormat
= m_pImpl
->GetFrameFormat();
3872 return pFormat
? &(*m_pImpl
->m_pTableCursor
) : nullptr;
3875 void SwXCellRange::Impl::Notify( const SfxHint
& rHint
)
3877 uno::Reference
<uno::XInterface
> const xThis(m_wThis
);
3878 if(rHint
.GetId() == SfxHintId::Dying
)
3880 m_pFrameFormat
= nullptr;
3881 m_pTableCursor
.reset(nullptr);
3884 { // fdo#72695: if UNO object is already dead, don't revive it with event
3886 lcl_SendChartEvent(xThis
.get(), m_ChartListeners
);
3888 m_ChartListeners
.disposeAndClear(lang::EventObject(xThis
));
3892 class SwXTableRows::Impl
: public SvtListener
3895 SwFrameFormat
* m_pFrameFormat
;
3898 explicit Impl(SwFrameFormat
& rFrameFormat
) : m_pFrameFormat(&rFrameFormat
)
3900 StartListening(rFrameFormat
.GetNotifier());
3902 SwFrameFormat
* GetFrameFormat() { return m_pFrameFormat
; }
3903 virtual void Notify(const SfxHint
&) override
;
3908 OUString
SwXTableRows::getImplementationName()
3909 { return "SwXTableRows"; }
3911 sal_Bool
SwXTableRows::supportsService(const OUString
& rServiceName
)
3912 { return cppu::supportsService(this, rServiceName
); }
3914 uno::Sequence
< OUString
> SwXTableRows::getSupportedServiceNames()
3915 { return { "com.sun.star.text.TableRows" }; }
3918 SwXTableRows::SwXTableRows(SwFrameFormat
& rFrameFormat
) :
3919 m_pImpl(new SwXTableRows::Impl(rFrameFormat
))
3922 SwXTableRows::~SwXTableRows()
3925 SwFrameFormat
* SwXTableRows::GetFrameFormat()
3927 return m_pImpl
->GetFrameFormat();
3930 sal_Int32
SwXTableRows::getCount()
3932 SolarMutexGuard aGuard
;
3933 SwFrameFormat
* pFrameFormat
= GetFrameFormat();
3935 throw uno::RuntimeException();
3936 SwTable
* pTable
= SwTable::FindTable(pFrameFormat
);
3937 return pTable
->GetTabLines().size();
3940 ///@see SwXCell::CreateXCell (TODO: seems to be copy and paste programming here)
3941 uno::Any
SwXTableRows::getByIndex(sal_Int32 nIndex
)
3943 SolarMutexGuard aGuard
;
3944 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
3946 throw lang::IndexOutOfBoundsException();
3947 SwTable
* pTable
= SwTable::FindTable( pFrameFormat
);
3948 if(static_cast<size_t>(nIndex
) >= pTable
->GetTabLines().size())
3949 throw lang::IndexOutOfBoundsException();
3950 SwTableLine
* pLine
= pTable
->GetTabLines()[nIndex
];
3951 FindUnoInstanceHint
<SwTableLine
,SwXTextTableRow
> aHint
{pLine
};
3952 pFrameFormat
->GetNotifier().Broadcast(aHint
);
3953 if(!aHint
.m_pResult
)
3954 aHint
.m_pResult
= new SwXTextTableRow(pFrameFormat
, pLine
);
3955 uno::Reference
<beans::XPropertySet
> xRet
= static_cast<beans::XPropertySet
*>(aHint
.m_pResult
);
3956 return uno::makeAny(xRet
);
3959 uno::Type SAL_CALL
SwXTableRows::getElementType()
3961 return cppu::UnoType
<beans::XPropertySet
>::get();
3964 sal_Bool
SwXTableRows::hasElements()
3966 SolarMutexGuard aGuard
;
3967 SwFrameFormat
* pFrameFormat
= GetFrameFormat();
3969 throw uno::RuntimeException();
3970 // a table always has rows
3974 void SwXTableRows::insertByIndex(sal_Int32 nIndex
, sal_Int32 nCount
)
3976 SolarMutexGuard aGuard
;
3979 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
3980 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFrameFormat
), static_cast<cppu::OWeakObject
*>(this));
3981 const size_t nRowCount
= pTable
->GetTabLines().size();
3982 if (nCount
<= 0 || !(0 <= nIndex
&& static_cast<size_t>(nIndex
) <= nRowCount
))
3983 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
3984 const OUString sTLName
= sw_GetCellName(0, nIndex
);
3985 const SwTableBox
* pTLBox
= pTable
->GetTableBox(sTLName
);
3986 bool bAppend
= false;
3990 // to append at the end the cursor must be in the last line
3991 SwTableLines
& rLines
= pTable
->GetTabLines();
3992 SwTableLine
* pLine
= rLines
.back();
3993 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
3994 pTLBox
= rBoxes
.front();
3997 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
3998 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
3999 SwPosition
aPos(*pSttNd
);
4000 // set cursor to the upper-left cell of the range
4001 UnoActionContext
aAction(pFrameFormat
->GetDoc());
4002 std::shared_ptr
<SwUnoTableCursor
> const pUnoCursor(
4003 std::dynamic_pointer_cast
<SwUnoTableCursor
>(
4004 pFrameFormat
->GetDoc()->CreateUnoCursor(aPos
, true)));
4005 pUnoCursor
->Move( fnMoveForward
, GoInNode
);
4007 // remove actions - TODO: why?
4008 UnoActionRemoveContext
aRemoveContext(pUnoCursor
->GetDoc());
4010 pFrameFormat
->GetDoc()->InsertRow(*pUnoCursor
, static_cast<sal_uInt16
>(nCount
), bAppend
);
4013 void SwXTableRows::removeByIndex(sal_Int32 nIndex
, sal_Int32 nCount
)
4015 SolarMutexGuard aGuard
;
4018 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
4019 if(nIndex
< 0 || nCount
<=0 )
4020 throw uno::RuntimeException();
4021 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFrameFormat
), static_cast<cppu::OWeakObject
*>(this));
4022 OUString sTLName
= sw_GetCellName(0, nIndex
);
4023 const SwTableBox
* pTLBox
= pTable
->GetTableBox(sTLName
);
4025 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
4026 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
4027 SwPosition
aPos(*pSttNd
);
4028 // set cursor to the upper-left cell of the range
4029 auto pUnoCursor(pFrameFormat
->GetDoc()->CreateUnoCursor(aPos
, true));
4030 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
4031 pUnoCursor
->SetRemainInSection( false );
4032 const OUString sBLName
= sw_GetCellName(0, nIndex
+ nCount
- 1);
4033 const SwTableBox
* pBLBox
= pTable
->GetTableBox( sBLName
);
4035 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
4036 pUnoCursor
->SetMark();
4037 pUnoCursor
->GetPoint()->nNode
= *pBLBox
->GetSttNd();
4038 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
4039 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
4041 // HACK: remove pending actions for selecting old style tables
4042 UnoActionRemoveContext
aRemoveContext(rCursor
);
4044 rCursor
.MakeBoxSels();
4045 { // these braces are important
4046 UnoActionContext
aAction(pFrameFormat
->GetDoc());
4047 pFrameFormat
->GetDoc()->DeleteRow(*pUnoCursor
);
4051 // invalidate all actions - TODO: why?
4052 UnoActionRemoveContext
aRemoveContext(pFrameFormat
->GetDoc());
4056 void SwXTableRows::Impl::Notify( const SfxHint
& rHint
)
4058 if(rHint
.GetId() == SfxHintId::Dying
)
4059 m_pFrameFormat
= nullptr;
4064 class SwXTableColumns::Impl
: public SvtListener
4066 SwFrameFormat
* m_pFrameFormat
;
4068 explicit Impl(SwFrameFormat
& rFrameFormat
) : m_pFrameFormat(&rFrameFormat
)
4070 StartListening(rFrameFormat
.GetNotifier());
4072 SwFrameFormat
* GetFrameFormat() { return m_pFrameFormat
; }
4073 virtual void Notify(const SfxHint
&) override
;
4076 OUString
SwXTableColumns::getImplementationName()
4077 { return "SwXTableColumns"; }
4079 sal_Bool
SwXTableColumns::supportsService(const OUString
& rServiceName
)
4080 { return cppu::supportsService(this, rServiceName
); }
4082 uno::Sequence
< OUString
> SwXTableColumns::getSupportedServiceNames()
4083 { return { "com.sun.star.text.TableColumns"}; }
4086 SwXTableColumns::SwXTableColumns(SwFrameFormat
& rFrameFormat
) :
4087 m_pImpl(new SwXTableColumns::Impl(rFrameFormat
))
4090 SwXTableColumns::~SwXTableColumns()
4093 SwFrameFormat
* SwXTableColumns::GetFrameFormat() const
4095 return m_pImpl
->GetFrameFormat();
4098 sal_Int32
SwXTableColumns::getCount()
4100 SolarMutexGuard aGuard
;
4101 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
4102 SwTable
* pTable
= SwTable::FindTable( pFrameFormat
);
4103 // if(!pTable->IsTableComplex())
4104 // throw uno::RuntimeException("Table too complex", static_cast<cppu::OWeakObject*>(this));
4105 SwTableLines
& rLines
= pTable
->GetTabLines();
4106 SwTableLine
* pLine
= rLines
.front();
4107 return pLine
->GetTabBoxes().size();
4110 uno::Any
SwXTableColumns::getByIndex(sal_Int32 nIndex
)
4112 SolarMutexGuard aGuard
;
4113 if(nIndex
< 0 || getCount() <= nIndex
)
4114 throw lang::IndexOutOfBoundsException();
4115 return uno::makeAny(uno::Reference
<uno::XInterface
>()); // i#21699 not supported
4118 uno::Type SAL_CALL
SwXTableColumns::getElementType()
4120 return cppu::UnoType
<uno::XInterface
>::get();
4123 sal_Bool
SwXTableColumns::hasElements()
4125 SolarMutexGuard aGuard
;
4126 lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this));
4130 ///@see SwXTableRows::insertByIndex (TODO: seems to be copy and paste programming here)
4131 void SwXTableColumns::insertByIndex(sal_Int32 nIndex
, sal_Int32 nCount
)
4133 SolarMutexGuard aGuard
;
4136 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
4137 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFrameFormat
), static_cast<cppu::OWeakObject
*>(this));
4138 SwTableLines
& rLines
= pTable
->GetTabLines();
4139 SwTableLine
* pLine
= rLines
.front();
4140 const size_t nColCount
= pLine
->GetTabBoxes().size();
4141 if (nCount
<= 0 || !(0 <= nIndex
&& static_cast<size_t>(nIndex
) <= nColCount
))
4142 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
4143 const OUString sTLName
= sw_GetCellName(nIndex
, 0);
4144 const SwTableBox
* pTLBox
= pTable
->GetTableBox( sTLName
);
4145 bool bAppend
= false;
4149 // to append at the end the cursor must be in the last line
4150 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
4151 pTLBox
= rBoxes
.back();
4154 throw uno::RuntimeException("Illegal arguments", static_cast<cppu::OWeakObject
*>(this));
4155 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
4156 SwPosition
aPos(*pSttNd
);
4157 UnoActionContext
aAction(pFrameFormat
->GetDoc());
4158 auto pUnoCursor(pFrameFormat
->GetDoc()->CreateUnoCursor(aPos
, true));
4159 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
4162 // remove actions - TODO: why?
4163 UnoActionRemoveContext
aRemoveContext(pUnoCursor
->GetDoc());
4166 pFrameFormat
->GetDoc()->InsertCol(*pUnoCursor
, static_cast<sal_uInt16
>(nCount
), bAppend
);
4169 ///@see SwXTableRows::removeByIndex (TODO: seems to be copy and paste programming here)
4170 void SwXTableColumns::removeByIndex(sal_Int32 nIndex
, sal_Int32 nCount
)
4172 SolarMutexGuard aGuard
;
4175 SwFrameFormat
* pFrameFormat(lcl_EnsureCoreConnected(GetFrameFormat(), static_cast<cppu::OWeakObject
*>(this)));
4176 if(nIndex
< 0 || nCount
<=0 )
4177 throw uno::RuntimeException();
4178 SwTable
* pTable
= lcl_EnsureTableNotComplex(SwTable::FindTable(pFrameFormat
), static_cast<cppu::OWeakObject
*>(this));
4179 const OUString sTLName
= sw_GetCellName(nIndex
, 0);
4180 const SwTableBox
* pTLBox
= pTable
->GetTableBox( sTLName
);
4182 throw uno::RuntimeException("Cell not found", static_cast<cppu::OWeakObject
*>(this));
4183 const SwStartNode
* pSttNd
= pTLBox
->GetSttNd();
4184 SwPosition
aPos(*pSttNd
);
4185 // set cursor to the upper-left cell of the range
4186 auto pUnoCursor(pFrameFormat
->GetDoc()->CreateUnoCursor(aPos
, true));
4187 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
4188 pUnoCursor
->SetRemainInSection(false);
4189 const OUString sTRName
= sw_GetCellName(nIndex
+ nCount
- 1, 0);
4190 const SwTableBox
* pTRBox
= pTable
->GetTableBox(sTRName
);
4192 throw uno::RuntimeException("Cell not found", static_cast<cppu::OWeakObject
*>(this));
4193 pUnoCursor
->SetMark();
4194 pUnoCursor
->GetPoint()->nNode
= *pTRBox
->GetSttNd();
4195 pUnoCursor
->Move(fnMoveForward
, GoInNode
);
4196 SwUnoTableCursor
& rCursor
= dynamic_cast<SwUnoTableCursor
&>(*pUnoCursor
);
4198 // HACK: remove pending actions for selecting old style tables
4199 UnoActionRemoveContext
aRemoveContext(rCursor
);
4201 rCursor
.MakeBoxSels();
4202 { // these braces are important
4203 UnoActionContext
aAction(pFrameFormat
->GetDoc());
4204 pFrameFormat
->GetDoc()->DeleteCol(*pUnoCursor
);
4208 // invalidate all actions - TODO: why?
4209 UnoActionRemoveContext
aRemoveContext(pFrameFormat
->GetDoc());
4213 void SwXTableColumns::Impl::Notify(const SfxHint
& rHint
)
4215 if(rHint
.GetId() == SfxHintId::Dying
)
4216 m_pFrameFormat
= nullptr;
4219 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */