LibreOffice Module sw (master) 1
unochart.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <algorithm>
21#include <string_view>
22
23#include <com/sun/star/chart/ChartDataRowSource.hpp>
24#include <com/sun/star/chart2/data/LabelOrigin.hpp>
25#include <com/sun/star/embed/XEmbeddedObject.hpp>
26#include <com/sun/star/frame/XModel.hpp>
28#include <o3tl/deleter.hxx>
29#include <o3tl/string_view.hxx>
30#include <mutex>
31#include <vcl/svapp.hxx>
32
33#include "XMLRangeHelper.hxx"
34#include <unochart.hxx>
35#include <swtable.hxx>
36#include <unoprnms.hxx>
37#include <unomap.hxx>
38#include <unocrsr.hxx>
39#include <unotbl.hxx>
40#include <doc.hxx>
42#include <frmfmt.hxx>
43#include <ndole.hxx>
44#include <swtypes.hxx>
45#include <strings.hrc>
47#include <comphelper/string.hxx>
48#include <svl/itemprop.hxx>
49
50using namespace ::com::sun::star;
51
53{
54 if (!pDoc)
55 return;
56
57 SwOLENode *pONd;
58 SwStartNode *pStNd;
60 while( nullptr != (pStNd = aIdx.GetNode().GetStartNode()) )
61 {
62 ++aIdx;
63 if (nullptr != ( pONd = aIdx.GetNode().GetOLENode() ) &&
64 pONd->GetOLEObj().GetObject().IsChart() )
65 {
66 // Load the object and set modified
67
68 uno::Reference < embed::XEmbeddedObject > xIP = pONd->GetOLEObj().GetOleRef();
70 {
71 try
72 {
73 uno::Reference< util::XModifiable > xModif( xIP->getComponent(), uno::UNO_QUERY_THROW );
74 xModif->setModified( true );
75 }
76 catch ( uno::Exception& )
77 {
78 }
79
80 }
81 }
82 aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
83 }
84}
85
87 m_pDoc( pDocument )
88 , m_aUnlockTimer( "sw::SwChartLockController_Helper aUnlockTimer" )
89 , m_bIsLocked( false )
90{
93}
94
96{
97 if (m_pDoc) // still connected?
99}
100
102{
103 if (!m_bIsLocked)
105 m_aUnlockTimer.Start(); // start or continue time of locking
106}
107
109{
112 m_pDoc = nullptr;
113}
114
116{
117 if (!m_pDoc)
118 return;
119
120 uno::Reference< frame::XModel > xRes;
121 SwOLENode *pONd;
122 SwStartNode *pStNd;
124 while( nullptr != (pStNd = aIdx.GetNode().GetStartNode()) )
125 {
126 ++aIdx;
127 if (nullptr != ( pONd = aIdx.GetNode().GetOLENode() ) &&
128 !pONd->GetChartTableName().isEmpty() /* is chart object? */)
129 {
130 uno::Reference < embed::XEmbeddedObject > xIP = pONd->GetOLEObj().GetOleRef();
132 {
133 xRes.set( xIP->getComponent(), uno::UNO_QUERY );
134 if (xRes.is())
135 {
136 if (bLock)
137 xRes->lockControllers();
138 else
139 xRes->unlockControllers();
140 }
141 }
142 }
143 aIdx.Assign( *pStNd->EndOfSectionNode(), + 1 );
144 }
145
146 m_bIsLocked = bLock;
147}
148
150{
151 UnlockAllCharts();
152}
153
154static std::mutex & GetChartMutex()
155{
156 static std::mutex aMutex;
157 return aMutex;
158}
159
162 const uno::Reference< uno::XInterface > &rxI )
163{
164 lang::EventObject aEvtObj( rxI );
165 std::unique_lock aGuard(GetChartMutex());
166 rICH.notifyEach( aGuard, &util::XModifyListener::modified, aEvtObj );
167}
168
175 SwRangeDescriptor &rDesc,
176 std::u16string_view rCellRangeName )
177{
178 sal_Int32 nToken = std::u16string_view::npos == rCellRangeName.find('.') ? 0 : 1;
179 std::u16string_view aCellRangeNoTableName( o3tl::getToken(rCellRangeName, nToken, '.' ) );
180 OUString aTLName( o3tl::getToken(aCellRangeNoTableName, 0, ':') ); // name of top left cell
181 OUString aBRName( o3tl::getToken(aCellRangeNoTableName, 1, ':') ); // name of bottom right cell
182 if(aTLName.isEmpty() || aBRName.isEmpty())
183 return false;
184
185 rDesc.nTop = rDesc.nLeft = rDesc.nBottom = rDesc.nRight = -1;
186 SwXTextTable::GetCellPosition( aTLName, rDesc.nLeft, rDesc.nTop );
187 SwXTextTable::GetCellPosition( aBRName, rDesc.nRight, rDesc.nBottom );
188 rDesc.Normalize();
189 OSL_ENSURE( rDesc.nTop != -1 &&
190 rDesc.nLeft != -1 &&
191 rDesc.nBottom != -1 &&
192 rDesc.nRight != -1,
193 "failed to get range descriptor" );
194 OSL_ENSURE( rDesc.nTop <= rDesc.nBottom && rDesc.nLeft <= rDesc.nRight,
195 "invalid range descriptor");
196 return true;
197}
198
199static OUString GetCellRangeName( const SwFrameFormat &rTableFormat, SwUnoCursor &rTableCursor )
200{
201 OUString aRes;
202
204
205 SwUnoTableCursor* pUnoTableCursor = dynamic_cast<SwUnoTableCursor*>(&rTableCursor);
206 if (!pUnoTableCursor)
207 return OUString();
208 pUnoTableCursor->MakeBoxSels();
209
210 const SwStartNode* pStart;
211 const SwTableBox* pStartBox = nullptr;
212 const SwTableBox* pEndBox = nullptr;
213
214 pStart = pUnoTableCursor->GetPoint()->GetNode().FindTableBoxStartNode();
215 if (pStart)
216 {
217 const SwTable* pTable = SwTable::FindTable( &rTableFormat );
218 pEndBox = pTable->GetTableBox( pStart->GetIndex());
219 aRes = pEndBox->GetName();
220
221 if(pUnoTableCursor->HasMark())
222 {
223 pStart = pUnoTableCursor->GetMark()->GetNode().FindTableBoxStartNode();
224 pStartBox = pTable->GetTableBox( pStart->GetIndex());
225 }
226 OSL_ENSURE( pStartBox, "start box not found" );
227 OSL_ENSURE( pEndBox, "end box not found" );
228
229 // need to switch start and end?
230 if (*pUnoTableCursor->GetPoint() < *pUnoTableCursor->GetMark())
231 {
232 const SwTableBox* pTmpBox = pStartBox;
233 pStartBox = pEndBox;
234 pEndBox = pTmpBox;
235 }
236
237 if (!pStartBox)
238 return aRes;
239
240 aRes = pStartBox->GetName() + ":";
241 if (pEndBox)
242 aRes += pEndBox->GetName();
243 else
244 aRes += pStartBox->GetName();
245 }
246
247 return aRes;
248}
249
250static OUString GetRangeRepFromTableAndCells( std::u16string_view rTableName,
251 std::u16string_view rStartCell, std::u16string_view rEndCell,
252 bool bForceEndCellName )
253{
254 OSL_ENSURE( !rTableName.empty(), "table name missing" );
255 OSL_ENSURE( !rStartCell.empty(), "cell name missing" );
256 OUString aRes = OUString::Concat(rTableName) + "." + rStartCell;
257
258 if (!rEndCell.empty())
259 {
260 aRes += OUString::Concat(":") + rEndCell;
261 }
262 else if (bForceEndCellName)
263 {
264 aRes += OUString::Concat(":") + rStartCell;
265 }
266
267 return aRes;
268}
269
271 std::u16string_view rRangeRepresentation,
272 OUString &rTableName,
273 OUString &rStartCell,
274 OUString &rEndCell,
275 bool bSortStartEndCells = true )
276{
277 // parse range representation for table name and cell/range names
278 // accepted format sth like: "Table1.A2:C5" , "Table2.A2.1:B3.2"
279 OUString aTableName; // table name
280 OUString aStartCell; // name of top left cell
281 OUString aEndCell; // name of bottom right cell
282 size_t nIdx = rRangeRepresentation.find( '.' );
283 if (nIdx != std::u16string_view::npos)
284 {
285 aTableName = rRangeRepresentation.substr( 0, nIdx );
286 std::u16string_view aRange = rRangeRepresentation.substr( nIdx + 1 ); // cell range
287 size_t nPos = aRange.find( ':' );
288 if (nPos != std::u16string_view::npos) // a cell-range like "Table1.A2:D4"
289 {
290 aStartCell = aRange.substr( 0, nPos );
291 aEndCell = aRange.substr( nPos + 1 );
292
293 // need to switch start and end cell ?
294 // (does not check for normalization here)
295 if (bSortStartEndCells && 1 == sw_CompareCellsByColFirst( aStartCell, aEndCell ))
296 {
297 OUString aTmp( aStartCell );
298 aStartCell = aEndCell;
299 aEndCell = aTmp;
300 }
301 }
302 else // a single cell like in "Table1.B3"
303 {
304 aStartCell = aEndCell = aRange;
305 }
306 }
307
308 bool bSuccess = !aTableName.isEmpty() &&
309 !aStartCell.isEmpty() && !aEndCell.isEmpty();
310 if (bSuccess)
311 {
312 rTableName = aTableName;
313 rStartCell = aStartCell;
314 rEndCell = aEndCell;
315 }
316 return bSuccess;
317}
318
319static void GetTableByName( const SwDoc &rDoc, std::u16string_view rTableName,
320 SwFrameFormat **ppTableFormat, SwTable **ppTable)
321{
322 SwFrameFormat *pTableFormat = nullptr;
323
324 // find frame format of table
326 const size_t nCount = rDoc.GetTableFrameFormatCount(true);
327 for (size_t i = 0; i < nCount && !pTableFormat; ++i)
328 {
329 SwFrameFormat& rTableFormat = rDoc.GetTableFrameFormat(i, true);
330 if(rTableName == rTableFormat.GetName())
331 pTableFormat = &rTableFormat;
332 }
333
334 if (ppTableFormat)
335 *ppTableFormat = pTableFormat;
336
337 if (ppTable)
338 *ppTable = pTableFormat ? SwTable::FindTable( pTableFormat ) : nullptr;
339}
340
342 const SwDoc *pDoc,
343 std::u16string_view rRangeRepresentation, // must be a single range (i.e. so called sub-range)
344 SwFrameFormat **ppTableFormat, // will be set to the table format of the table used in the range representation
345 std::shared_ptr<SwUnoCursor>& rpUnoCursor ) // will be set to cursor spanning the cell range (cursor will be created!)
346{
347 OUString aTableName; // table name
348 OUString aStartCell; // name of top left cell
349 OUString aEndCell; // name of bottom right cell
350 bool bNamesFound = GetTableAndCellsFromRangeRep( rRangeRepresentation,
351 aTableName, aStartCell, aEndCell );
352
353 if (!bNamesFound)
354 {
355 if (ppTableFormat)
356 *ppTableFormat = nullptr;
357 rpUnoCursor.reset();
358 }
359 else
360 {
361 SwFrameFormat *pTableFormat = nullptr;
362
363 // is the correct table format already provided?
364 if (*ppTableFormat != nullptr && (*ppTableFormat)->GetName() == aTableName)
365 pTableFormat = *ppTableFormat;
366 else
367 GetTableByName( *pDoc, aTableName, &pTableFormat, nullptr );
368
369 *ppTableFormat = pTableFormat;
370
371 rpUnoCursor.reset(); // default result in case of failure
372
373 SwTable *pTable = pTableFormat ? SwTable::FindTable( pTableFormat ) : nullptr;
374 // create new SwUnoCursor spanning the specified range
376 // #i80314#
377 // perform validation check. Thus, pass <true> as 2nd parameter to <SwTable::GetTableBox(..)>
378 const SwTableBox* pTLBox =
379 pTable ? pTable->GetTableBox( aStartCell, true ) : nullptr;
380 if(pTLBox)
381 {
382 const SwStartNode* pSttNd = pTLBox->GetSttNd();
383 SwPosition aPos(*pSttNd);
384
385 // set cursor to top left box of range
386 auto pUnoCursor = pTableFormat->GetDoc()->CreateUnoCursor(aPos, true);
387 pUnoCursor->Move( fnMoveForward, GoInNode );
388 pUnoCursor->SetRemainInSection( false );
389
390 // #i80314#
391 // perform validation check. Thus, pass <true> as 2nd parameter to <SwTable::GetTableBox(..)>
392 const SwTableBox* pBRBox = pTable->GetTableBox( aEndCell, true );
393 if(pBRBox)
394 {
395 pUnoCursor->SetMark();
396 pUnoCursor->GetPoint()->Assign( *pBRBox->GetSttNd() );
397 pUnoCursor->Move( fnMoveForward, GoInNode );
398 SwUnoTableCursor& rCursor =
399 dynamic_cast<SwUnoTableCursor&>(*pUnoCursor);
400 // HACK: remove pending actions for old style tables
401 UnoActionRemoveContext aRemoveContext(rCursor);
402 rCursor.MakeBoxSels();
403 rpUnoCursor = pUnoCursor;
404 }
405 }
406 }
407}
408
409static bool GetSubranges( std::u16string_view rRangeRepresentation,
410 uno::Sequence< OUString > &rSubRanges, bool bNormalize )
411{
412 bool bRes = true;
413 const sal_Int32 nLen = comphelper::string::getTokenCount(rRangeRepresentation, ';');
414 uno::Sequence< OUString > aRanges( nLen );
415
416 sal_Int32 nCnt = 0;
417 if (nLen != 0)
418 {
419 OUString *pRanges = aRanges.getArray();
420 OUString aFirstTable;
421 sal_Int32 nPos = 0;
422 for( sal_Int32 i = 0; i < nLen && bRes; ++i )
423 {
424 const OUString aRange( o3tl::getToken(rRangeRepresentation, 0, ';', nPos ) );
425 if (!aRange.isEmpty())
426 {
427 pRanges[nCnt] = aRange;
428
429 OUString aTableName, aStartCell, aEndCell;
430 if (!GetTableAndCellsFromRangeRep( aRange,
431 aTableName, aStartCell, aEndCell ))
432 bRes = false;
433
434 if (bNormalize)
435 {
436 sw_NormalizeRange( aStartCell, aEndCell );
437 pRanges[nCnt] = GetRangeRepFromTableAndCells( aTableName,
438 aStartCell, aEndCell, true );
439 }
440
441 // make sure to use only a single table
442 if (nCnt == 0)
443 aFirstTable = aTableName;
444 else
445 if (aFirstTable != aTableName) bRes = false;
446
447 ++nCnt;
448 }
449 }
450 }
451 aRanges.realloc( nCnt );
452
453 rSubRanges = aRanges;
454 return bRes;
455}
456
457static void SortSubranges( uno::Sequence< OUString > &rSubRanges, bool bCmpByColumn )
458{
459 sal_Int32 nLen = rSubRanges.getLength();
460 OUString *pSubRanges = rSubRanges.getArray();
461
462 OUString aSmallestTableName;
463 OUString aSmallestStartCell;
464 OUString aSmallestEndCell;
465
466 for (sal_Int32 i = 0; i < nLen; ++i)
467 {
468 sal_Int32 nIdxOfSmallest = i;
469 GetTableAndCellsFromRangeRep( pSubRanges[nIdxOfSmallest],
470 aSmallestTableName, aSmallestStartCell, aSmallestEndCell );
471 if (aSmallestEndCell.isEmpty())
472 aSmallestEndCell = aSmallestStartCell;
473
474 for (sal_Int32 k = i+1; k < nLen; ++k)
475 {
476 // get cell names for sub range
477 OUString aTableName;
478 OUString aStartCell;
479 OUString aEndCell;
480 GetTableAndCellsFromRangeRep( pSubRanges[k],
481 aTableName, aStartCell, aEndCell );
482 if (aEndCell.isEmpty())
483 aEndCell = aStartCell;
484
485 // compare cell ranges ( is the new one smaller? )
486 if (-1 == sw_CompareCellRanges( aStartCell, aEndCell,
487 aSmallestStartCell, aSmallestEndCell, bCmpByColumn ))
488 {
489 nIdxOfSmallest = k;
490 aSmallestTableName = aTableName;
491 aSmallestStartCell = aStartCell;
492 aSmallestEndCell = aEndCell;
493 }
494 }
495
496 // move smallest element to the start of the not sorted area
497 const OUString aTmp( pSubRanges[ nIdxOfSmallest ] );
498 pSubRanges[ nIdxOfSmallest ] = pSubRanges[ i ];
499 pSubRanges[ i ] = aTmp;
500 }
501}
502
504 m_pDoc( &rSwDoc )
505{
506 m_bDisposed = false;
507}
508
510{
511}
512
513uno::Reference< chart2::data::XDataSource > SwChartDataProvider::Impl_createDataSource(
514 const uno::Sequence< beans::PropertyValue >& rArguments, bool bTestOnly )
515{
516 SolarMutexGuard aGuard;
517 if (m_bDisposed)
518 throw lang::DisposedException();
519
520 uno::Reference< chart2::data::XDataSource > xRes;
521
522 if (!m_pDoc)
523 throw uno::RuntimeException("Not connected to a document.");
524
525 // get arguments
526 OUString aRangeRepresentation;
527 uno::Sequence< sal_Int32 > aSequenceMapping;
528 bool bFirstIsLabel = false;
529 bool bDtaSrcIsColumns = true; // true : DataSource will be sequence of columns
530 // false: DataSource will be sequence of rows
531
532 OUString aChartOleObjectName; //work around wrong writer ranges ( see Issue 58464 )
533 sal_Int32 nArgs = rArguments.getLength();
534 OSL_ENSURE( nArgs != 0, "no properties provided" );
535 if (nArgs == 0)
536 return xRes;
537 for (const beans::PropertyValue& rArg : rArguments)
538 {
539 if ( rArg.Name == "DataRowSource" )
540 {
541 chart::ChartDataRowSource eSource;
542 if (!(rArg.Value >>= eSource))
543 {
544 sal_Int32 nTmp = 0;
545 if (!(rArg.Value >>= nTmp))
546 throw lang::IllegalArgumentException();
547 eSource = static_cast< chart::ChartDataRowSource >( nTmp );
548 }
549 bDtaSrcIsColumns = eSource == chart::ChartDataRowSource_COLUMNS;
550 }
551 else if ( rArg.Name == "FirstCellAsLabel" )
552 {
553 if (!(rArg.Value >>= bFirstIsLabel))
554 throw lang::IllegalArgumentException();
555 }
556 else if ( rArg.Name == "CellRangeRepresentation" )
557 {
558 if (!(rArg.Value >>= aRangeRepresentation))
559 throw lang::IllegalArgumentException();
560 }
561 else if ( rArg.Name == "SequenceMapping" )
562 {
563 if (!(rArg.Value >>= aSequenceMapping))
564 throw lang::IllegalArgumentException();
565 }
566 else if ( rArg.Name == "ChartOleObjectName" )
567 {
568 if (!(rArg.Value >>= aChartOleObjectName))
569 throw lang::IllegalArgumentException();
570 }
571 }
572
573 uno::Sequence< OUString > aSubRanges;
574 // get sub-ranges and check that they all are from the very same table
575 bool bOk = GetSubranges( aRangeRepresentation, aSubRanges, true );
576
577 if (!bOk && m_pDoc && !aChartOleObjectName.isEmpty() )
578 {
579 //try to correct the range here
580 //work around wrong writer ranges ( see Issue 58464 )
581 OUString aChartTableName;
582
583 const SwNodes& rNodes = m_pDoc->GetNodes();
584 for( SwNodeOffset nN = rNodes.Count(); nN--; )
585 {
586 SwNode* pNode = rNodes[nN];
587 if( !pNode )
588 continue;
589 const SwOLENode* pOleNode = pNode->GetOLENode();
590 if( !pOleNode )
591 continue;
592 const SwOLEObj& rOObj = pOleNode->GetOLEObj();
593 if( aChartOleObjectName == rOObj.GetCurrentPersistName() )
594 {
595 aChartTableName = pOleNode->GetChartTableName();
596 break;
597 }
598 }
599
600 if( !aChartTableName.isEmpty() )
601 {
602 //the wrong range is still shifted one row down
603 //thus the first row is missing and an invalid row at the end is added.
604 //Therefore we need to shift the range one row up
605 SwRangeDescriptor aDesc;
606 if (aRangeRepresentation.isEmpty())
607 return xRes; // we can't handle this thus returning an empty references
608
609 aRangeRepresentation = aRangeRepresentation.copy( 1 ); // get rid of '.' to have only the cell range left
610 FillRangeDescriptor( aDesc, aRangeRepresentation );
611 aDesc.Normalize();
612
613 if (aDesc.nTop <= 0) // no chance to shift the range one row up?
614 return xRes; // we can't handle this thus returning an empty references
615
616 aDesc.nTop -= 1;
617 aDesc.nBottom -= 1;
618
619 OUString aNewStartCell( sw_GetCellName( aDesc.nLeft, aDesc.nTop ) );
620 OUString aNewEndCell( sw_GetCellName( aDesc.nRight, aDesc.nBottom ) );
621 aRangeRepresentation = GetRangeRepFromTableAndCells(
622 aChartTableName, aNewStartCell, aNewEndCell, true );
623 bOk = GetSubranges( aRangeRepresentation, aSubRanges, true );
624 }
625 }
626 if (!bOk) // different tables used, or incorrect range specifiers
627 throw lang::IllegalArgumentException();
628
629 SortSubranges( aSubRanges, bDtaSrcIsColumns );
630
631 // get table format for that single table from above
632 SwFrameFormat *pTableFormat = nullptr; // pointer to table format
633 std::shared_ptr<SwUnoCursor> pUnoCursor; // here required to check if the cells in the range do actually exist
634 if (aSubRanges.hasElements())
635 GetFormatAndCreateCursorFromRangeRep( m_pDoc, aSubRanges[0], &pTableFormat, pUnoCursor );
636
637 if (!pTableFormat || !pUnoCursor)
638 throw lang::IllegalArgumentException();
639
640 SwTable* pTable = SwTable::FindTable(pTableFormat);
641 if (pTable->IsTableComplex())
642 return xRes; // we can't handle this thus returning an empty references
643
644 // get a character map in the size of the table to mark
645 // all the ranges to use in
646 sal_Int32 nRows = pTable->GetTabLines().size();
647 sal_Int32 nCols = 0;
648 // As per tdf#149718 one should know that some cells can be merged together.
649 // Therefore, the number of columns (boxes in each row) are not necessarily
650 // equal. Here, we calculate the maximum number of columns in all rows.
651 for (sal_Int32 i = 0; i < nRows; ++i)
652 nCols = std::max(nCols, static_cast<sal_Int32>(pTable->GetTabLines()[i]->GetTabBoxes().size()));
653
654 std::vector<std::vector<char>> aMap(nRows);
655 for (sal_Int32 i = 0; i < nRows; ++i)
656 aMap[i].resize(nCols);
657
658 // iterate over subranges and mark used cells in above map
662 for (const OUString& rSubRange : std::as_const(aSubRanges))
663 {
664 OUString aTableName, aStartCell, aEndCell;
666 rSubRange, aTableName, aStartCell, aEndCell );
667 OSL_ENSURE(bOk2, "failed to get table and start/end cells");
668
669 sal_Int32 nStartRow, nStartCol, nEndRow, nEndCol;
670 SwXTextTable::GetCellPosition(aStartCell, nStartCol, nStartRow);
671 SwXTextTable::GetCellPosition(aEndCell, nEndCol, nEndRow);
672 OSL_ENSURE( nStartRow <= nEndRow && nStartCol <= nEndCol,
673 "cell range not normalized");
674
675 // test if the ranges span more than the available cells
676 if( nStartRow < 0 || nEndRow >= nRows ||
677 nStartCol < 0 || nEndCol >= nCols )
678 {
679 throw lang::IllegalArgumentException();
680 }
681 for (sal_Int32 k1 = nStartRow; k1 <= nEndRow; ++k1)
682 {
683 for (sal_Int32 k2 = nStartCol; k2 <= nEndCol; ++k2)
684 aMap[k1][k2] = 'x';
685 }
686 }
687
688 // find label and data sequences to use
689
690 sal_Int32 oi; // outer index (slower changing index)
691 sal_Int32 ii; // inner index (faster changing index)
692 sal_Int32 oiEnd = bDtaSrcIsColumns ? nCols : nRows;
693 sal_Int32 iiEnd = bDtaSrcIsColumns ? nRows : nCols;
694 std::vector<sal_Int32> aLabelIdx(oiEnd);
695 std::vector<sal_Int32> aDataStartIdx(oiEnd);
696 std::vector<sal_Int32> aDataLen(oiEnd);
697 for (oi = 0; oi < oiEnd; ++oi)
698 {
699 aLabelIdx[oi] = -1;
700 aDataStartIdx[oi] = -1;
701 aDataLen[oi] = 0;
702 }
703
704 for (oi = 0; oi < oiEnd; ++oi)
705 {
706 ii = 0;
707 while (ii < iiEnd)
708 {
709 char &rChar = bDtaSrcIsColumns ? aMap[ii][oi] : aMap[oi][ii];
710
711 // label should be used but is not yet found?
712 if (rChar == 'x' && bFirstIsLabel && aLabelIdx[oi] == -1)
713 {
714 aLabelIdx[oi] = ii;
715 rChar = 'L'; // setting a different char for labels here
716 // makes the test for the data sequence below
717 // easier
718 }
719
720 // find data sequence
721 if (rChar == 'x' && aDataStartIdx[oi] == -1)
722 {
723 aDataStartIdx[oi] = ii;
724
725 // get length of data sequence
726 sal_Int32 nL = 0;
727 while (ii< iiEnd && 'x' == (bDtaSrcIsColumns ? aMap[ii][oi] : aMap[oi][ii]))
728 {
729 ++nL; ++ii;
730 }
731 aDataLen[oi] = nL;
732
733 // check that there is no other separate sequence of data
734 // to be found because that is not supported
735 while (ii < iiEnd)
736 {
737 if ('x' == (bDtaSrcIsColumns ? aMap[ii][oi] : aMap[oi][ii]))
738 throw lang::IllegalArgumentException();
739 ++ii;
740 }
741 }
742 else
743 ++ii;
744 }
745 }
746
747 // make some other consistency checks while calculating
748 // the number of XLabeledDataSequence to build:
749 // - labels should always be used or not at all
750 // - the data sequences should have equal non-zero length
751 sal_Int32 nNumLDS = 0;
752 if (oiEnd > 0)
753 {
754 for (oi = 0; oi < oiEnd; ++oi)
755 {
756 // row/col used at all?
757 if (aDataStartIdx[oi] != -1 &&
758 (!bFirstIsLabel || aLabelIdx[oi] != -1))
759 {
760 ++nNumLDS;
761 }
762 }
763 }
764 if (nNumLDS == 0)
765 throw lang::IllegalArgumentException();
766
767 // now we should have all necessary data to build a proper DataSource
768 // thus if we came this far there should be no further problem
769 if (bTestOnly)
770 return xRes; // have createDataSourcePossible return true
771
772 // create data source from found label and data sequences
773 uno::Sequence<uno::Reference<chart2::data::XDataSequence>> aLabelSeqs(nNumLDS);
774 uno::Reference<chart2::data::XDataSequence>* pLabelSeqs = aLabelSeqs.getArray();
775 uno::Sequence<uno::Reference<chart2::data::XDataSequence>> aDataSeqs(nNumLDS);
776 uno::Reference<chart2::data::XDataSequence>* pDataSeqs = aDataSeqs.getArray();
777 sal_Int32 nSeqsIdx = 0;
778 for (oi = 0; oi < oiEnd; ++oi)
779 {
780 // row/col not used? (see if-statement above where nNumLDS was counted)
781 if (!(aDataStartIdx[oi] != -1 &&
782 (!bFirstIsLabel || aLabelIdx[oi] != -1)))
783 continue;
784
785 // get cell ranges for label and data
786
787 SwRangeDescriptor aLabelDesc;
788 SwRangeDescriptor aDataDesc;
789 if (bDtaSrcIsColumns) // use columns
790 {
791 aLabelDesc.nTop = aLabelIdx[oi];
792 aLabelDesc.nLeft = oi;
793 aLabelDesc.nBottom = aLabelDesc.nTop;
794 aLabelDesc.nRight = oi;
795
796 aDataDesc.nTop = aDataStartIdx[oi];
797 aDataDesc.nLeft = oi;
798 aDataDesc.nBottom = aDataDesc.nTop + aDataLen[oi] - 1;
799 aDataDesc.nRight = oi;
800 }
801 else // use rows
802 {
803 aLabelDesc.nTop = oi;
804 aLabelDesc.nLeft = aLabelIdx[oi];
805 aLabelDesc.nBottom = oi;
806 aLabelDesc.nRight = aLabelDesc.nLeft;
807
808 aDataDesc.nTop = oi;
809 aDataDesc.nLeft = aDataStartIdx[oi];
810 aDataDesc.nBottom = oi;
811 aDataDesc.nRight = aDataDesc.nLeft + aDataLen[oi] - 1;
812 }
813 const OUString aBaseName = pTableFormat->GetName() + ".";
814
815 OUString aLabelRange;
816 if (aLabelIdx[oi] != -1)
817 {
818 aLabelRange = aBaseName
819 + sw_GetCellName( aLabelDesc.nLeft, aLabelDesc.nTop )
820 + ":" + sw_GetCellName( aLabelDesc.nRight, aLabelDesc.nBottom );
821 }
822
823 OUString aDataRange = aBaseName
824 + sw_GetCellName( aDataDesc.nLeft, aDataDesc.nTop )
825 + ":" + sw_GetCellName( aDataDesc.nRight, aDataDesc.nBottom );
826
827 // get cursors spanning the cell ranges for label and data
828 std::shared_ptr<SwUnoCursor> pLabelUnoCursor;
829 std::shared_ptr<SwUnoCursor> pDataUnoCursor;
830 GetFormatAndCreateCursorFromRangeRep(m_pDoc, aLabelRange, &pTableFormat, pLabelUnoCursor);
831 GetFormatAndCreateCursorFromRangeRep(m_pDoc, aDataRange, &pTableFormat, pDataUnoCursor);
832
833 // create XDataSequence's from cursors
834 if (pLabelUnoCursor)
835 pLabelSeqs[nSeqsIdx] = new SwChartDataSequence(*this, *pTableFormat, pLabelUnoCursor);
836 OSL_ENSURE(pDataUnoCursor, "pointer to data sequence missing");
837 if (pDataUnoCursor)
838 pDataSeqs[nSeqsIdx] = new SwChartDataSequence(*this, *pTableFormat, pDataUnoCursor);
839 if (pLabelUnoCursor || pDataUnoCursor)
840 ++nSeqsIdx;
841 }
842 OSL_ENSURE(nSeqsIdx == nNumLDS, "mismatch between sequence size and num,ber of entries");
843
844 // build data source from data and label sequences
845 uno::Sequence<uno::Reference<chart2::data::XLabeledDataSequence>> aLDS(nNumLDS);
846 uno::Reference<chart2::data::XLabeledDataSequence>* pLDS = aLDS.getArray();
847 for (sal_Int32 i = 0; i < nNumLDS; ++i)
848 {
850 pLabeledDtaSeq->setLabel(pLabelSeqs[i]);
851 pLabeledDtaSeq->setValues(pDataSeqs[i]);
852 pLDS[i] = pLabeledDtaSeq;
853 }
854
855 // apply 'SequenceMapping' if it was provided
856 if (aSequenceMapping.hasElements())
857 {
858 uno::Sequence<uno::Reference<chart2::data::XLabeledDataSequence>> aOld_LDS(aLDS);
859 uno::Reference<chart2::data::XLabeledDataSequence>* pOld_LDS = aOld_LDS.getArray();
860
861 sal_Int32 nNewCnt = 0;
862 for (sal_Int32 nIdx : std::as_const(aSequenceMapping))
863 {
864 // check that index to be used is valid
865 // and has not yet been used
866 if (0 <= nIdx && nIdx < nNumLDS && pOld_LDS[nIdx].is())
867 {
868 pLDS[nNewCnt++] = pOld_LDS[nIdx];
869
870 // mark index as being used already (avoids duplicate entries)
871 pOld_LDS[nIdx].clear();
872 }
873 }
874 // add not yet used 'old' sequences to new one
875 for (sal_Int32 i = 0; i < nNumLDS; ++i)
876 {
877 if (pOld_LDS[i].is())
878 pLDS[nNewCnt++] = pOld_LDS[i];
879 }
880 OSL_ENSURE(nNewCnt == nNumLDS, "unexpected size of resulting sequence");
881 }
882
883 xRes = new SwChartDataSource(aLDS);
884 return xRes;
885}
886
888 const uno::Sequence< beans::PropertyValue >& rArguments )
889{
890 SolarMutexGuard aGuard;
891
892 bool bPossible = true;
893 try
894 {
895 Impl_createDataSource( rArguments, true );
896 }
897 catch (lang::IllegalArgumentException &)
898 {
899 bPossible = false;
900 }
901
902 return bPossible;
903}
904
905uno::Reference< chart2::data::XDataSource > SAL_CALL SwChartDataProvider::createDataSource(
906 const uno::Sequence< beans::PropertyValue >& rArguments )
907{
908 SolarMutexGuard aGuard;
909 return Impl_createDataSource( rArguments );
910}
911
922 std::u16string_view rCellRangeRepresentation )
923{
924 // check that we do not have multiple ranges
925 if (std::u16string_view::npos == rCellRangeRepresentation.find( ';' ))
926 {
927 // get current cell and table names
928 OUString aTableName, aStartCell, aEndCell;
929 GetTableAndCellsFromRangeRep( rCellRangeRepresentation,
930 aTableName, aStartCell, aEndCell, false );
931 sal_Int32 nStartCol = -1, nStartRow = -1, nEndCol = -1, nEndRow = -1;
932 SwXTextTable::GetCellPosition( aStartCell, nStartCol, nStartRow );
933 SwXTextTable::GetCellPosition( aEndCell, nEndCol, nEndRow );
934
935 // get new cell names
936 ++nStartRow;
937 ++nEndRow;
938 aStartCell = sw_GetCellName( nStartCol, nStartRow );
939 aEndCell = sw_GetCellName( nEndCol, nEndRow );
940
941 return GetRangeRepFromTableAndCells( aTableName,
942 aStartCell, aEndCell, false );
943 }
944
945 return OUString();
946}
947
948uno::Sequence< beans::PropertyValue > SAL_CALL SwChartDataProvider::detectArguments(
949 const uno::Reference< chart2::data::XDataSource >& xDataSource )
950{
951 SolarMutexGuard aGuard;
952 if (m_bDisposed)
953 throw lang::DisposedException();
954
955 uno::Sequence< beans::PropertyValue > aResult;
956 if (!xDataSource.is())
957 return aResult;
958
959 const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aDS_LDS( xDataSource->getDataSequences() );
960 const uno::Reference< chart2::data::XLabeledDataSequence > *pDS_LDS = aDS_LDS.getConstArray();
961 sal_Int32 nNumDS_LDS = aDS_LDS.getLength();
962
963 if (nNumDS_LDS == 0)
964 {
965 OSL_FAIL( "XLabeledDataSequence in data source contains 0 entries" );
966 return aResult;
967 }
968
969 SwFrameFormat *pTableFormat = nullptr;
970 SwTable *pTable = nullptr;
971 OUString aTableName;
972 sal_Int32 nTableRows = 0;
973 sal_Int32 nTableCols = 0;
974
975 // data used to build 'CellRangeRepresentation' from later on
976 std::vector< std::vector< char > > aMap;
977
978 uno::Sequence< sal_Int32 > aSequenceMapping( nNumDS_LDS );
979 sal_Int32 *pSequenceMapping = aSequenceMapping.getArray();
980
981 OUString aCellRanges;
982 sal_Int16 nDtaSrcIsColumns = -1;// -1: don't know yet, 0: false, 1: true -2: neither
983 sal_Int32 nLabelSeqLen = -1; // used to see if labels are always used or not and have
984 // the expected size of 1 (i.e. if FirstCellAsLabel can
985 // be determined)
986 // -1: don't know yet, 0: not used, 1: always a single labe cell, ...
987 // -2: neither/failed
988 for (sal_Int32 nDS1 = 0; nDS1 < nNumDS_LDS; ++nDS1)
989 {
990 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledDataSequence( pDS_LDS[nDS1] );
991 if( !xLabeledDataSequence.is() )
992 {
993 OSL_FAIL("got NULL for XLabeledDataSequence from Data source");
994 continue;
995 }
996 const uno::Reference< chart2::data::XDataSequence > xCurLabel = xLabeledDataSequence->getLabel();
997 const uno::Reference< chart2::data::XDataSequence > xCurValues = xLabeledDataSequence->getValues();
998
999 // get sequence lengths for label and values.
1000 // (0 length is Ok)
1001 sal_Int32 nCurLabelSeqLen = -1;
1002 sal_Int32 nCurValuesSeqLen = -1;
1003 if (xCurLabel.is())
1004 nCurLabelSeqLen = xCurLabel->getData().getLength();
1005 if (xCurValues.is())
1006 nCurValuesSeqLen = xCurValues->getData().getLength();
1007
1008 // check for consistent use of 'first cell as label'
1009 if (nLabelSeqLen == -1) // set initial value to compare with below further on
1010 nLabelSeqLen = nCurLabelSeqLen;
1011 if (nLabelSeqLen != nCurLabelSeqLen)
1012 nLabelSeqLen = -2; // failed / no consistent use of label cells
1013
1014 // get table and cell names for label and values data sequences
1015 // (start and end cell will be sorted, i.e. start cell <= end cell)
1016 OUString aLabelTableName, aLabelStartCell, aLabelEndCell;
1017 OUString aValuesTableName, aValuesStartCell, aValuesEndCell;
1018 OUString aLabelRange, aValuesRange;
1019 if (xCurLabel.is())
1020 aLabelRange = xCurLabel->getSourceRangeRepresentation();
1021 if (xCurValues.is())
1022 aValuesRange = xCurValues->getSourceRangeRepresentation();
1023 if ((!aLabelRange.isEmpty() && !GetTableAndCellsFromRangeRep( aLabelRange,
1024 aLabelTableName, aLabelStartCell, aLabelEndCell )) ||
1025 !GetTableAndCellsFromRangeRep( aValuesRange,
1026 aValuesTableName, aValuesStartCell, aValuesEndCell ))
1027 {
1028 return aResult; // failed -> return empty property sequence
1029 }
1030
1031 // make sure all sequences use the same table
1032 if (aTableName.isEmpty())
1033 aTableName = aValuesTableName; // get initial value to compare with
1034 if (aTableName.isEmpty() ||
1035 aTableName != aValuesTableName ||
1036 (!aLabelTableName.isEmpty() && aTableName != aLabelTableName))
1037 {
1038 return aResult; // failed -> return empty property sequence
1039 }
1040
1041 // try to get 'DataRowSource' value (ROWS or COLUMNS) from inspecting
1042 // first and last cell used in both sequences
1043
1044 sal_Int32 nFirstCol = -1, nFirstRow = -1, nLastCol = -1, nLastRow = -1;
1045 const OUString aCell( !aLabelStartCell.isEmpty() ? aLabelStartCell : aValuesStartCell );
1046 OSL_ENSURE( !aCell.isEmpty() , "start cell missing?" );
1047 SwXTextTable::GetCellPosition( aCell, nFirstCol, nFirstRow);
1048 SwXTextTable::GetCellPosition( aValuesEndCell, nLastCol, nLastRow);
1049
1050 sal_Int16 nDirection = -1; // -1: not yet set, 0: columns, 1: rows, -2: failed
1051 if (nFirstCol == nLastCol && nFirstRow == nLastRow) // a single cell...
1052 {
1053 OSL_ENSURE( nCurLabelSeqLen == 0 && nCurValuesSeqLen == 1,
1054 "trying to determine 'DataRowSource': something's fishy... should have been a single cell");
1055 nDirection = 0; // default direction for a single cell should be 'columns'
1056 }
1057 else // more than one cell is available (in values and label together!)
1058 {
1059 if (nFirstCol == nLastCol && nFirstRow != nLastRow)
1060 nDirection = 1;
1061 else if (nFirstCol != nLastCol && nFirstRow == nLastRow)
1062 nDirection = 0;
1063 else
1064 {
1065 OSL_FAIL( "trying to determine 'DataRowSource': unexpected case found" );
1066 nDirection = -2;
1067 }
1068 }
1069 // check for consistent direction of data source
1070 if (nDtaSrcIsColumns == -1) // set initial value to compare with below
1071 nDtaSrcIsColumns = nDirection;
1072 if (nDtaSrcIsColumns != nDirection)
1073 {
1074 nDtaSrcIsColumns = -2; // failed
1075 }
1076
1077 if (nDtaSrcIsColumns == 0 || nDtaSrcIsColumns == 1)
1078 {
1079 // build data to obtain 'SequenceMapping' later on
1080
1081 OSL_ENSURE( nDtaSrcIsColumns == 0 || /* rows */
1082 nDtaSrcIsColumns == 1, /* columns */
1083 "unexpected value for 'nDtaSrcIsColumns'" );
1084 pSequenceMapping[nDS1] = nDtaSrcIsColumns ? nFirstCol : nFirstRow;
1085
1086 // build data used to determine 'CellRangeRepresentation' later on
1087
1088 GetTableByName( *m_pDoc, aTableName, &pTableFormat, &pTable );
1089 if (!pTable || pTable->IsTableComplex())
1090 return aResult; // failed -> return empty property sequence
1091 nTableRows = pTable->GetTabLines().size();
1092 nTableCols = pTable->GetTabLines().front()->GetTabBoxes().size();
1093 aMap.resize( nTableRows );
1094 for (sal_Int32 i = 0; i < nTableRows; ++i)
1095 aMap[i].resize( nTableCols );
1096
1097 if (!aLabelStartCell.isEmpty() && !aLabelEndCell.isEmpty())
1098 {
1099 sal_Int32 nStartCol = -1, nStartRow = -1, nEndCol = -1, nEndRow = -1;
1100 SwXTextTable::GetCellPosition( aLabelStartCell, nStartCol, nStartRow );
1101 SwXTextTable::GetCellPosition( aLabelEndCell, nEndCol, nEndRow );
1102 if (nStartRow < 0 || nEndRow >= nTableRows ||
1103 nStartCol < 0 || nEndCol >= nTableCols)
1104 {
1105 return aResult; // failed -> return empty property sequence
1106 }
1107 for (sal_Int32 i = nStartRow; i <= nEndRow; ++i)
1108 {
1109 for (sal_Int32 k = nStartCol; k <= nEndCol; ++k)
1110 {
1111 char &rChar = aMap[i][k];
1112 if (rChar == '\0') // check for overlapping values and/or labels
1113 rChar = 'L';
1114 else
1115 return aResult; // failed -> return empty property sequence
1116 }
1117 }
1118 }
1119 if (!aValuesStartCell.isEmpty() && !aValuesEndCell.isEmpty())
1120 {
1121 sal_Int32 nStartCol = -1, nStartRow = -1, nEndCol = -1, nEndRow = -1;
1122 SwXTextTable::GetCellPosition( aValuesStartCell, nStartCol, nStartRow );
1123 SwXTextTable::GetCellPosition( aValuesEndCell, nEndCol, nEndRow );
1124 if (nStartRow < 0 || nEndRow >= nTableRows ||
1125 nStartCol < 0 || nEndCol >= nTableCols)
1126 {
1127 return aResult; // failed -> return empty property sequence
1128 }
1129 for (sal_Int32 i = nStartRow; i <= nEndRow; ++i)
1130 {
1131 for (sal_Int32 k = nStartCol; k <= nEndCol; ++k)
1132 {
1133 char &rChar = aMap[i][k];
1134 if (rChar == '\0') // check for overlapping values and/or labels
1135 rChar = 'x';
1136 else
1137 return aResult; // failed -> return empty property sequence
1138 }
1139 }
1140 }
1141 }
1142
1143#if OSL_DEBUG_LEVEL > 0
1144 // do some extra sanity checking that the length of the sequences
1145 // matches their range representation
1146 {
1147 sal_Int32 nStartRow = -1, nStartCol = -1, nEndRow = -1, nEndCol = -1;
1148 if (xCurLabel.is())
1149 {
1150 SwXTextTable::GetCellPosition( aLabelStartCell, nStartCol, nStartRow);
1151 SwXTextTable::GetCellPosition( aLabelEndCell, nEndCol, nEndRow);
1152 OSL_ENSURE( (nStartCol == nEndCol && (nEndRow - nStartRow + 1) == xCurLabel->getData().getLength()) ||
1153 (nStartRow == nEndRow && (nEndCol - nStartCol + 1) == xCurLabel->getData().getLength()),
1154 "label sequence length does not match range representation!" );
1155 }
1156 if (xCurValues.is())
1157 {
1158 SwXTextTable::GetCellPosition( aValuesStartCell, nStartCol, nStartRow);
1159 SwXTextTable::GetCellPosition( aValuesEndCell, nEndCol, nEndRow);
1160 OSL_ENSURE( (nStartCol == nEndCol && (nEndRow - nStartRow + 1) == xCurValues->getData().getLength()) ||
1161 (nStartRow == nEndRow && (nEndCol - nStartCol + 1) == xCurValues->getData().getLength()),
1162 "value sequence length does not match range representation!" );
1163 }
1164 }
1165#endif
1166 } // for
1167
1168 // build value for 'CellRangeRepresentation'
1169
1170 const OUString aCellRangeBase = aTableName + ".";
1171 OUString aCurRange;
1172 for (sal_Int32 i = 0; i < nTableRows; ++i)
1173 {
1174 for (sal_Int32 k = 0; k < nTableCols; ++k)
1175 {
1176 if (aMap[i][k] != '\0') // top-left cell of a sub-range found
1177 {
1178 // find rectangular sub-range to use
1179 sal_Int32 nRowIndex1 = i; // row index
1180 sal_Int32 nColIndex1 = k; // column index
1181 sal_Int32 nRowSubLen = 0;
1182 sal_Int32 nColSubLen = 0;
1183 while (nRowIndex1 < nTableRows && aMap[nRowIndex1++][k] != '\0')
1184 ++nRowSubLen;
1185 // be aware of shifted sequences!
1186 // (according to the checks done prior the length should be ok)
1187 while (nColIndex1 < nTableCols && aMap[i][nColIndex1] != '\0'
1188 && aMap[i + nRowSubLen-1][nColIndex1] != '\0')
1189 {
1190 ++nColIndex1;
1191 ++nColSubLen;
1192 }
1193 OUString aStartCell( sw_GetCellName( k, i ) );
1194 OUString aEndCell( sw_GetCellName( k + nColSubLen - 1, i + nRowSubLen - 1) );
1195 aCurRange = aCellRangeBase + aStartCell + ":" + aEndCell;
1196 if (!aCellRanges.isEmpty())
1197 aCellRanges += ";";
1198 aCellRanges += aCurRange;
1199
1200 // clear already found sub-range from map
1201 for (sal_Int32 nRowIndex2 = 0; nRowIndex2 < nRowSubLen; ++nRowIndex2)
1202 for (sal_Int32 nColumnIndex2 = 0; nColumnIndex2 < nColSubLen; ++nColumnIndex2)
1203 aMap[i + nRowIndex2][k + nColumnIndex2] = '\0';
1204 }
1205 }
1206 }
1207 // to be nice to the user we now sort the cell ranges according to
1208 // rows or columns depending on the direction used in the data source
1209 uno::Sequence< OUString > aSortedRanges;
1210 GetSubranges( aCellRanges, aSortedRanges, false /*sub ranges should already be normalized*/ );
1211 SortSubranges( aSortedRanges, (nDtaSrcIsColumns == 1) );
1212 OUString aSortedCellRanges;
1213 for (const OUString& rSortedRange : std::as_const(aSortedRanges))
1214 {
1215 if (!aSortedCellRanges.isEmpty())
1216 aSortedCellRanges += ";";
1217 aSortedCellRanges += rSortedRange;
1218 }
1219
1220 // build value for 'SequenceMapping'
1221
1222 uno::Sequence< sal_Int32 > aSortedMapping( aSequenceMapping );
1223 auto [begin, end] = asNonConstRange(aSortedMapping);
1224 std::sort(begin, end);
1225 bool bNeedSequenceMapping = false;
1226 for (sal_Int32 i = 0; i < aSequenceMapping.getLength(); ++i)
1227 {
1228 auto it = std::find( std::cbegin(aSortedMapping), std::cend(aSortedMapping),
1229 aSequenceMapping[i] );
1230 pSequenceMapping[i] = std::distance(std::cbegin(aSortedMapping), it);
1231
1232 if (i != std::as_const(aSequenceMapping)[i])
1233 bNeedSequenceMapping = true;
1234 }
1235
1236 // check if 'SequenceMapping' is actually not required...
1237 // (don't write unnecessary properties to the XML file)
1238 if (!bNeedSequenceMapping)
1239 aSequenceMapping.realloc(0);
1240
1241 // build resulting properties
1242
1243 OSL_ENSURE(nLabelSeqLen >= 0 || nLabelSeqLen == -2 /*not used*/,
1244 "unexpected value for 'nLabelSeqLen'" );
1245 bool bFirstCellIsLabel = false; // default value if 'nLabelSeqLen' could not properly determined
1246 if (nLabelSeqLen > 0) // == 0 means no label sequence in use
1247 bFirstCellIsLabel = true;
1248
1249 OSL_ENSURE( !aSortedCellRanges.isEmpty(), "CellRangeRepresentation missing" );
1250 const OUString aBrokenCellRangeForExport( GetBrokenCellRangeForExport( aSortedCellRanges ) );
1251
1252 aResult.realloc(5);
1253 auto pResult = aResult.getArray();
1254 sal_Int32 nProps = 0;
1255 pResult[nProps ].Name = "FirstCellAsLabel";
1256 pResult[nProps++].Value <<= bFirstCellIsLabel;
1257 pResult[nProps ].Name = "CellRangeRepresentation";
1258 pResult[nProps++].Value <<= aSortedCellRanges;
1259 if (!aBrokenCellRangeForExport.isEmpty())
1260 {
1261 pResult[nProps ].Name = "BrokenCellRangeForExport";
1262 pResult[nProps++].Value <<= aBrokenCellRangeForExport;
1263 }
1264 if (nDtaSrcIsColumns == 0 || nDtaSrcIsColumns == 1)
1265 {
1266 chart::ChartDataRowSource eDataRowSource = (nDtaSrcIsColumns == 1) ?
1267 chart::ChartDataRowSource_COLUMNS : chart::ChartDataRowSource_ROWS;
1268 pResult[nProps ].Name = "DataRowSource";
1269 pResult[nProps++].Value <<= eDataRowSource;
1270
1271 if (aSequenceMapping.hasElements())
1272 {
1273 pResult[nProps ].Name = "SequenceMapping";
1274 pResult[nProps++].Value <<= aSequenceMapping;
1275 }
1276 }
1277 aResult.realloc( nProps );
1278
1279 return aResult;
1280}
1281
1282uno::Reference< chart2::data::XDataSequence > SwChartDataProvider::Impl_createDataSequenceByRangeRepresentation(
1283 std::u16string_view rRangeRepresentation, bool bTestOnly )
1284{
1285 if (m_bDisposed)
1286 throw lang::DisposedException();
1287
1288 SwFrameFormat *pTableFormat = nullptr; // pointer to table format
1289 std::shared_ptr<SwUnoCursor> pUnoCursor; // pointer to new created cursor spanning the cell range
1290 GetFormatAndCreateCursorFromRangeRep( m_pDoc, rRangeRepresentation,
1291 &pTableFormat, pUnoCursor );
1292 if (!pTableFormat || !pUnoCursor)
1293 throw lang::IllegalArgumentException();
1294
1295 // check that cursors point and mark are in a single row or column.
1296 OUString aCellRange( GetCellRangeName( *pTableFormat, *pUnoCursor ) );
1297 SwRangeDescriptor aDesc;
1298 FillRangeDescriptor( aDesc, aCellRange );
1299 if (aDesc.nTop != aDesc.nBottom && aDesc.nLeft != aDesc.nRight)
1300 throw lang::IllegalArgumentException();
1301
1302 OSL_ENSURE( pTableFormat && pUnoCursor, "table format or cursor missing" );
1303 uno::Reference< chart2::data::XDataSequence > xDataSeq;
1304 if (!bTestOnly)
1305 xDataSeq = new SwChartDataSequence( *this, *pTableFormat, pUnoCursor );
1306
1307 return xDataSeq;
1308}
1309
1311 const OUString& rRangeRepresentation )
1312{
1313 SolarMutexGuard aGuard;
1314
1315 bool bPossible = true;
1316 try
1317 {
1318 Impl_createDataSequenceByRangeRepresentation( rRangeRepresentation, true );
1319 }
1320 catch (lang::IllegalArgumentException &)
1321 {
1322 bPossible = false;
1323 }
1324
1325 return bPossible;
1326}
1327
1328uno::Reference< chart2::data::XDataSequence > SAL_CALL SwChartDataProvider::createDataSequenceByRangeRepresentation(
1329 const OUString& rRangeRepresentation )
1330{
1331 SolarMutexGuard aGuard;
1332 return Impl_createDataSequenceByRangeRepresentation( rRangeRepresentation );
1333}
1334
1335uno::Reference< sheet::XRangeSelection > SAL_CALL SwChartDataProvider::getRangeSelection( )
1336{
1337 // note: it is no error to return nothing here
1338 return uno::Reference< sheet::XRangeSelection >();
1339}
1340
1341uno::Reference<css::chart2::data::XDataSequence> SAL_CALL
1343 const OUString& /*aRole*/, const OUString& /*aRangeRepresentation*/,
1344 const OUString& /*aRoleQualifier*/ )
1345{
1346 return uno::Reference<css::chart2::data::XDataSequence>();
1347}
1348
1350{
1351 bool bMustDispose( false );
1352 {
1353 std::unique_lock aGuard( GetChartMutex() );
1354 bMustDispose = !m_bDisposed;
1355 if (!m_bDisposed)
1356 m_bDisposed = true;
1357 }
1358 if (!bMustDispose)
1359 return;
1360
1361 // dispose all data-sequences
1362 for (const auto& rEntry : m_aDataSequences)
1363 {
1364 DisposeAllDataSequences( rEntry.first );
1365 }
1366 // release all references to data-sequences
1367 m_aDataSequences.clear();
1368
1369 // require listeners to release references to this object
1370 lang::EventObject aEvtObj( static_cast< chart2::data::XDataProvider * >(this) );
1371 std::unique_lock aGuard( GetChartMutex() );
1372 m_aEventListeners.disposeAndClear( aGuard, aEvtObj );
1373}
1374
1376 const uno::Reference< lang::XEventListener >& rxListener )
1377{
1378 std::unique_lock aGuard( GetChartMutex() );
1379 if (!m_bDisposed && rxListener.is())
1380 m_aEventListeners.addInterface( aGuard, rxListener );
1381}
1382
1384 const uno::Reference< lang::XEventListener >& rxListener )
1385{
1386 std::unique_lock aGuard( GetChartMutex() );
1387 if (!m_bDisposed && rxListener.is())
1388 m_aEventListeners.removeInterface( aGuard, rxListener );
1389}
1390
1392{
1393 return "SwChartDataProvider";
1394}
1395
1396sal_Bool SAL_CALL SwChartDataProvider::supportsService(const OUString& rServiceName )
1397{
1398 return cppu::supportsService(this, rServiceName);
1399}
1400
1401uno::Sequence< OUString > SAL_CALL SwChartDataProvider::getSupportedServiceNames( )
1402{
1403 return { "com.sun.star.chart2.data.DataProvider"};
1404}
1405
1407{
1408 Vec_DataSequenceRef_t& rVec = m_aDataSequences[ &rTable ];
1409 assert(std::find_if(rVec.begin(), rVec.end(),
1410 [&rxDataSequence](const unotools::WeakReference < SwChartDataSequence >& i)
1411 {
1412 return i.get() == rxDataSequence;
1413 }) == rVec.end() && "duplicate insert");
1414 rVec.push_back( rxDataSequence );
1415}
1416
1418{
1419 Vec_DataSequenceRef_t& rVec = m_aDataSequences[ &rTable ];
1420 rVec.erase( std::remove_if(rVec.begin(), rVec.end(),
1421 [&rxDataSequence](const unotools::WeakReference < SwChartDataSequence >& i)
1422 {
1423 return i.get() == rxDataSequence;
1424 }), rVec.end());
1425}
1426
1427void SwChartDataProvider::InvalidateTable( const SwTable *pTable, bool bImmediate )
1428{
1429 OSL_ENSURE( pTable, "table pointer is NULL" );
1430 if (!pTable)
1431 return;
1432
1433 if (!m_bDisposed)
1435
1436 const Vec_DataSequenceRef_t &rVec = m_aDataSequences[ pTable ];
1437 for (const unotools::WeakReference<SwChartDataSequence>& rItem : rVec)
1438 {
1440 if (xRef.is())
1441 {
1442 // mark the sequence as 'dirty' and notify listeners
1443 xRef->setModified( true );
1444 }
1445 }
1446
1447 // tdf#122995 added Immediate-mode to allow non-timer-delayed Chart invalidation
1448 if (bImmediate && !m_bDisposed)
1450}
1451
1452void SwChartDataProvider::DeleteBox( const SwTable *pTable, const SwTableBox &rBox )
1453{
1454 OSL_ENSURE( pTable, "table pointer is NULL" );
1455 if (!pTable)
1456 return;
1457
1458 if (!m_bDisposed)
1460
1461 Vec_DataSequenceRef_t &rVec = m_aDataSequences[ pTable ];
1462
1463 // iterate over all data-sequences for that table...
1464 auto aIt( rVec.begin() );
1465 while (aIt != rVec.end())
1466 {
1467 bool bNowEmpty = false;
1468 bool bSeqDisposed = false;
1469
1470 // check if weak reference is still valid...
1472 if (pDataSeq.is())
1473 {
1474 // then delete that table box (check if implementation cursor needs to be adjusted)
1475 try
1476 {
1477 bNowEmpty = pDataSeq->DeleteBox( rBox );
1478 }
1479 catch (const lang::DisposedException&)
1480 {
1481 bNowEmpty = true;
1482 bSeqDisposed = true;
1483 }
1484 }
1485
1486 if (bNowEmpty)
1487 {
1488 aIt = rVec.erase( aIt );
1489 if (pDataSeq && !bSeqDisposed)
1490 pDataSeq->dispose(); // the current way to tell chart that sth. got removed
1491 }
1492 else
1493 ++aIt;
1494 }
1495}
1496
1498{
1499 OSL_ENSURE( pTable, "table pointer is NULL" );
1500 if (!pTable)
1501 return;
1502
1503 if (!m_bDisposed)
1505
1510 const Vec_DataSequenceRef_t aVec( m_aDataSequences[ pTable ] );
1511
1512 for (const unotools::WeakReference<SwChartDataSequence>& rItem : aVec)
1513 {
1515 if (xRef.is())
1516 {
1517 xRef->dispose();
1518 }
1519 }
1520}
1521
1544 const SwTable &rTable,
1545 const SwSelBoxes& rBoxes,
1546 sal_uInt16 nLines, bool bBehind )
1547{
1548 if (rTable.IsTableComplex())
1549 return;
1550
1551 const size_t nBoxes = rBoxes.size();
1552 if (nBoxes < 1 || nLines < 1)
1553 return;
1554
1555 SwTableBox* pFirstBox = rBoxes[0];
1556 SwTableBox* pLastBox = rBoxes.back();
1557
1558 if (!(pFirstBox && pLastBox))
1559 return;
1560
1561 sal_Int32 nFirstCol = -1, nFirstRow = -1, nLastCol = -1, nLastRow = -1;
1562 SwXTextTable::GetCellPosition( pFirstBox->GetName(), nFirstCol, nFirstRow );
1563 SwXTextTable::GetCellPosition( pLastBox->GetName(), nLastCol, nLastRow );
1564
1565 bool bAddCols = false; // default; also to be used if nBoxes == 1 :-/
1566 if (nFirstCol == nLastCol && nFirstRow != nLastRow)
1567 bAddCols = true;
1568 if (nFirstCol != nLastCol && nFirstRow != nLastRow)
1569 return;
1570
1571 //get range of indices in col/rows for new cells
1572 sal_Int32 nFirstNewCol = nFirstCol;
1573 sal_Int32 nFirstNewRow = bBehind ? nFirstRow + 1 : nFirstRow - nLines;
1574 if (bAddCols)
1575 {
1576 OSL_ENSURE( nFirstCol == nLastCol, "column indices seem broken" );
1577 nFirstNewCol = bBehind ? nFirstCol + 1 : nFirstCol - nLines;
1578 nFirstNewRow = nFirstRow;
1579 }
1580
1581 // iterate over all data-sequences for the table
1582 const Vec_DataSequenceRef_t &rVec = m_aDataSequences[ &rTable ];
1583 for (const unotools::WeakReference<SwChartDataSequence>& rItem : rVec)
1584 {
1586 if (pDataSeq.is())
1587 {
1588 const sal_Int32 nLen = pDataSeq->getTextualData().getLength();
1589 if (nLen > 1) // value data-sequence ?
1590 {
1591 SwRangeDescriptor aDesc;
1592 pDataSeq->FillRangeDesc( aDesc );
1593
1594 chart::ChartDataRowSource eDRSource = chart::ChartDataRowSource_COLUMNS;
1595 if (aDesc.nTop == aDesc.nBottom && aDesc.nLeft != aDesc.nRight)
1596 eDRSource = chart::ChartDataRowSource_ROWS;
1597
1598 if (!bAddCols && eDRSource == chart::ChartDataRowSource_COLUMNS)
1599 {
1600 // add rows: extend affected columns by newly added row cells
1601 pDataSeq->ExtendTo( true, nFirstNewRow, nLines );
1602 }
1603 else if (bAddCols && eDRSource == chart::ChartDataRowSource_ROWS)
1604 {
1605 // add cols: extend affected rows by newly added column cells
1606 pDataSeq->ExtendTo( false, nFirstNewCol, nLines );
1607 }
1608 }
1609 }
1610 }
1611}
1612
1613// XRangeXMLConversion
1614OUString SAL_CALL SwChartDataProvider::convertRangeToXML( const OUString& rRangeRepresentation )
1615{
1616 SolarMutexGuard aGuard;
1617 if (m_bDisposed)
1618 throw lang::DisposedException();
1619
1620 if (rRangeRepresentation.isEmpty())
1621 return OUString();
1622
1623 OUStringBuffer aRes;
1624
1625 // multiple ranges are delimited by a ';' like in
1626 // "Table1.A1:A4;Table1.C2:C5" the same table must be used in all ranges!
1627 SwTable* pFirstFoundTable = nullptr; // to check that only one table will be used
1628 sal_Int32 nPos = 0;
1629 do {
1630 const OUString aRange( rRangeRepresentation.getToken(0, ';', nPos) );
1631 SwFrameFormat *pTableFormat = nullptr; // pointer to table format
1632 std::shared_ptr<SwUnoCursor> pCursor;
1633 GetFormatAndCreateCursorFromRangeRep( m_pDoc, aRange, &pTableFormat, pCursor );
1634 if (!pTableFormat)
1635 throw lang::IllegalArgumentException();
1636 SwTable* pTable = SwTable::FindTable( pTableFormat );
1637 if (pTable->IsTableComplex())
1638 throw uno::RuntimeException("Table too complex.");
1639
1640 // check that there is only one table used in all ranges
1641 if (!pFirstFoundTable)
1642 pFirstFoundTable = pTable;
1643 if (pTable != pFirstFoundTable)
1644 throw lang::IllegalArgumentException();
1645
1646 OUString aTableName;
1647 OUString aStartCell;
1648 OUString aEndCell;
1649 if (!GetTableAndCellsFromRangeRep( aRange, aTableName, aStartCell, aEndCell ))
1650 throw lang::IllegalArgumentException();
1651
1652 sal_Int32 nCol, nRow;
1653 SwXTextTable::GetCellPosition( aStartCell, nCol, nRow );
1654 if (nCol < 0 || nRow < 0)
1655 throw uno::RuntimeException("Cell not found.");
1656
1659 XMLRangeHelper::CellRange aCellRange;
1660 aCellRange.aTableName = aTableName;
1661 aCellRange.aUpperLeft.nColumn = nCol;
1662 aCellRange.aUpperLeft.nRow = nRow;
1663 aCellRange.aUpperLeft.bIsEmpty = false;
1664 if (aStartCell != aEndCell && !aEndCell.isEmpty())
1665 {
1666 SwXTextTable::GetCellPosition( aEndCell, nCol, nRow );
1667 if (nCol < 0 || nRow < 0)
1668 throw uno::RuntimeException("Cell not found.");
1669
1670 aCellRange.aLowerRight.nColumn = nCol;
1671 aCellRange.aLowerRight.nRow = nRow;
1672 aCellRange.aLowerRight.bIsEmpty = false;
1673 }
1674 OUString aTmp( XMLRangeHelper::getXMLStringFromCellRange( aCellRange ) );
1675 if (!aRes.isEmpty()) // in case of multiple ranges add delimiter
1676 aRes.append(" ");
1677 aRes.append(aTmp);
1678 }
1679 while (nPos>0);
1680
1681 return aRes.makeStringAndClear();
1682}
1683
1684OUString SAL_CALL SwChartDataProvider::convertRangeFromXML( const OUString& rXMLRange )
1685{
1686 SolarMutexGuard aGuard;
1687 if (m_bDisposed)
1688 throw lang::DisposedException();
1689
1690 if (rXMLRange.isEmpty())
1691 return OUString();
1692
1693 OUStringBuffer aRes;
1694
1695 // multiple ranges are delimited by a ' ' like in
1696 // "Table1.$A$1:.$A$4 Table1.$C$2:.$C$5" the same table must be used in all ranges!
1697 OUString aFirstFoundTable; // to check that only one table will be used
1698 sal_Int32 nPos = 0;
1699 do
1700 {
1701 OUString aRange( rXMLRange.getToken(0, ' ', nPos) );
1702
1706
1707 // check that there is only one table used in all ranges
1708 if (aFirstFoundTable.isEmpty())
1709 aFirstFoundTable = aCellRange.aTableName;
1710 if (aCellRange.aTableName != aFirstFoundTable)
1711 throw lang::IllegalArgumentException();
1712
1713 OUString aTmp = aCellRange.aTableName + "." +
1714 sw_GetCellName( aCellRange.aUpperLeft.nColumn,
1715 aCellRange.aUpperLeft.nRow );
1716 // does cell range consist of more than a single cell?
1717 if (!aCellRange.aLowerRight.bIsEmpty)
1718 {
1719 aTmp += ":" + sw_GetCellName( aCellRange.aLowerRight.nColumn,
1720 aCellRange.aLowerRight.nRow );
1721 }
1722
1723 if (!aRes.isEmpty()) // in case of multiple ranges add delimiter
1724 aRes.append(";");
1725 aRes.append(aTmp);
1726 }
1727 while (nPos>0);
1728
1729 return aRes.makeStringAndClear();
1730}
1731
1733 const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > &rLDS ) :
1734 m_aLDS( rLDS )
1735{
1736}
1737
1739{
1740}
1741
1742uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > SAL_CALL SwChartDataSource::getDataSequences( )
1743{
1744 SolarMutexGuard aGuard;
1745 return m_aLDS;
1746}
1747
1749{
1750 return "SwChartDataSource";
1751}
1752
1753sal_Bool SAL_CALL SwChartDataSource::supportsService(const OUString& rServiceName )
1754{
1755 return cppu::supportsService(this, rServiceName);
1756}
1757
1758uno::Sequence< OUString > SAL_CALL SwChartDataSource::getSupportedServiceNames( )
1759{
1760 return { "com.sun.star.chart2.data.DataSource" };
1761}
1762
1764 SwChartDataProvider& rProvider,
1765 SwFrameFormat& rTableFormat,
1766 const std::shared_ptr<SwUnoCursor>& pTableCursor ) :
1767 m_pFormat(&rTableFormat),
1768 m_aRowLabelText( SwResId( STR_CHART2_ROW_LABEL_TEXT ) ),
1769 m_aColLabelText( SwResId( STR_CHART2_COL_LABEL_TEXT ) ),
1770 m_xDataProvider( &rProvider ),
1771 m_pTableCursor( pTableCursor ),
1772 m_pPropSet( aSwMapProvider.GetPropertySet( PROPERTY_MAP_CHART2_DATA_SEQUENCE ) )
1773{
1774 StartListening(rTableFormat.GetNotifier());
1775 m_bDisposed = false;
1776
1777 acquire();
1778 try
1779 {
1780 const SwTable* pTable = SwTable::FindTable( &rTableFormat );
1781 if (pTable)
1782 {
1783 m_xDataProvider->AddDataSequence( *pTable, this );
1784 m_xDataProvider->addEventListener( static_cast< lang::XEventListener * >(this) );
1785 }
1786 else {
1787 OSL_FAIL( "table missing" );
1788 }
1789 }
1790 catch (uno::RuntimeException &)
1791 {
1792 // TODO: shouldn't there be a call to release() here?
1793 throw;
1794 }
1795 catch (uno::Exception &)
1796 {
1797 }
1798 release();
1799
1800#if OSL_DEBUG_LEVEL > 0
1801 // check if it can properly convert into a SwUnoTableCursor
1802 // which is required for some functions
1803 SwUnoTableCursor* pUnoTableCursor = dynamic_cast<SwUnoTableCursor*>(&(*m_pTableCursor));
1804 OSL_ENSURE(pUnoTableCursor, "SwChartDataSequence: cursor not SwUnoTableCursor");
1805#endif
1806}
1807
1810 SvtListener(),
1811 m_pFormat( rObj.m_pFormat ),
1812 m_aRole( rObj.m_aRole ),
1813 m_aRowLabelText( SwResId(STR_CHART2_ROW_LABEL_TEXT) ),
1814 m_aColLabelText( SwResId(STR_CHART2_COL_LABEL_TEXT) ),
1815 m_xDataProvider( rObj.m_xDataProvider ),
1816 m_pTableCursor( rObj.m_pTableCursor ),
1817 m_pPropSet( rObj.m_pPropSet )
1818{
1819 if(m_pFormat)
1820 StartListening(m_pFormat->GetNotifier());
1821 m_bDisposed = false;
1822
1823 acquire();
1824 try
1825 {
1826 const SwTable* pTable = SwTable::FindTable( GetFrameFormat() );
1827 if (pTable)
1828 {
1829 m_xDataProvider->AddDataSequence( *pTable, this );
1830 m_xDataProvider->addEventListener( static_cast< lang::XEventListener * >(this) );
1831 }
1832 else {
1833 OSL_FAIL( "table missing" );
1834 }
1835 }
1836 catch (uno::RuntimeException &)
1837 {
1838 // TODO: shouldn't there be a call to release() here?
1839 throw;
1840 }
1841 catch (uno::Exception &)
1842 {
1843 }
1844 release();
1845
1846#if OSL_DEBUG_LEVEL > 0
1847 // check if it can properly convert into a SwUnoTableCursor
1848 // which is required for some functions
1849 SwUnoTableCursor* pUnoTableCursor = dynamic_cast<SwUnoTableCursor*>(&(*m_pTableCursor));
1850 OSL_ENSURE(pUnoTableCursor, "SwChartDataSequence: cursor not SwUnoTableCursor");
1851#endif
1852}
1853
1855{
1856}
1857
1859{
1860 SolarMutexGuard aGuard;
1861 if (m_bDisposed)
1862 throw lang::DisposedException();
1863
1864 OUString aRes;
1865 SwFrameFormat* pTableFormat = GetFrameFormat();
1866 if (pTableFormat)
1867 {
1868 const OUString aCellRange( GetCellRangeName( *pTableFormat, *m_pTableCursor ) );
1869 OSL_ENSURE( !aCellRange.isEmpty(), "failed to get cell range" );
1870 aRes = pTableFormat->GetName() + "." + aCellRange;
1871 }
1872 return aRes;
1873}
1874
1875uno::Sequence< OUString > SAL_CALL SwChartDataSequence::generateLabel(
1876 chart2::data::LabelOrigin eLabelOrigin )
1877{
1878 SolarMutexGuard aGuard;
1879 if (m_bDisposed)
1880 throw lang::DisposedException();
1881
1882 uno::Sequence< OUString > aLabels;
1883
1884 {
1885 SwRangeDescriptor aDesc;
1886 bool bOk = false;
1887 SwFrameFormat* pTableFormat = GetFrameFormat();
1888 if (!pTableFormat)
1889 throw uno::RuntimeException("No table format found.");
1890 SwTable* pTable = SwTable::FindTable( pTableFormat );
1891 if (!pTable)
1892 throw uno::RuntimeException("No table found.");
1893 if (pTable->IsTableComplex())
1894 throw uno::RuntimeException("Table too complex.");
1895
1896 const OUString aCellRange( GetCellRangeName( *pTableFormat, *m_pTableCursor ) );
1897 OSL_ENSURE( !aCellRange.isEmpty(), "failed to get cell range" );
1898 bOk = FillRangeDescriptor( aDesc, aCellRange );
1899 OSL_ENSURE( bOk, "failed to get SwRangeDescriptor" );
1900
1901 if (bOk)
1902 {
1903 aDesc.Normalize();
1904 sal_Int32 nColSpan = aDesc.nRight - aDesc.nLeft + 1;
1905 sal_Int32 nRowSpan = aDesc.nBottom - aDesc.nTop + 1;
1906 OSL_ENSURE( nColSpan == 1 || nRowSpan == 1,
1907 "unexpected range of selected cells" );
1908
1909 OUString aText; // label text to be returned
1910 bool bReturnEmptyText = false;
1911 bool bUseCol = true;
1912 if (eLabelOrigin == chart2::data::LabelOrigin_COLUMN)
1913 bUseCol = true;
1914 else if (eLabelOrigin == chart2::data::LabelOrigin_ROW)
1915 bUseCol = false;
1916 else if (eLabelOrigin == chart2::data::LabelOrigin_SHORT_SIDE)
1917 {
1918 bUseCol = nColSpan < nRowSpan;
1919 bReturnEmptyText = nColSpan == nRowSpan;
1920 }
1921 else if (eLabelOrigin == chart2::data::LabelOrigin_LONG_SIDE)
1922 {
1923 bUseCol = nColSpan > nRowSpan;
1924 bReturnEmptyText = nColSpan == nRowSpan;
1925 }
1926 else {
1927 OSL_FAIL( "unexpected case" );
1928 }
1929
1930 // build label sequence
1931
1932 sal_Int32 nSeqLen = bUseCol ? nColSpan : nRowSpan;
1933 aLabels.realloc( nSeqLen );
1934 OUString *pLabels = aLabels.getArray();
1935 for (sal_Int32 i = 0; i < nSeqLen; ++i)
1936 {
1937 if (!bReturnEmptyText)
1938 {
1939 aText = bUseCol ? m_aColLabelText : m_aRowLabelText;
1940 sal_Int32 nCol = aDesc.nLeft;
1941 sal_Int32 nRow = aDesc.nTop;
1942 if (bUseCol)
1943 nCol = nCol + i;
1944 else
1945 nRow = nRow + i;
1946 OUString aCellName( sw_GetCellName( nCol, nRow ) );
1947
1948 sal_Int32 nLen = aCellName.getLength();
1949 if (nLen)
1950 {
1951 const sal_Unicode *pBuf = aCellName.getStr();
1952 const sal_Unicode *pEnd = pBuf + nLen;
1953 while (pBuf < pEnd && ('0' > *pBuf || *pBuf > '9'))
1954 ++pBuf;
1955 // start of number found?
1956 if (pBuf < pEnd && ('0' <= *pBuf && *pBuf <= '9'))
1957 {
1958 OUString aRplc;
1959 std::u16string_view aNew;
1960 if (bUseCol)
1961 {
1962 aRplc = "%COLUMNLETTER";
1963 aNew = aCellName.subView(0, pBuf - aCellName.getStr());
1964 }
1965 else
1966 {
1967 aRplc = "%ROWNUMBER";
1968 aNew = std::u16string_view(pBuf, (aCellName.getStr() + nLen) - pBuf);
1969 }
1970 aText = aText.replaceFirst( aRplc, aNew );
1971 }
1972 }
1973 }
1974 pLabels[i] = aText;
1975 }
1976 }
1977 }
1978
1979 return aLabels;
1980}
1981
1983 ::sal_Int32 /*nIndex*/ )
1984{
1985 return 0;
1986}
1987
1988std::vector< css::uno::Reference< css::table::XCell > > SwChartDataSequence::GetCells()
1989{
1990 if (m_bDisposed)
1991 throw lang::DisposedException();
1992 auto pTableFormat(GetFrameFormat());
1993 if(!pTableFormat)
1994 return std::vector< css::uno::Reference< css::table::XCell > >();
1995 auto pTable(SwTable::FindTable(pTableFormat));
1996 if(pTable->IsTableComplex())
1997 return std::vector< css::uno::Reference< css::table::XCell > >();
1998 SwRangeDescriptor aDesc;
1999 if(!FillRangeDescriptor(aDesc, GetCellRangeName(*pTableFormat, *m_pTableCursor)))
2000 return std::vector< css::uno::Reference< css::table::XCell > >();
2001 return SwXCellRange::CreateXCellRange(m_pTableCursor, *pTableFormat, aDesc)->GetCells();
2002}
2003
2004uno::Sequence< OUString > SAL_CALL SwChartDataSequence::getTextualData()
2005{
2006 SolarMutexGuard aGuard;
2007 auto vCells(GetCells());
2008 uno::Sequence< OUString > vTextData(vCells.size());
2009 std::transform(vCells.begin(),
2010 vCells.end(),
2011 vTextData.getArray(),
2012 [] (decltype(vCells)::value_type& xCell)
2013 { return static_cast<SwXCell*>(xCell.get())->getString(); });
2014 return vTextData;
2015}
2016
2017uno::Sequence< uno::Any > SAL_CALL SwChartDataSequence::getData()
2018{
2019 SolarMutexGuard aGuard;
2020 auto vCells(GetCells());
2021 uno::Sequence< uno::Any > vAnyData(vCells.size());
2022 std::transform(vCells.begin(),
2023 vCells.end(),
2024 vAnyData.getArray(),
2025 [] (decltype(vCells)::value_type& xCell)
2026 { return static_cast<SwXCell*>(xCell.get())->GetAny(); });
2027 return vAnyData;
2028}
2029
2030uno::Sequence< double > SAL_CALL SwChartDataSequence::getNumericalData()
2031{
2032 SolarMutexGuard aGuard;
2033 auto vCells(GetCells());
2034 uno::Sequence< double > vNumData(vCells.size());
2035 std::transform(vCells.begin(),
2036 vCells.end(),
2037 vNumData.getArray(),
2038 [] (decltype(vCells)::value_type& xCell)
2039 { return static_cast<SwXCell*>(xCell.get())->GetForcedNumericalValue(); });
2040 return vNumData;
2041}
2042
2043uno::Reference< util::XCloneable > SAL_CALL SwChartDataSequence::createClone( )
2044{
2045 SolarMutexGuard aGuard;
2046 if (m_bDisposed)
2047 throw lang::DisposedException();
2048 return new SwChartDataSequence( *this );
2049}
2050
2051uno::Reference< beans::XPropertySetInfo > SAL_CALL SwChartDataSequence::getPropertySetInfo( )
2052{
2053 SolarMutexGuard aGuard;
2054 if (m_bDisposed)
2055 throw lang::DisposedException();
2056
2057 static uno::Reference< beans::XPropertySetInfo > xRes = m_pPropSet->getPropertySetInfo();
2058 return xRes;
2059}
2060
2062 const OUString& rPropertyName,
2063 const uno::Any& rValue )
2064{
2065 SolarMutexGuard aGuard;
2066 if (m_bDisposed)
2067 throw lang::DisposedException();
2068
2069 if (rPropertyName != UNO_NAME_ROLE)
2070 throw beans::UnknownPropertyException(rPropertyName);
2071
2072 if ( !(rValue >>= m_aRole) )
2073 throw lang::IllegalArgumentException();
2074}
2075
2077 const OUString& rPropertyName )
2078{
2079 SolarMutexGuard aGuard;
2080 if (m_bDisposed)
2081 throw lang::DisposedException();
2082
2083 if (!(rPropertyName == UNO_NAME_ROLE))
2084 throw beans::UnknownPropertyException(rPropertyName);
2085
2086 return uno::Any(m_aRole);
2087}
2088
2090 const OUString& /*rPropertyName*/,
2091 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
2092{
2093 OSL_FAIL( "not implemented" );
2094}
2095
2097 const OUString& /*rPropertyName*/,
2098 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
2099{
2100 OSL_FAIL( "not implemented" );
2101}
2102
2104 const OUString& /*rPropertyName*/,
2105 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/ )
2106{
2107 OSL_FAIL( "not implemented" );
2108}
2109
2111 const OUString& /*rPropertyName*/,
2112 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/ )
2113{
2114 OSL_FAIL( "not implemented" );
2115}
2116
2118{
2119 return "SwChartDataSequence";
2120}
2121
2122sal_Bool SAL_CALL SwChartDataSequence::supportsService(const OUString& rServiceName )
2123{
2124 return cppu::supportsService(this, rServiceName);
2125}
2126
2127uno::Sequence< OUString > SAL_CALL SwChartDataSequence::getSupportedServiceNames( )
2128{
2129 return { "com.sun.star.chart2.data.DataSequence" };
2130}
2131
2133{
2134 if(rHint.GetId() == SfxHintId::Dying)
2135 m_pFormat = nullptr;
2136 if(!m_pFormat || !m_pTableCursor)
2137 {
2138 m_pFormat = nullptr;
2139 m_pTableCursor.reset(nullptr);
2140 dispose();
2141 }
2142 else if (rHint.GetId() == SfxHintId::SwLegacyModify)
2143 {
2144 setModified( true );
2145 }
2146}
2147
2149{
2150 SolarMutexGuard aGuard;
2151 if (m_bDisposed)
2152 throw lang::DisposedException();
2153
2154 return true;
2155}
2156
2158 sal_Bool bModified )
2159{
2160 SolarMutexGuard aGuard;
2161 if (m_bDisposed)
2162 throw lang::DisposedException();
2163
2164 if (bModified)
2165 LaunchModifiedEvent( m_aModifyListeners, static_cast< XModifyBroadcaster * >(this) );
2166}
2167
2169 const uno::Reference< util::XModifyListener >& rxListener )
2170{
2171 std::unique_lock aGuard( GetChartMutex() );
2172 if (!m_bDisposed && rxListener.is())
2173 m_aModifyListeners.addInterface( aGuard, rxListener );
2174}
2175
2177 const uno::Reference< util::XModifyListener >& rxListener )
2178{
2179 std::unique_lock aGuard( GetChartMutex() );
2180 if (!m_bDisposed && rxListener.is())
2181 m_aModifyListeners.removeInterface( aGuard, rxListener );
2182}
2183
2184void SAL_CALL SwChartDataSequence::disposing( const lang::EventObject& rSource )
2185{
2186 if (m_bDisposed)
2187 throw lang::DisposedException();
2188 if (rSource.Source == static_cast<cppu::OWeakObject*>(m_xDataProvider.get()))
2189 {
2190 m_xDataProvider.clear();
2191 }
2192}
2193
2195{
2196 bool bMustDispose( false );
2197 {
2198 std::unique_lock aGuard( GetChartMutex() );
2199 bMustDispose = !m_bDisposed;
2200 if (!m_bDisposed)
2201 m_bDisposed = true;
2202 }
2203 if (!bMustDispose)
2204 return;
2205
2206 m_bDisposed = true;
2207 if (m_xDataProvider.is())
2208 {
2209 const SwTable* pTable = SwTable::FindTable( GetFrameFormat() );
2210 if (pTable)
2211 {
2212 m_xDataProvider->RemoveDataSequence( *pTable, this );
2213 }
2214 else {
2215 OSL_FAIL( "table missing" );
2216 }
2217
2218 //#i119653# The bug is crashed for an exception thrown by
2219 //SwCharDataSequence::setModified() because
2220 //the SwCharDataSequence object has been disposed.
2221
2222 //Actually, the former design of SwClient will disconnect itself
2223 //from the notification list in its destructor.
2224
2225 //But the SwCharDataSequence won't be destructed but disposed in code
2226 //(the data member SwChartDataSequence::bDisposed will be set to
2227 //TRUE), the relationship between client and modification is not
2228 //released.
2229
2230 //So any notification from modify object will lead to said
2231 //exception threw out. Recorrect the logic of code in
2232 //SwChartDataSequence::Dispose(), release the relationship
2233 //here...
2234 if (m_pFormat && m_pFormat->HasWriterListeners())
2235 {
2237 m_pFormat = nullptr;
2238 m_pTableCursor.reset(nullptr);
2239 }
2240 }
2241
2242 // require listeners to release references to this object
2243 lang::EventObject aEvtObj( static_cast< chart2::data::XDataSequence * >(this) );
2244 std::unique_lock aGuard( GetChartMutex() );
2245 m_aModifyListeners.disposeAndClear( aGuard, aEvtObj );
2246 m_aEvtListeners.disposeAndClear( aGuard, aEvtObj );
2247}
2248
2250 const uno::Reference< lang::XEventListener >& rxListener )
2251{
2252 std::unique_lock aGuard( GetChartMutex() );
2253 if (!m_bDisposed && rxListener.is())
2254 m_aEvtListeners.addInterface( aGuard, rxListener );
2255}
2256
2258 const uno::Reference< lang::XEventListener >& rxListener )
2259{
2260 std::unique_lock aGuard( GetChartMutex() );
2261 if (!m_bDisposed && rxListener.is())
2262 m_aEvtListeners.removeInterface( aGuard, rxListener );
2263}
2264
2266{
2267 if (m_bDisposed)
2268 throw lang::DisposedException();
2269
2270 // to be set if the last box of the data-sequence was removed here
2271 bool bNowEmpty = false;
2272
2273 // if the implementation cursor gets affected (i.e. the box where it is located
2274 // in gets removed) we need to move it before that... (otherwise it does not need to change)
2275
2276 const SwStartNode* pPointStartNode = m_pTableCursor->GetPoint()->GetNode().FindTableBoxStartNode();
2277 const SwStartNode* pMarkStartNode = m_pTableCursor->GetMark()->GetNode().FindTableBoxStartNode();
2278
2279 if (!m_pTableCursor->HasMark() || (pPointStartNode == rBox.GetSttNd() && pMarkStartNode == rBox.GetSttNd()))
2280 {
2281 bNowEmpty = true;
2282 }
2283 else if (pPointStartNode == rBox.GetSttNd() || pMarkStartNode == rBox.GetSttNd())
2284 {
2285 sal_Int32 nPointRow = -1, nPointCol = -1;
2286 sal_Int32 nMarkRow = -1, nMarkCol = -1;
2287 const SwTable* pTable = SwTable::FindTable( GetFrameFormat() );
2288 OUString aPointCellName( pTable->GetTableBox( pPointStartNode->GetIndex() )->GetName() );
2289 OUString aMarkCellName( pTable->GetTableBox( pMarkStartNode->GetIndex() )->GetName() );
2290
2291 SwXTextTable::GetCellPosition( aPointCellName, nPointCol, nPointRow );
2292 SwXTextTable::GetCellPosition( aMarkCellName, nMarkCol, nMarkRow );
2293 OSL_ENSURE( nPointRow >= 0 && nPointCol >= 0, "invalid row and col" );
2294 OSL_ENSURE( nMarkRow >= 0 && nMarkCol >= 0, "invalid row and col" );
2295
2296 // move vertical or horizontal?
2297 OSL_ENSURE( nPointRow == nMarkRow || nPointCol == nMarkCol,
2298 "row/col indices not matching" );
2299 OSL_ENSURE( nPointRow != nMarkRow || nPointCol != nMarkCol,
2300 "point and mark are identical" );
2301 bool bMoveVertical = (nPointCol == nMarkCol);
2302 bool bMoveHorizontal = (nPointRow == nMarkRow);
2303
2304 // get movement direction
2305 bool bMoveLeft = false; // move left or right?
2306 bool bMoveUp = false; // move up or down?
2307 if (bMoveVertical)
2308 {
2309 if (pPointStartNode == rBox.GetSttNd()) // move point?
2310 bMoveUp = nPointRow > nMarkRow;
2311 else // move mark
2312 bMoveUp = nMarkRow > nPointRow;
2313 }
2314 else if (bMoveHorizontal)
2315 {
2316 if (pPointStartNode == rBox.GetSttNd()) // move point?
2317 bMoveLeft = nPointCol > nMarkCol;
2318 else // move mark
2319 bMoveLeft = nMarkCol > nPointCol;
2320 }
2321 else {
2322 OSL_FAIL( "neither vertical nor horizontal movement" );
2323 }
2324
2325 // get new box (position) to use...
2326 sal_Int32 nRow = (pPointStartNode == rBox.GetSttNd()) ? nPointRow : nMarkRow;
2327 sal_Int32 nCol = (pPointStartNode == rBox.GetSttNd()) ? nPointCol : nMarkCol;
2328 if (bMoveVertical)
2329 nRow += bMoveUp ? -1 : +1;
2330 if (bMoveHorizontal)
2331 nCol += bMoveLeft ? -1 : +1;
2332 const OUString aNewCellName = sw_GetCellName( nCol, nRow );
2333 SwTableBox* pNewBox = const_cast<SwTableBox*>(pTable->GetTableBox( aNewCellName ));
2334
2335 if (pNewBox) // set new position (cell range) to use
2336 {
2337 // This is how you get the first content node of a row:
2338 // First get a SwNodeIndex pointing to the node after SwStartNode of the box...
2339 SwNodeIndex aIdx( *pNewBox->GetSttNd(), +1 );
2340 // This can be a SwContentNode, but might also be a table or section node,
2341 // therefore call GoNext
2342 SwContentNode *pCNd = aIdx.GetNode().GetContentNode();
2343 if (!pCNd)
2344 pCNd = GetFrameFormat()->GetDoc()->GetNodes().GoNext( &aIdx );
2345 // and then one can e.g. create a SwPosition:
2346 SwPosition aNewPos( *pCNd ); // new position to be used with cursor
2347
2348 // if the mark is to be changed, make sure there is one
2349 if (pMarkStartNode == rBox.GetSttNd() && !m_pTableCursor->HasMark())
2351
2352 // set cursor to new position
2353 SwPosition *pPos = (pPointStartNode == rBox.GetSttNd()) ?
2355 if (pPos)
2356 {
2357 *pPos = aNewPos;
2358 }
2359 else {
2360 OSL_FAIL( "neither point nor mark available for change" );
2361 }
2362 }
2363 else {
2364 OSL_FAIL( "failed to get position" );
2365 }
2366 }
2367
2368 return bNowEmpty;
2369}
2370
2372{
2373 SwFrameFormat* pTableFormat = GetFrameFormat();
2374 if(pTableFormat)
2375 {
2376 SwTable* pTable = SwTable::FindTable( pTableFormat );
2377 if(!pTable->IsTableComplex())
2378 {
2379 FillRangeDescriptor( rRangeDesc, GetCellRangeName( *pTableFormat, *m_pTableCursor ) );
2380 }
2381 }
2382}
2383
2398void SwChartDataSequence::ExtendTo( bool bExtendCol,
2399 sal_Int32 nFirstNew, sal_Int32 nCount )
2400{
2401 SwUnoTableCursor* pUnoTableCursor = dynamic_cast<SwUnoTableCursor*>(&(*m_pTableCursor));
2402 if (!pUnoTableCursor)
2403 return;
2404
2405 const SwStartNode *pStartNd = nullptr;
2406 const SwTableBox *pStartBox = nullptr;
2407 const SwTableBox *pEndBox = nullptr;
2408
2409 const SwTable* pTable = SwTable::FindTable( GetFrameFormat() );
2410 OSL_ENSURE( !pTable->IsTableComplex(), "table too complex" );
2411 if (nCount < 1 || nFirstNew < 0 || pTable->IsTableComplex())
2412 return;
2413
2414 // get range descriptor (cell range) for current data-sequence
2415
2416 pStartNd = pUnoTableCursor->GetPoint()->GetNode().FindTableBoxStartNode();
2417 pEndBox = pTable->GetTableBox( pStartNd->GetIndex() );
2418 const OUString aEndBox( pEndBox->GetName() );
2419
2420 pStartNd = pUnoTableCursor->GetMark()->GetNode().FindTableBoxStartNode();
2421 pStartBox = pTable->GetTableBox( pStartNd->GetIndex() );
2422 const OUString aStartBox( pStartBox->GetName() );
2423
2424 SwRangeDescriptor aDesc;
2425 // note that cell range here takes the newly added rows/cols already into account
2426 OUString sDescrip = aStartBox + ":" + aEndBox;
2427 FillRangeDescriptor( aDesc, sDescrip );
2428
2429 bool bChanged = false;
2430 OUString aNewStartCell;
2431 OUString aNewEndCell;
2432 if (bExtendCol && aDesc.nBottom + 1 == nFirstNew)
2433 {
2434 // new column cells adjacent to the bottom of the
2435 // current data-sequence to be added...
2436 OSL_ENSURE( aDesc.nLeft == aDesc.nRight, "data-sequence is not a column" );
2437 aNewStartCell = sw_GetCellName(aDesc.nLeft, aDesc.nTop);
2438 aNewEndCell = sw_GetCellName(aDesc.nRight, aDesc.nBottom + nCount);
2439 bChanged = true;
2440 }
2441 else if (bExtendCol && aDesc.nTop - nCount == nFirstNew)
2442 {
2443 // new column cells adjacent to the top of the
2444 // current data-sequence to be added...
2445 OSL_ENSURE( aDesc.nLeft == aDesc.nRight, "data-sequence is not a column" );
2446 aNewStartCell = sw_GetCellName(aDesc.nLeft, aDesc.nTop - nCount);
2447 aNewEndCell = sw_GetCellName(aDesc.nRight, aDesc.nBottom);
2448 bChanged = true;
2449 }
2450 else if (!bExtendCol && aDesc.nRight + 1 == nFirstNew)
2451 {
2452 // new row cells adjacent to the right of the
2453 // current data-sequence to be added...
2454 OSL_ENSURE( aDesc.nTop == aDesc.nBottom, "data-sequence is not a row" );
2455 aNewStartCell = sw_GetCellName(aDesc.nLeft, aDesc.nTop);
2456 aNewEndCell = sw_GetCellName(aDesc.nRight + nCount, aDesc.nBottom);
2457 bChanged = true;
2458 }
2459 else if (!bExtendCol && aDesc.nLeft - nCount == nFirstNew)
2460 {
2461 // new row cells adjacent to the left of the
2462 // current data-sequence to be added...
2463 OSL_ENSURE( aDesc.nTop == aDesc.nBottom, "data-sequence is not a row" );
2464 aNewStartCell = sw_GetCellName(aDesc.nLeft - nCount, aDesc.nTop);
2465 aNewEndCell = sw_GetCellName(aDesc.nRight, aDesc.nBottom);
2466 bChanged = true;
2467 }
2468
2469 if (bChanged)
2470 {
2471 // move table cursor to new start and end of data-sequence
2472 const SwTableBox *pNewStartBox = pTable->GetTableBox( aNewStartCell );
2473 const SwTableBox *pNewEndBox = pTable->GetTableBox( aNewEndCell );
2474 pUnoTableCursor->SetMark();
2475 pUnoTableCursor->GetPoint()->Assign( *pNewEndBox->GetSttNd() );
2476 pUnoTableCursor->GetMark()->Assign( *pNewStartBox->GetSttNd() );
2477 pUnoTableCursor->Move( fnMoveForward, GoInNode );
2478 pUnoTableCursor->MakeBoxSels();
2479 }
2480}
2481
2483{
2484 m_bDisposed = false;
2485}
2486
2488{
2489}
2490
2491uno::Reference< chart2::data::XDataSequence > SAL_CALL SwChartLabeledDataSequence::getValues( )
2492{
2493 SolarMutexGuard aGuard;
2494 if (m_bDisposed)
2495 throw lang::DisposedException();
2496 return m_xData;
2497}
2498
2500 uno::Reference< chart2::data::XDataSequence >& rxDest,
2501 const uno::Reference< chart2::data::XDataSequence >& rxSource)
2502{
2503 uno::Reference< util::XModifyListener > xML(this);
2504 uno::Reference< lang::XEventListener > xEL(this);
2505
2506 // stop listening to old data-sequence
2507 uno::Reference< util::XModifyBroadcaster > xMB( rxDest, uno::UNO_QUERY );
2508 if (xMB.is())
2509 xMB->removeModifyListener( xML );
2510 uno::Reference< lang::XComponent > xC( rxDest, uno::UNO_QUERY );
2511 if (xC.is())
2512 xC->removeEventListener( xEL );
2513
2514 rxDest = rxSource;
2515
2516 // start listening to new data-sequence
2517 xC.set( rxDest, uno::UNO_QUERY );
2518 if (xC.is())
2519 xC->addEventListener( xEL );
2520 xMB.set( rxDest, uno::UNO_QUERY );
2521 if (xMB.is())
2522 xMB->addModifyListener( xML );
2523}
2524
2526 const uno::Reference< chart2::data::XDataSequence >& rxSequence )
2527{
2528 SolarMutexGuard aGuard;
2529 if (m_bDisposed)
2530 throw lang::DisposedException();
2531
2532 if (m_xData != rxSequence)
2533 {
2534 SetDataSequence( m_xData, rxSequence );
2535 // inform listeners of changes
2536 LaunchModifiedEvent( m_aModifyListeners, static_cast< XModifyBroadcaster * >(this) );
2537 }
2538}
2539
2540uno::Reference< chart2::data::XDataSequence > SAL_CALL SwChartLabeledDataSequence::getLabel( )
2541{
2542 SolarMutexGuard aGuard;
2543 if (m_bDisposed)
2544 throw lang::DisposedException();
2545 return m_xLabels;
2546}
2547
2549 const uno::Reference< chart2::data::XDataSequence >& rxSequence )
2550{
2551 SolarMutexGuard aGuard;
2552 if (m_bDisposed)
2553 throw lang::DisposedException();
2554
2555 if (m_xLabels != rxSequence)
2556 {
2557 SetDataSequence( m_xLabels, rxSequence );
2558 // inform listeners of changes
2559 LaunchModifiedEvent( m_aModifyListeners, static_cast< XModifyBroadcaster * >(this) );
2560 }
2561}
2562
2563uno::Reference< util::XCloneable > SAL_CALL SwChartLabeledDataSequence::createClone( )
2564{
2565 SolarMutexGuard aGuard;
2566 if (m_bDisposed)
2567 throw lang::DisposedException();
2568
2569 uno::Reference< util::XCloneable > xDataCloneable( m_xData, uno::UNO_QUERY );
2570 uno::Reference< util::XCloneable > xLabelsCloneable( m_xLabels, uno::UNO_QUERY );
2572 if (xDataCloneable.is())
2573 {
2574 uno::Reference< chart2::data::XDataSequence > xDataClone( xDataCloneable->createClone(), uno::UNO_QUERY );
2575 pRes->setValues( xDataClone );
2576 }
2577
2578 if (xLabelsCloneable.is())
2579 {
2580 uno::Reference< chart2::data::XDataSequence > xLabelsClone( xLabelsCloneable->createClone(), uno::UNO_QUERY );
2581 pRes->setLabel( xLabelsClone );
2582 }
2583 return pRes;
2584}
2585
2587{
2588 return "SwChartLabeledDataSequence";
2589}
2590
2592 const OUString& rServiceName )
2593{
2594 return cppu::supportsService(this, rServiceName);
2595}
2596
2597uno::Sequence< OUString > SAL_CALL SwChartLabeledDataSequence::getSupportedServiceNames( )
2598{
2599 return { "com.sun.star.chart2.data.LabeledDataSequence" };
2600}
2601
2603 const lang::EventObject& rSource )
2604{
2605 std::unique_lock aGuard( GetChartMutex() );
2606 uno::Reference< uno::XInterface > xRef( rSource.Source );
2607 if (xRef == m_xData)
2608 m_xData.clear();
2609 if (xRef == m_xLabels)
2610 m_xLabels.clear();
2611 if (!m_xData.is() && !m_xLabels.is())
2612 {
2613 aGuard.unlock();
2614 dispose();
2615 }
2616}
2617
2619 const lang::EventObject& rEvent )
2620{
2621 if (rEvent.Source == m_xData || rEvent.Source == m_xLabels)
2622 {
2623 LaunchModifiedEvent( m_aModifyListeners, static_cast< XModifyBroadcaster * >(this) );
2624 }
2625}
2626
2628 const uno::Reference< util::XModifyListener >& rxListener )
2629{
2630 std::unique_lock aGuard( GetChartMutex() );
2631 if (!m_bDisposed && rxListener.is())
2632 m_aModifyListeners.addInterface( aGuard, rxListener );
2633}
2634
2636 const uno::Reference< util::XModifyListener >& rxListener )
2637{
2638 std::unique_lock aGuard( GetChartMutex() );
2639 if (!m_bDisposed && rxListener.is())
2640 m_aModifyListeners.removeInterface( aGuard, rxListener );
2641}
2642
2644{
2645 bool bMustDispose( false );
2646 {
2647 std::unique_lock aGuard( GetChartMutex() );
2648 bMustDispose = !m_bDisposed;
2649 if (!m_bDisposed)
2650 m_bDisposed = true;
2651 }
2652 if (bMustDispose)
2653 {
2654 m_bDisposed = true;
2655
2656 // require listeners to release references to this object
2657 lang::EventObject aEvtObj( static_cast< chart2::data::XLabeledDataSequence * >(this) );
2658 std::unique_lock aGuard( GetChartMutex() );
2659 m_aModifyListeners.disposeAndClear( aGuard, aEvtObj );
2660 m_aEventListeners.disposeAndClear( aGuard, aEvtObj );
2661 }
2662}
2663
2665 const uno::Reference< lang::XEventListener >& rxListener )
2666{
2667 std::unique_lock aGuard( GetChartMutex() );
2668 if (!m_bDisposed && rxListener.is())
2669 m_aEventListeners.addInterface( aGuard, rxListener );
2670}
2671
2673 const uno::Reference< lang::XEventListener >& rxListener )
2674{
2675 std::unique_lock aGuard( GetChartMutex() );
2676 if (!m_bDisposed && rxListener.is())
2677 m_aEventListeners.removeInterface( aGuard, rxListener );
2678}
2679
2680/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString m_aRole
virtual SwChartLockController_Helper & GetChartControllerHelper()=0
returns chart controller helper that is used to lock/unlock all charts when relevant parts of tables ...
SfxHintId GetId() const
css::uno::Reference< css::beans::XPropertySetInfo > const & getPropertySetInfo() const
void EndListeningAll()
bool StartListening(SvtBroadcaster &rBroadcaster)
const SwDoc * m_pDoc
Definition: unochart.hxx:121
::comphelper::OInterfaceContainerHelper4< css::lang::XEventListener > m_aEventListeners
Definition: unochart.hxx:120
void InvalidateTable(const SwTable *pTable, bool bImmediate=false)
Definition: unochart.cxx:1427
void RemoveDataSequence(const SwTable &rTable, rtl::Reference< SwChartDataSequence > const &rxDataSequence)
Definition: unochart.cxx:1417
SwChartDataProvider(const SwChartDataProvider &)=delete
virtual sal_Bool SAL_CALL createDataSourcePossible(const css::uno::Sequence< css::beans::PropertyValue > &aArguments) override
Definition: unochart.cxx:887
virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL createDataSequenceByValueArray(const OUString &aRole, const OUString &aRangeRepresentation, const OUString &aRoleQualifier) override
Definition: unochart.cxx:1342
css::uno::Reference< css::chart2::data::XDataSource > Impl_createDataSource(const css::uno::Sequence< css::beans::PropertyValue > &aArguments, bool bTestOnly=false)
Definition: unochart.cxx:513
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
Definition: unochart.cxx:1375
virtual void SAL_CALL dispose() override
Definition: unochart.cxx:1349
virtual OUString SAL_CALL convertRangeToXML(const OUString &aRangeRepresentation) override
Definition: unochart.cxx:1614
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &aListener) override
Definition: unochart.cxx:1383
css::uno::Reference< css::chart2::data::XDataSequence > Impl_createDataSequenceByRangeRepresentation(std::u16string_view aRangeRepresentation, bool bTestOnly=false)
Definition: unochart.cxx:1282
virtual sal_Bool SAL_CALL createDataSequenceByRangeRepresentationPossible(const OUString &aRangeRepresentation) override
Definition: unochart.cxx:1310
virtual css::uno::Reference< css::chart2::data::XDataSource > SAL_CALL createDataSource(const css::uno::Sequence< css::beans::PropertyValue > &aArguments) override
Definition: unochart.cxx:905
virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL detectArguments(const css::uno::Reference< css::chart2::data::XDataSource > &xDataSource) override
Definition: unochart.cxx:948
virtual css::uno::Reference< css::sheet::XRangeSelection > SAL_CALL getRangeSelection() override
Definition: unochart.cxx:1335
virtual OUString SAL_CALL convertRangeFromXML(const OUString &aXMLRange) override
Definition: unochart.cxx:1684
void AddRowCols(const SwTable &rTable, const SwSelBoxes &rBoxes, sal_uInt16 nLines, bool bBehind)
SwChartDataProvider::AddRowCols tries to notify charts of added columns or rows and extends the value...
Definition: unochart.cxx:1543
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: unochart.cxx:1396
static OUString GetBrokenCellRangeForExport(std::u16string_view rCellRangeRepresentation)
Fix for #i79009 we need to return a property that has the same value as the property 'CellRangeRepres...
Definition: unochart.cxx:921
virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL createDataSequenceByRangeRepresentation(const OUString &aRangeRepresentation) override
Definition: unochart.cxx:1328
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: unochart.cxx:1401
virtual ~SwChartDataProvider() override
Definition: unochart.cxx:509
void AddDataSequence(const SwTable &rTable, rtl::Reference< SwChartDataSequence > const &rxDataSequence)
Definition: unochart.cxx:1406
virtual OUString SAL_CALL getImplementationName() override
Definition: unochart.cxx:1391
Map_Set_DataSequenceRef_t m_aDataSequences
Definition: unochart.hxx:118
void DisposeAllDataSequences(const SwTable *pTable)
Definition: unochart.cxx:1497
void DeleteBox(const SwTable *pTable, const SwTableBox &rBox)
Definition: unochart.cxx:1452
std::vector< unotools::WeakReference< SwChartDataSequence > > Vec_DataSequenceRef_t
Definition: unochart.hxx:109
void ExtendTo(bool bExtendCol, sal_Int32 nFirstNew, sal_Int32 nCount)
Extends the data-sequence by new cells added at the end of the direction the data-sequence points to.
Definition: unochart.cxx:2398
::comphelper::OInterfaceContainerHelper4< css::lang::XEventListener > m_aEvtListeners
Definition: unochart.hxx:227
virtual css::uno::Sequence< OUString > SAL_CALL getTextualData() override
Definition: unochart.cxx:2004
virtual void Notify(const SfxHint &rHint) override
Definition: unochart.cxx:2132
std::vector< css::uno::Reference< css::table::XCell > > GetCells()
Definition: unochart.cxx:1988
virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override
Definition: unochart.cxx:2043
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: unochart.cxx:2127
virtual void SAL_CALL removeModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
Definition: unochart.cxx:2176
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: unochart.cxx:2184
virtual void SAL_CALL addPropertyChangeListener(const OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &xListener) override
Definition: unochart.cxx:2089
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: unochart.cxx:2122
const SfxItemPropertySet * m_pPropSet
Definition: unochart.hxx:238
virtual OUString SAL_CALL getImplementationName() override
Definition: unochart.cxx:2117
::comphelper::OInterfaceContainerHelper4< css::util::XModifyListener > m_aModifyListeners
Definition: unochart.hxx:228
virtual void SAL_CALL addModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
Definition: unochart.cxx:2168
SwFrameFormat * GetFrameFormat() const
Definition: unochart.hxx:296
SwFrameFormat * m_pFormat
Definition: unochart.hxx:226
virtual css::uno::Sequence< double > SAL_CALL getNumericalData() override
Definition: unochart.cxx:2030
virtual void SAL_CALL setModified(sal_Bool bModified) override
Definition: unochart.cxx:2157
virtual OUString SAL_CALL getSourceRangeRepresentation() override
Definition: unochart.cxx:1858
virtual void SAL_CALL removeVetoableChangeListener(const OUString &PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override
Definition: unochart.cxx:2110
virtual void SAL_CALL setPropertyValue(const OUString &aPropertyName, const css::uno::Any &aValue) override
Definition: unochart.cxx:2061
void FillRangeDesc(SwRangeDescriptor &rRangeDesc) const
Definition: unochart.cxx:2371
OUString m_aRowLabelText
Definition: unochart.hxx:231
virtual void SAL_CALL dispose() override
Definition: unochart.cxx:2194
virtual css::uno::Sequence< css::uno::Any > SAL_CALL getData() override
Definition: unochart.cxx:2017
bool DeleteBox(const SwTableBox &rBox)
Definition: unochart.cxx:2265
css::chart2::data::DataSequenceRole m_aRole
Definition: unochart.hxx:229
SwChartDataSequence(const SwChartDataSequence &rObj)
Definition: unochart.cxx:1808
virtual void SAL_CALL removePropertyChangeListener(const OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &aListener) override
Definition: unochart.cxx:2096
sw::UnoCursorPointer m_pTableCursor
Definition: unochart.hxx:236
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
Definition: unochart.cxx:2249
rtl::Reference< SwChartDataProvider > m_xDataProvider
Definition: unochart.hxx:234
virtual ::sal_Int32 SAL_CALL getNumberFormatKeyByIndex(::sal_Int32 nIndex) override
Definition: unochart.cxx:1982
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &aListener) override
Definition: unochart.cxx:2257
virtual ~SwChartDataSequence() override
Definition: unochart.cxx:1854
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
Definition: unochart.cxx:2051
virtual void SAL_CALL addVetoableChangeListener(const OUString &PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override
Definition: unochart.cxx:2103
virtual sal_Bool SAL_CALL isModified() override
Definition: unochart.cxx:2148
virtual css::uno::Sequence< OUString > SAL_CALL generateLabel(css::chart2::data::LabelOrigin eLabelOrigin) override
Definition: unochart.cxx:1875
OUString m_aColLabelText
Definition: unochart.hxx:232
virtual css::uno::Any SAL_CALL getPropertyValue(const OUString &PropertyName) override
Definition: unochart.cxx:2076
SwChartDataSource(const SwChartDataSource &)=delete
virtual OUString SAL_CALL getImplementationName() override
Definition: unochart.cxx:1748
virtual ~SwChartDataSource() override
Definition: unochart.cxx:1738
css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > m_aLDS
Definition: unochart.hxx:190
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: unochart.cxx:1758
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: unochart.cxx:1753
virtual css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > SAL_CALL getDataSequences() override
Definition: unochart.cxx:1742
static void DoUpdateAllCharts(SwDoc *pDoc)
Definition: unochart.cxx:52
virtual OUString SAL_CALL getImplementationName() override
Definition: unochart.cxx:2586
virtual void SAL_CALL dispose() override
Definition: unochart.cxx:2643
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: unochart.cxx:2602
virtual void SAL_CALL modified(const css::lang::EventObject &aEvent) override
Definition: unochart.cxx:2618
css::uno::Reference< css::chart2::data::XDataSequence > m_xData
Definition: unochart.hxx:321
virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override
Definition: unochart.cxx:2563
virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL getLabel() override
Definition: unochart.cxx:2540
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
Definition: unochart.cxx:2664
::comphelper::OInterfaceContainerHelper4< css::util::XModifyListener > m_aModifyListeners
Definition: unochart.hxx:319
virtual void SAL_CALL setValues(const css::uno::Reference< css::chart2::data::XDataSequence > &xSequence) override
Definition: unochart.cxx:2525
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: unochart.cxx:2597
::comphelper::OInterfaceContainerHelper4< css::lang::XEventListener > m_aEventListeners
Definition: unochart.hxx:318
virtual void SAL_CALL addModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
Definition: unochart.cxx:2627
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: unochart.cxx:2591
virtual void SAL_CALL setLabel(const css::uno::Reference< css::chart2::data::XDataSequence > &xSequence) override
Definition: unochart.cxx:2548
virtual ~SwChartLabeledDataSequence() override
Definition: unochart.cxx:2487
css::uno::Reference< css::chart2::data::XDataSequence > m_xLabels
Definition: unochart.hxx:322
virtual void SAL_CALL removeModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
Definition: unochart.cxx:2635
void SetDataSequence(css::uno::Reference< css::chart2::data::XDataSequence > &rxDest, const css::uno::Reference< css::chart2::data::XDataSequence > &rxSource)
Definition: unochart.cxx:2499
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &aListener) override
Definition: unochart.cxx:2672
virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL getValues() override
Definition: unochart.cxx:2491
SwChartLockController_Helper(const SwChartLockController_Helper &)=delete
void LockUnlockAllCharts(bool bLock)
Definition: unochart.cxx:115
Definition: doc.hxx:195
size_t GetTableFrameFormatCount(bool bUsed) const
Definition: docfmt.cxx:769
IDocumentChartDataProviderAccess const & getIDocumentChartDataProviderAccess() const
Definition: doc.cxx:235
SwNodes & GetNodes()
Definition: doc.hxx:418
std::shared_ptr< SwUnoCursor > CreateUnoCursor(const SwPosition &rPos, bool bTableCursor=false)
Definition: doc.cxx:1803
SwFrameFormat & GetTableFrameFormat(size_t nFormat, bool bUsed) const
Definition: docfmt.cxx:786
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:139
const OUString & GetName() const
Definition: format.hxx:131
Style of a layout element.
Definition: frmfmt.hxx:62
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNodeIndex & Assign(SwNodes const &rNds, SwNodeOffset)
Definition: ndindex.hxx:291
SwNode & GetNode() const
Definition: ndindex.hxx:136
Base class of the Writer document model elements.
Definition: node.hxx:98
SwStartNode * GetStartNode()
Definition: node.hxx:642
SwNodeOffset GetIndex() const
Definition: node.hxx:312
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:218
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
SwOLENode * GetOLENode()
Inline methods from Node.hxx.
Definition: ndole.hxx:165
SwContentNode * GetContentNode()
Definition: node.hxx:666
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:733
SwNode & GetEndOfAutotext() const
Section for all Flys/Header/Footers.
Definition: ndarr.hxx:158
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1299
SwNodeOffset Count() const
Definition: ndarr.hxx:142
const SwOLEObj & GetOLEObj() const
Definition: ndole.hxx:116
const OUString & GetChartTableName() const
Definition: ndole.hxx:156
svt::EmbeddedObjectRef & GetObject()
Definition: ndole.cxx:992
css::uno::Reference< css::embed::XEmbeddedObject > const & GetOleRef()
Definition: ndole.cxx:941
const OUString & GetCurrentPersistName() const
Definition: ndole.hxx:72
const SwPosition * GetMark() const
Definition: pam.hxx:263
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:642
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:668
const SwPosition * GetPoint() const
Definition: pam.hxx:261
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:259
Starts a section of nodes in the document model.
Definition: node.hxx:348
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:426
OUString GetName() const
Definition: swtable.cxx:2012
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:478
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:374
size_type size() const
Definition: swtable.hxx:76
SwTableLine * front() const
Definition: swtable.hxx:81
SwTable is one table in the document model, containing rows (which contain cells).
Definition: swtable.hxx:113
SwTableLines & GetTabLines()
Definition: swtable.hxx:204
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:207
bool IsTableComplex() const
Definition: swtable.cxx:1441
const SwTableBox * GetTableBox(const OUString &rName, const bool bPerformValidCheck=false) const
Definition: swtable.cxx:1340
static SwTable * FindTable(SwFrameFormat const *const pFormat)
Definition: swtable.cxx:2135
void MakeBoxSels()
Definition: unocrsr.cxx:184
static ::rtl::Reference< SwXCellRange > CreateXCellRange(const sw::UnoCursorPointer &pCursor, SwFrameFormat &rFrameFormat, SwRangeDescriptor const &rDesc)
Definition: unotbl.cxx:3162
static void GetCellPosition(std::u16string_view aCellName, sal_Int32 &o_rColumn, sal_Int32 &o_rRow)
get position of a cell with a given name
Definition: unotbl.cxx:352
void Stop()
void SetTimeout(sal_uInt64 nTimeoutMs)
void SetInvokeHandler(const Link< Timer *, void > &rLink)
virtual void Start(bool bStartTimer=true) override
void notifyEach(std::unique_lock< std::mutex > &rGuard, void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event)
sal_Int32 addInterface(std::unique_lock< std::mutex > &rGuard, const css::uno::Reference< ListenerT > &rxIFace)
void disposeAndClear(::std::unique_lock<::std::mutex > &rGuard, const css::lang::EventObject &rEvt)
sal_Int32 removeInterface(std::unique_lock< std::mutex > &rGuard, const css::uno::Reference< ListenerT > &rxIFace)
const Value & back() const
size_type size() const
static bool TryRunningState(const css::uno::Reference< css::embed::XEmbeddedObject > &)
void reset(std::shared_ptr< SwUnoCursor > pNew)
Definition: unocrsr.hxx:158
int nCount
#define suppress_fun_call_w_exception(expr)
Mutex aMutex
sal_uInt16 nPos
OUString getXMLStringFromCellRange(const CellRange &rRange)
CellRange getCellRangeFromXMLString(const OUString &rXMLString)
sal_Int32 getTokenCount(std::string_view rIn, char cTok)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
enumrange< T >::Iterator begin(enumrange< T >)
end
HashMap_OWString_Interface aMap
bool GoInNode(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:1171
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:61
std::unique_ptr< uint8_t[]> pLabels
DefTokenId nToken
Marks a position in the document model.
Definition: pam.hxx:37
SwNode & GetNode() const
Definition: pam.hxx:80
void Assign(const SwNode &rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset=0)
These all set both nNode and nContent.
Definition: pam.cxx:230
sal_Int32 nLeft
Definition: unotbl.hxx:242
sal_Int32 nBottom
Definition: unotbl.hxx:243
void Normalize()
Definition: unotbl.cxx:537
sal_Int32 nTop
Definition: unotbl.hxx:241
sal_Int32 nRight
Definition: unotbl.hxx:244
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:168
unsigned char sal_Bool
sal_uInt16 sal_Unicode
IMPL_LINK_NOARG(SwChartLockController_Helper, DoUnlockAllCharts, Timer *, void)
Definition: unochart.cxx:149
static void SortSubranges(uno::Sequence< OUString > &rSubRanges, bool bCmpByColumn)
Definition: unochart.cxx:457
static bool GetSubranges(std::u16string_view rRangeRepresentation, uno::Sequence< OUString > &rSubRanges, bool bNormalize)
Definition: unochart.cxx:409
static bool GetTableAndCellsFromRangeRep(std::u16string_view rRangeRepresentation, OUString &rTableName, OUString &rStartCell, OUString &rEndCell, bool bSortStartEndCells=true)
Definition: unochart.cxx:270
static OUString GetCellRangeName(const SwFrameFormat &rTableFormat, SwUnoCursor &rTableCursor)
Definition: unochart.cxx:199
static void GetTableByName(const SwDoc &rDoc, std::u16string_view rTableName, SwFrameFormat **ppTableFormat, SwTable **ppTable)
Definition: unochart.cxx:319
static void GetFormatAndCreateCursorFromRangeRep(const SwDoc *pDoc, std::u16string_view rRangeRepresentation, SwFrameFormat **ppTableFormat, std::shared_ptr< SwUnoCursor > &rpUnoCursor)
Definition: unochart.cxx:341
static std::mutex & GetChartMutex()
Definition: unochart.cxx:154
static OUString GetRangeRepFromTableAndCells(std::u16string_view rTableName, std::u16string_view rStartCell, std::u16string_view rEndCell, bool bForceEndCellName)
Definition: unochart.cxx:250
static void LaunchModifiedEvent(::comphelper::OInterfaceContainerHelper4< util::XModifyListener > &rICH, const uno::Reference< uno::XInterface > &rxI)
Definition: unochart.cxx:160
bool FillRangeDescriptor(SwRangeDescriptor &rDesc, std::u16string_view rCellRangeName)
rCellRangeName needs to be of one of the following formats:
Definition: unochart.cxx:174
cppu::WeakImplHelper< css::chart2::data::XDataSequence, css::chart2::data::XTextualDataSequence, css::chart2::data::XNumericalDataSequence, css::util::XCloneable, css::beans::XPropertySet, css::lang::XServiceInfo, css::util::XModifiable, css::lang::XEventListener, css::lang::XComponent > SwChartDataSequenceBaseClass
Definition: unochart.hxx:220
SwUnoPropertyMapProvider aSwMapProvider
Definition: unomap1.cxx:87
#define PROPERTY_MAP_CHART2_DATA_SEQUENCE
Definition: unomap.hxx:117
constexpr OUStringLiteral UNO_NAME_ROLE
Definition: unoprnms.hxx:808
void sw_NormalizeRange(OUString &rCell1, OUString &rCell2)
cleanup order in a range
Definition: unotbl.cxx:525
int sw_CompareCellsByColFirst(std::u16string_view aCellName1, std::u16string_view aCellName2)
compare position of two cells (check columns first)
Definition: unotbl.cxx:427
OUString sw_GetCellName(sal_Int32 nColumn, sal_Int32 nRow)
get cell name at a specified coordinate
Definition: unotbl.cxx:480
int sw_CompareCellRanges(std::u16string_view aRange1StartCell, std::u16string_view aRange1EndCell, std::u16string_view aRange2StartCell, std::u16string_view aRange2EndCell, bool bCmpColsFirst)
compare position of two cell ranges
Definition: unotbl.cxx:454