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 = pTable->GetTabLines().front()->GetTabBoxes().size();
648 std::vector<std::vector<char>> aMap(nRows);
649 for (sal_Int32 i = 0; i < nRows; ++i)
650 aMap[i].resize(nCols);
651
652 // iterate over subranges and mark used cells in above map
656 for (const OUString& rSubRange : std::as_const(aSubRanges))
657 {
658 OUString aTableName, aStartCell, aEndCell;
660 rSubRange, aTableName, aStartCell, aEndCell );
661 OSL_ENSURE(bOk2, "failed to get table and start/end cells");
662
663 sal_Int32 nStartRow, nStartCol, nEndRow, nEndCol;
664 SwXTextTable::GetCellPosition(aStartCell, nStartCol, nStartRow);
665 SwXTextTable::GetCellPosition(aEndCell, nEndCol, nEndRow);
666 OSL_ENSURE( nStartRow <= nEndRow && nStartCol <= nEndCol,
667 "cell range not normalized");
668
669 // test if the ranges span more than the available cells
670 if( nStartRow < 0 || nEndRow >= nRows ||
671 nStartCol < 0 || nEndCol >= nCols )
672 {
673 throw lang::IllegalArgumentException();
674 }
675 for (sal_Int32 k1 = nStartRow; k1 <= nEndRow; ++k1)
676 {
677 for (sal_Int32 k2 = nStartCol; k2 <= nEndCol; ++k2)
678 aMap[k1][k2] = 'x';
679 }
680 }
681
682 // find label and data sequences to use
683
684 sal_Int32 oi; // outer index (slower changing index)
685 sal_Int32 ii; // inner index (faster changing index)
686 sal_Int32 oiEnd = bDtaSrcIsColumns ? nCols : nRows;
687 sal_Int32 iiEnd = bDtaSrcIsColumns ? nRows : nCols;
688 std::vector<sal_Int32> aLabelIdx(oiEnd);
689 std::vector<sal_Int32> aDataStartIdx(oiEnd);
690 std::vector<sal_Int32> aDataLen(oiEnd);
691 for (oi = 0; oi < oiEnd; ++oi)
692 {
693 aLabelIdx[oi] = -1;
694 aDataStartIdx[oi] = -1;
695 aDataLen[oi] = 0;
696 }
697
698 for (oi = 0; oi < oiEnd; ++oi)
699 {
700 ii = 0;
701 while (ii < iiEnd)
702 {
703 char &rChar = bDtaSrcIsColumns ? aMap[ii][oi] : aMap[oi][ii];
704
705 // label should be used but is not yet found?
706 if (rChar == 'x' && bFirstIsLabel && aLabelIdx[oi] == -1)
707 {
708 aLabelIdx[oi] = ii;
709 rChar = 'L'; // setting a different char for labels here
710 // makes the test for the data sequence below
711 // easier
712 }
713
714 // find data sequence
715 if (rChar == 'x' && aDataStartIdx[oi] == -1)
716 {
717 aDataStartIdx[oi] = ii;
718
719 // get length of data sequence
720 sal_Int32 nL = 0;
721 while (ii< iiEnd && 'x' == (bDtaSrcIsColumns ? aMap[ii][oi] : aMap[oi][ii]))
722 {
723 ++nL; ++ii;
724 }
725 aDataLen[oi] = nL;
726
727 // check that there is no other separate sequence of data
728 // to be found because that is not supported
729 while (ii < iiEnd)
730 {
731 if ('x' == (bDtaSrcIsColumns ? aMap[ii][oi] : aMap[oi][ii]))
732 throw lang::IllegalArgumentException();
733 ++ii;
734 }
735 }
736 else
737 ++ii;
738 }
739 }
740
741 // make some other consistency checks while calculating
742 // the number of XLabeledDataSequence to build:
743 // - labels should always be used or not at all
744 // - the data sequences should have equal non-zero length
745 sal_Int32 nNumLDS = 0;
746 if (oiEnd > 0)
747 {
748 sal_Int32 nFirstSeqLen = 0;
749 sal_Int32 nFirstSeqLabelIdx = -1;
750 bool bFirstFound = false;
751 for (oi = 0; oi < oiEnd; ++oi)
752 {
753 // row/col used at all?
754 if (aDataStartIdx[oi] != -1 &&
755 (!bFirstIsLabel || aLabelIdx[oi] != -1))
756 {
757 ++nNumLDS;
758 if (!bFirstFound)
759 {
760 nFirstSeqLen = aDataLen[oi];
761 nFirstSeqLabelIdx = aLabelIdx[oi];
762 bFirstFound = true;
763 }
764 else
765 {
766 if (nFirstSeqLen != aDataLen[oi] ||
767 nFirstSeqLabelIdx != aLabelIdx[oi])
768 throw lang::IllegalArgumentException();
769 }
770 }
771 }
772 }
773 if (nNumLDS == 0)
774 throw lang::IllegalArgumentException();
775
776 // now we should have all necessary data to build a proper DataSource
777 // thus if we came this far there should be no further problem
778 if (bTestOnly)
779 return xRes; // have createDataSourcePossible return true
780
781 // create data source from found label and data sequences
782 uno::Sequence<uno::Reference<chart2::data::XDataSequence>> aLabelSeqs(nNumLDS);
783 uno::Reference<chart2::data::XDataSequence>* pLabelSeqs = aLabelSeqs.getArray();
784 uno::Sequence<uno::Reference<chart2::data::XDataSequence>> aDataSeqs(nNumLDS);
785 uno::Reference<chart2::data::XDataSequence>* pDataSeqs = aDataSeqs.getArray();
786 sal_Int32 nSeqsIdx = 0;
787 for (oi = 0; oi < oiEnd; ++oi)
788 {
789 // row/col not used? (see if-statement above where nNumLDS was counted)
790 if (!(aDataStartIdx[oi] != -1 &&
791 (!bFirstIsLabel || aLabelIdx[oi] != -1)))
792 continue;
793
794 // get cell ranges for label and data
795
796 SwRangeDescriptor aLabelDesc;
797 SwRangeDescriptor aDataDesc;
798 if (bDtaSrcIsColumns) // use columns
799 {
800 aLabelDesc.nTop = aLabelIdx[oi];
801 aLabelDesc.nLeft = oi;
802 aLabelDesc.nBottom = aLabelDesc.nTop;
803 aLabelDesc.nRight = oi;
804
805 aDataDesc.nTop = aDataStartIdx[oi];
806 aDataDesc.nLeft = oi;
807 aDataDesc.nBottom = aDataDesc.nTop + aDataLen[oi] - 1;
808 aDataDesc.nRight = oi;
809 }
810 else // use rows
811 {
812 aLabelDesc.nTop = oi;
813 aLabelDesc.nLeft = aLabelIdx[oi];
814 aLabelDesc.nBottom = oi;
815 aLabelDesc.nRight = aLabelDesc.nLeft;
816
817 aDataDesc.nTop = oi;
818 aDataDesc.nLeft = aDataStartIdx[oi];
819 aDataDesc.nBottom = oi;
820 aDataDesc.nRight = aDataDesc.nLeft + aDataLen[oi] - 1;
821 }
822 const OUString aBaseName = pTableFormat->GetName() + ".";
823
824 OUString aLabelRange;
825 if (aLabelIdx[oi] != -1)
826 {
827 aLabelRange = aBaseName
828 + sw_GetCellName( aLabelDesc.nLeft, aLabelDesc.nTop )
829 + ":" + sw_GetCellName( aLabelDesc.nRight, aLabelDesc.nBottom );
830 }
831
832 OUString aDataRange = aBaseName
833 + sw_GetCellName( aDataDesc.nLeft, aDataDesc.nTop )
834 + ":" + sw_GetCellName( aDataDesc.nRight, aDataDesc.nBottom );
835
836 // get cursors spanning the cell ranges for label and data
837 std::shared_ptr<SwUnoCursor> pLabelUnoCursor;
838 std::shared_ptr<SwUnoCursor> pDataUnoCursor;
839 GetFormatAndCreateCursorFromRangeRep(m_pDoc, aLabelRange, &pTableFormat, pLabelUnoCursor);
840 GetFormatAndCreateCursorFromRangeRep(m_pDoc, aDataRange, &pTableFormat, pDataUnoCursor);
841
842 // create XDataSequence's from cursors
843 if (pLabelUnoCursor)
844 pLabelSeqs[nSeqsIdx] = new SwChartDataSequence(*this, *pTableFormat, pLabelUnoCursor);
845 OSL_ENSURE(pDataUnoCursor, "pointer to data sequence missing");
846 if (pDataUnoCursor)
847 pDataSeqs[nSeqsIdx] = new SwChartDataSequence(*this, *pTableFormat, pDataUnoCursor);
848 if (pLabelUnoCursor || pDataUnoCursor)
849 ++nSeqsIdx;
850 }
851 OSL_ENSURE(nSeqsIdx == nNumLDS, "mismatch between sequence size and num,ber of entries");
852
853 // build data source from data and label sequences
854 uno::Sequence<uno::Reference<chart2::data::XLabeledDataSequence>> aLDS(nNumLDS);
855 uno::Reference<chart2::data::XLabeledDataSequence>* pLDS = aLDS.getArray();
856 for (sal_Int32 i = 0; i < nNumLDS; ++i)
857 {
859 pLabeledDtaSeq->setLabel(pLabelSeqs[i]);
860 pLabeledDtaSeq->setValues(pDataSeqs[i]);
861 pLDS[i] = pLabeledDtaSeq;
862 }
863
864 // apply 'SequenceMapping' if it was provided
865 if (aSequenceMapping.hasElements())
866 {
867 uno::Sequence<uno::Reference<chart2::data::XLabeledDataSequence>> aOld_LDS(aLDS);
868 uno::Reference<chart2::data::XLabeledDataSequence>* pOld_LDS = aOld_LDS.getArray();
869
870 sal_Int32 nNewCnt = 0;
871 for (sal_Int32 nIdx : std::as_const(aSequenceMapping))
872 {
873 // check that index to be used is valid
874 // and has not yet been used
875 if (0 <= nIdx && nIdx < nNumLDS && pOld_LDS[nIdx].is())
876 {
877 pLDS[nNewCnt++] = pOld_LDS[nIdx];
878
879 // mark index as being used already (avoids duplicate entries)
880 pOld_LDS[nIdx].clear();
881 }
882 }
883 // add not yet used 'old' sequences to new one
884 for (sal_Int32 i = 0; i < nNumLDS; ++i)
885 {
886 if (pOld_LDS[i].is())
887 pLDS[nNewCnt++] = pOld_LDS[i];
888 }
889 OSL_ENSURE(nNewCnt == nNumLDS, "unexpected size of resulting sequence");
890 }
891
892 xRes = new SwChartDataSource(aLDS);
893 return xRes;
894}
895
897 const uno::Sequence< beans::PropertyValue >& rArguments )
898{
899 SolarMutexGuard aGuard;
900
901 bool bPossible = true;
902 try
903 {
904 Impl_createDataSource( rArguments, true );
905 }
906 catch (lang::IllegalArgumentException &)
907 {
908 bPossible = false;
909 }
910
911 return bPossible;
912}
913
914uno::Reference< chart2::data::XDataSource > SAL_CALL SwChartDataProvider::createDataSource(
915 const uno::Sequence< beans::PropertyValue >& rArguments )
916{
917 SolarMutexGuard aGuard;
918 return Impl_createDataSource( rArguments );
919}
920
931 std::u16string_view rCellRangeRepresentation )
932{
933 // check that we do not have multiple ranges
934 if (std::u16string_view::npos == rCellRangeRepresentation.find( ';' ))
935 {
936 // get current cell and table names
937 OUString aTableName, aStartCell, aEndCell;
938 GetTableAndCellsFromRangeRep( rCellRangeRepresentation,
939 aTableName, aStartCell, aEndCell, false );
940 sal_Int32 nStartCol = -1, nStartRow = -1, nEndCol = -1, nEndRow = -1;
941 SwXTextTable::GetCellPosition( aStartCell, nStartCol, nStartRow );
942 SwXTextTable::GetCellPosition( aEndCell, nEndCol, nEndRow );
943
944 // get new cell names
945 ++nStartRow;
946 ++nEndRow;
947 aStartCell = sw_GetCellName( nStartCol, nStartRow );
948 aEndCell = sw_GetCellName( nEndCol, nEndRow );
949
950 return GetRangeRepFromTableAndCells( aTableName,
951 aStartCell, aEndCell, false );
952 }
953
954 return OUString();
955}
956
957uno::Sequence< beans::PropertyValue > SAL_CALL SwChartDataProvider::detectArguments(
958 const uno::Reference< chart2::data::XDataSource >& xDataSource )
959{
960 SolarMutexGuard aGuard;
961 if (m_bDisposed)
962 throw lang::DisposedException();
963
964 uno::Sequence< beans::PropertyValue > aResult;
965 if (!xDataSource.is())
966 return aResult;
967
968 const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aDS_LDS( xDataSource->getDataSequences() );
969 const uno::Reference< chart2::data::XLabeledDataSequence > *pDS_LDS = aDS_LDS.getConstArray();
970 sal_Int32 nNumDS_LDS = aDS_LDS.getLength();
971
972 if (nNumDS_LDS == 0)
973 {
974 OSL_FAIL( "XLabeledDataSequence in data source contains 0 entries" );
975 return aResult;
976 }
977
978 SwFrameFormat *pTableFormat = nullptr;
979 SwTable *pTable = nullptr;
980 OUString aTableName;
981 sal_Int32 nTableRows = 0;
982 sal_Int32 nTableCols = 0;
983
984 // data used to build 'CellRangeRepresentation' from later on
985 std::vector< std::vector< char > > aMap;
986
987 uno::Sequence< sal_Int32 > aSequenceMapping( nNumDS_LDS );
988 sal_Int32 *pSequenceMapping = aSequenceMapping.getArray();
989
990 OUString aCellRanges;
991 sal_Int16 nDtaSrcIsColumns = -1;// -1: don't know yet, 0: false, 1: true -2: neither
992 sal_Int32 nLabelSeqLen = -1; // used to see if labels are always used or not and have
993 // the expected size of 1 (i.e. if FirstCellAsLabel can
994 // be determined)
995 // -1: don't know yet, 0: not used, 1: always a single labe cell, ...
996 // -2: neither/failed
997 for (sal_Int32 nDS1 = 0; nDS1 < nNumDS_LDS; ++nDS1)
998 {
999 uno::Reference< chart2::data::XLabeledDataSequence > xLabeledDataSequence( pDS_LDS[nDS1] );
1000 if( !xLabeledDataSequence.is() )
1001 {
1002 OSL_FAIL("got NULL for XLabeledDataSequence from Data source");
1003 continue;
1004 }
1005 const uno::Reference< chart2::data::XDataSequence > xCurLabel = xLabeledDataSequence->getLabel();
1006 const uno::Reference< chart2::data::XDataSequence > xCurValues = xLabeledDataSequence->getValues();
1007
1008 // get sequence lengths for label and values.
1009 // (0 length is Ok)
1010 sal_Int32 nCurLabelSeqLen = -1;
1011 sal_Int32 nCurValuesSeqLen = -1;
1012 if (xCurLabel.is())
1013 nCurLabelSeqLen = xCurLabel->getData().getLength();
1014 if (xCurValues.is())
1015 nCurValuesSeqLen = xCurValues->getData().getLength();
1016
1017 // check for consistent use of 'first cell as label'
1018 if (nLabelSeqLen == -1) // set initial value to compare with below further on
1019 nLabelSeqLen = nCurLabelSeqLen;
1020 if (nLabelSeqLen != nCurLabelSeqLen)
1021 nLabelSeqLen = -2; // failed / no consistent use of label cells
1022
1023 // get table and cell names for label and values data sequences
1024 // (start and end cell will be sorted, i.e. start cell <= end cell)
1025 OUString aLabelTableName, aLabelStartCell, aLabelEndCell;
1026 OUString aValuesTableName, aValuesStartCell, aValuesEndCell;
1027 OUString aLabelRange, aValuesRange;
1028 if (xCurLabel.is())
1029 aLabelRange = xCurLabel->getSourceRangeRepresentation();
1030 if (xCurValues.is())
1031 aValuesRange = xCurValues->getSourceRangeRepresentation();
1032 if ((!aLabelRange.isEmpty() && !GetTableAndCellsFromRangeRep( aLabelRange,
1033 aLabelTableName, aLabelStartCell, aLabelEndCell )) ||
1034 !GetTableAndCellsFromRangeRep( aValuesRange,
1035 aValuesTableName, aValuesStartCell, aValuesEndCell ))
1036 {
1037 return aResult; // failed -> return empty property sequence
1038 }
1039
1040 // make sure all sequences use the same table
1041 if (aTableName.isEmpty())
1042 aTableName = aValuesTableName; // get initial value to compare with
1043 if (aTableName.isEmpty() ||
1044 aTableName != aValuesTableName ||
1045 (!aLabelTableName.isEmpty() && aTableName != aLabelTableName))
1046 {
1047 return aResult; // failed -> return empty property sequence
1048 }
1049
1050 // try to get 'DataRowSource' value (ROWS or COLUMNS) from inspecting
1051 // first and last cell used in both sequences
1052
1053 sal_Int32 nFirstCol = -1, nFirstRow = -1, nLastCol = -1, nLastRow = -1;
1054 const OUString aCell( !aLabelStartCell.isEmpty() ? aLabelStartCell : aValuesStartCell );
1055 OSL_ENSURE( !aCell.isEmpty() , "start cell missing?" );
1056 SwXTextTable::GetCellPosition( aCell, nFirstCol, nFirstRow);
1057 SwXTextTable::GetCellPosition( aValuesEndCell, nLastCol, nLastRow);
1058
1059 sal_Int16 nDirection = -1; // -1: not yet set, 0: columns, 1: rows, -2: failed
1060 if (nFirstCol == nLastCol && nFirstRow == nLastRow) // a single cell...
1061 {
1062 OSL_ENSURE( nCurLabelSeqLen == 0 && nCurValuesSeqLen == 1,
1063 "trying to determine 'DataRowSource': something's fishy... should have been a single cell");
1064 nDirection = 0; // default direction for a single cell should be 'columns'
1065 }
1066 else // more than one cell is available (in values and label together!)
1067 {
1068 if (nFirstCol == nLastCol && nFirstRow != nLastRow)
1069 nDirection = 1;
1070 else if (nFirstCol != nLastCol && nFirstRow == nLastRow)
1071 nDirection = 0;
1072 else
1073 {
1074 OSL_FAIL( "trying to determine 'DataRowSource': unexpected case found" );
1075 nDirection = -2;
1076 }
1077 }
1078 // check for consistent direction of data source
1079 if (nDtaSrcIsColumns == -1) // set initial value to compare with below
1080 nDtaSrcIsColumns = nDirection;
1081 if (nDtaSrcIsColumns != nDirection)
1082 {
1083 nDtaSrcIsColumns = -2; // failed
1084 }
1085
1086 if (nDtaSrcIsColumns == 0 || nDtaSrcIsColumns == 1)
1087 {
1088 // build data to obtain 'SequenceMapping' later on
1089
1090 OSL_ENSURE( nDtaSrcIsColumns == 0 || /* rows */
1091 nDtaSrcIsColumns == 1, /* columns */
1092 "unexpected value for 'nDtaSrcIsColumns'" );
1093 pSequenceMapping[nDS1] = nDtaSrcIsColumns ? nFirstCol : nFirstRow;
1094
1095 // build data used to determine 'CellRangeRepresentation' later on
1096
1097 GetTableByName( *m_pDoc, aTableName, &pTableFormat, &pTable );
1098 if (!pTable || pTable->IsTableComplex())
1099 return aResult; // failed -> return empty property sequence
1100 nTableRows = pTable->GetTabLines().size();
1101 nTableCols = pTable->GetTabLines().front()->GetTabBoxes().size();
1102 aMap.resize( nTableRows );
1103 for (sal_Int32 i = 0; i < nTableRows; ++i)
1104 aMap[i].resize( nTableCols );
1105
1106 if (!aLabelStartCell.isEmpty() && !aLabelEndCell.isEmpty())
1107 {
1108 sal_Int32 nStartCol = -1, nStartRow = -1, nEndCol = -1, nEndRow = -1;
1109 SwXTextTable::GetCellPosition( aLabelStartCell, nStartCol, nStartRow );
1110 SwXTextTable::GetCellPosition( aLabelEndCell, nEndCol, nEndRow );
1111 if (nStartRow < 0 || nEndRow >= nTableRows ||
1112 nStartCol < 0 || nEndCol >= nTableCols)
1113 {
1114 return aResult; // failed -> return empty property sequence
1115 }
1116 for (sal_Int32 i = nStartRow; i <= nEndRow; ++i)
1117 {
1118 for (sal_Int32 k = nStartCol; k <= nEndCol; ++k)
1119 {
1120 char &rChar = aMap[i][k];
1121 if (rChar == '\0') // check for overlapping values and/or labels
1122 rChar = 'L';
1123 else
1124 return aResult; // failed -> return empty property sequence
1125 }
1126 }
1127 }
1128 if (!aValuesStartCell.isEmpty() && !aValuesEndCell.isEmpty())
1129 {
1130 sal_Int32 nStartCol = -1, nStartRow = -1, nEndCol = -1, nEndRow = -1;
1131 SwXTextTable::GetCellPosition( aValuesStartCell, nStartCol, nStartRow );
1132 SwXTextTable::GetCellPosition( aValuesEndCell, nEndCol, nEndRow );
1133 if (nStartRow < 0 || nEndRow >= nTableRows ||
1134 nStartCol < 0 || nEndCol >= nTableCols)
1135 {
1136 return aResult; // failed -> return empty property sequence
1137 }
1138 for (sal_Int32 i = nStartRow; i <= nEndRow; ++i)
1139 {
1140 for (sal_Int32 k = nStartCol; k <= nEndCol; ++k)
1141 {
1142 char &rChar = aMap[i][k];
1143 if (rChar == '\0') // check for overlapping values and/or labels
1144 rChar = 'x';
1145 else
1146 return aResult; // failed -> return empty property sequence
1147 }
1148 }
1149 }
1150 }
1151
1152#if OSL_DEBUG_LEVEL > 0
1153 // do some extra sanity checking that the length of the sequences
1154 // matches their range representation
1155 {
1156 sal_Int32 nStartRow = -1, nStartCol = -1, nEndRow = -1, nEndCol = -1;
1157 if (xCurLabel.is())
1158 {
1159 SwXTextTable::GetCellPosition( aLabelStartCell, nStartCol, nStartRow);
1160 SwXTextTable::GetCellPosition( aLabelEndCell, nEndCol, nEndRow);
1161 OSL_ENSURE( (nStartCol == nEndCol && (nEndRow - nStartRow + 1) == xCurLabel->getData().getLength()) ||
1162 (nStartRow == nEndRow && (nEndCol - nStartCol + 1) == xCurLabel->getData().getLength()),
1163 "label sequence length does not match range representation!" );
1164 }
1165 if (xCurValues.is())
1166 {
1167 SwXTextTable::GetCellPosition( aValuesStartCell, nStartCol, nStartRow);
1168 SwXTextTable::GetCellPosition( aValuesEndCell, nEndCol, nEndRow);
1169 OSL_ENSURE( (nStartCol == nEndCol && (nEndRow - nStartRow + 1) == xCurValues->getData().getLength()) ||
1170 (nStartRow == nEndRow && (nEndCol - nStartCol + 1) == xCurValues->getData().getLength()),
1171 "value sequence length does not match range representation!" );
1172 }
1173 }
1174#endif
1175 } // for
1176
1177 // build value for 'CellRangeRepresentation'
1178
1179 const OUString aCellRangeBase = aTableName + ".";
1180 OUString aCurRange;
1181 for (sal_Int32 i = 0; i < nTableRows; ++i)
1182 {
1183 for (sal_Int32 k = 0; k < nTableCols; ++k)
1184 {
1185 if (aMap[i][k] != '\0') // top-left cell of a sub-range found
1186 {
1187 // find rectangular sub-range to use
1188 sal_Int32 nRowIndex1 = i; // row index
1189 sal_Int32 nColIndex1 = k; // column index
1190 sal_Int32 nRowSubLen = 0;
1191 sal_Int32 nColSubLen = 0;
1192 while (nRowIndex1 < nTableRows && aMap[nRowIndex1++][k] != '\0')
1193 ++nRowSubLen;
1194 // be aware of shifted sequences!
1195 // (according to the checks done prior the length should be ok)
1196 while (nColIndex1 < nTableCols && aMap[i][nColIndex1] != '\0'
1197 && aMap[i + nRowSubLen-1][nColIndex1] != '\0')
1198 {
1199 ++nColIndex1;
1200 ++nColSubLen;
1201 }
1202 OUString aStartCell( sw_GetCellName( k, i ) );
1203 OUString aEndCell( sw_GetCellName( k + nColSubLen - 1, i + nRowSubLen - 1) );
1204 aCurRange = aCellRangeBase + aStartCell + ":" + aEndCell;
1205 if (!aCellRanges.isEmpty())
1206 aCellRanges += ";";
1207 aCellRanges += aCurRange;
1208
1209 // clear already found sub-range from map
1210 for (sal_Int32 nRowIndex2 = 0; nRowIndex2 < nRowSubLen; ++nRowIndex2)
1211 for (sal_Int32 nColumnIndex2 = 0; nColumnIndex2 < nColSubLen; ++nColumnIndex2)
1212 aMap[i + nRowIndex2][k + nColumnIndex2] = '\0';
1213 }
1214 }
1215 }
1216 // to be nice to the user we now sort the cell ranges according to
1217 // rows or columns depending on the direction used in the data source
1218 uno::Sequence< OUString > aSortedRanges;
1219 GetSubranges( aCellRanges, aSortedRanges, false /*sub ranges should already be normalized*/ );
1220 SortSubranges( aSortedRanges, (nDtaSrcIsColumns == 1) );
1221 OUString aSortedCellRanges;
1222 for (const OUString& rSortedRange : std::as_const(aSortedRanges))
1223 {
1224 if (!aSortedCellRanges.isEmpty())
1225 aSortedCellRanges += ";";
1226 aSortedCellRanges += rSortedRange;
1227 }
1228
1229 // build value for 'SequenceMapping'
1230
1231 uno::Sequence< sal_Int32 > aSortedMapping( aSequenceMapping );
1232 auto [begin, end] = asNonConstRange(aSortedMapping);
1233 std::sort(begin, end);
1234 bool bNeedSequenceMapping = false;
1235 for (sal_Int32 i = 0; i < aSequenceMapping.getLength(); ++i)
1236 {
1237 auto it = std::find( std::cbegin(aSortedMapping), std::cend(aSortedMapping),
1238 aSequenceMapping[i] );
1239 pSequenceMapping[i] = std::distance(std::cbegin(aSortedMapping), it);
1240
1241 if (i != std::as_const(aSequenceMapping)[i])
1242 bNeedSequenceMapping = true;
1243 }
1244
1245 // check if 'SequenceMapping' is actually not required...
1246 // (don't write unnecessary properties to the XML file)
1247 if (!bNeedSequenceMapping)
1248 aSequenceMapping.realloc(0);
1249
1250 // build resulting properties
1251
1252 OSL_ENSURE(nLabelSeqLen >= 0 || nLabelSeqLen == -2 /*not used*/,
1253 "unexpected value for 'nLabelSeqLen'" );
1254 bool bFirstCellIsLabel = false; // default value if 'nLabelSeqLen' could not properly determined
1255 if (nLabelSeqLen > 0) // == 0 means no label sequence in use
1256 bFirstCellIsLabel = true;
1257
1258 OSL_ENSURE( !aSortedCellRanges.isEmpty(), "CellRangeRepresentation missing" );
1259 const OUString aBrokenCellRangeForExport( GetBrokenCellRangeForExport( aSortedCellRanges ) );
1260
1261 aResult.realloc(5);
1262 auto pResult = aResult.getArray();
1263 sal_Int32 nProps = 0;
1264 pResult[nProps ].Name = "FirstCellAsLabel";
1265 pResult[nProps++].Value <<= bFirstCellIsLabel;
1266 pResult[nProps ].Name = "CellRangeRepresentation";
1267 pResult[nProps++].Value <<= aSortedCellRanges;
1268 if (!aBrokenCellRangeForExport.isEmpty())
1269 {
1270 pResult[nProps ].Name = "BrokenCellRangeForExport";
1271 pResult[nProps++].Value <<= aBrokenCellRangeForExport;
1272 }
1273 if (nDtaSrcIsColumns == 0 || nDtaSrcIsColumns == 1)
1274 {
1275 chart::ChartDataRowSource eDataRowSource = (nDtaSrcIsColumns == 1) ?
1276 chart::ChartDataRowSource_COLUMNS : chart::ChartDataRowSource_ROWS;
1277 pResult[nProps ].Name = "DataRowSource";
1278 pResult[nProps++].Value <<= eDataRowSource;
1279
1280 if (aSequenceMapping.hasElements())
1281 {
1282 pResult[nProps ].Name = "SequenceMapping";
1283 pResult[nProps++].Value <<= aSequenceMapping;
1284 }
1285 }
1286 aResult.realloc( nProps );
1287
1288 return aResult;
1289}
1290
1291uno::Reference< chart2::data::XDataSequence > SwChartDataProvider::Impl_createDataSequenceByRangeRepresentation(
1292 std::u16string_view rRangeRepresentation, bool bTestOnly )
1293{
1294 if (m_bDisposed)
1295 throw lang::DisposedException();
1296
1297 SwFrameFormat *pTableFormat = nullptr; // pointer to table format
1298 std::shared_ptr<SwUnoCursor> pUnoCursor; // pointer to new created cursor spanning the cell range
1299 GetFormatAndCreateCursorFromRangeRep( m_pDoc, rRangeRepresentation,
1300 &pTableFormat, pUnoCursor );
1301 if (!pTableFormat || !pUnoCursor)
1302 throw lang::IllegalArgumentException();
1303
1304 // check that cursors point and mark are in a single row or column.
1305 OUString aCellRange( GetCellRangeName( *pTableFormat, *pUnoCursor ) );
1306 SwRangeDescriptor aDesc;
1307 FillRangeDescriptor( aDesc, aCellRange );
1308 if (aDesc.nTop != aDesc.nBottom && aDesc.nLeft != aDesc.nRight)
1309 throw lang::IllegalArgumentException();
1310
1311 OSL_ENSURE( pTableFormat && pUnoCursor, "table format or cursor missing" );
1312 uno::Reference< chart2::data::XDataSequence > xDataSeq;
1313 if (!bTestOnly)
1314 xDataSeq = new SwChartDataSequence( *this, *pTableFormat, pUnoCursor );
1315
1316 return xDataSeq;
1317}
1318
1320 const OUString& rRangeRepresentation )
1321{
1322 SolarMutexGuard aGuard;
1323
1324 bool bPossible = true;
1325 try
1326 {
1327 Impl_createDataSequenceByRangeRepresentation( rRangeRepresentation, true );
1328 }
1329 catch (lang::IllegalArgumentException &)
1330 {
1331 bPossible = false;
1332 }
1333
1334 return bPossible;
1335}
1336
1337uno::Reference< chart2::data::XDataSequence > SAL_CALL SwChartDataProvider::createDataSequenceByRangeRepresentation(
1338 const OUString& rRangeRepresentation )
1339{
1340 SolarMutexGuard aGuard;
1341 return Impl_createDataSequenceByRangeRepresentation( rRangeRepresentation );
1342}
1343
1344uno::Reference< sheet::XRangeSelection > SAL_CALL SwChartDataProvider::getRangeSelection( )
1345{
1346 // note: it is no error to return nothing here
1347 return uno::Reference< sheet::XRangeSelection >();
1348}
1349
1350uno::Reference<css::chart2::data::XDataSequence> SAL_CALL
1352 const OUString& /*aRole*/, const OUString& /*aRangeRepresentation*/,
1353 const OUString& /*aRoleQualifier*/ )
1354{
1355 return uno::Reference<css::chart2::data::XDataSequence>();
1356}
1357
1359{
1360 bool bMustDispose( false );
1361 {
1362 std::unique_lock aGuard( GetChartMutex() );
1363 bMustDispose = !m_bDisposed;
1364 if (!m_bDisposed)
1365 m_bDisposed = true;
1366 }
1367 if (!bMustDispose)
1368 return;
1369
1370 // dispose all data-sequences
1371 for (const auto& rEntry : m_aDataSequences)
1372 {
1373 DisposeAllDataSequences( rEntry.first );
1374 }
1375 // release all references to data-sequences
1376 m_aDataSequences.clear();
1377
1378 // require listeners to release references to this object
1379 lang::EventObject aEvtObj( static_cast< chart2::data::XDataProvider * >(this) );
1380 std::unique_lock aGuard( GetChartMutex() );
1381 m_aEventListeners.disposeAndClear( aGuard, aEvtObj );
1382}
1383
1385 const uno::Reference< lang::XEventListener >& rxListener )
1386{
1387 std::unique_lock aGuard( GetChartMutex() );
1388 if (!m_bDisposed && rxListener.is())
1389 m_aEventListeners.addInterface( aGuard, rxListener );
1390}
1391
1393 const uno::Reference< lang::XEventListener >& rxListener )
1394{
1395 std::unique_lock aGuard( GetChartMutex() );
1396 if (!m_bDisposed && rxListener.is())
1397 m_aEventListeners.removeInterface( aGuard, rxListener );
1398}
1399
1401{
1402 return "SwChartDataProvider";
1403}
1404
1405sal_Bool SAL_CALL SwChartDataProvider::supportsService(const OUString& rServiceName )
1406{
1407 return cppu::supportsService(this, rServiceName);
1408}
1409
1410uno::Sequence< OUString > SAL_CALL SwChartDataProvider::getSupportedServiceNames( )
1411{
1412 return { "com.sun.star.chart2.data.DataProvider"};
1413}
1414
1415void SwChartDataProvider::AddDataSequence( const SwTable &rTable, uno::Reference< chart2::data::XDataSequence > const &rxDataSequence )
1416{
1417 m_aDataSequences[ &rTable ].insert( rxDataSequence );
1418}
1419
1420void SwChartDataProvider::RemoveDataSequence( const SwTable &rTable, uno::Reference< chart2::data::XDataSequence > const &rxDataSequence )
1421{
1422 m_aDataSequences[ &rTable ].erase( rxDataSequence );
1423}
1424
1425void SwChartDataProvider::InvalidateTable( const SwTable *pTable, bool bImmediate )
1426{
1427 OSL_ENSURE( pTable, "table pointer is NULL" );
1428 if (!pTable)
1429 return;
1430
1431 if (!m_bDisposed)
1433
1434 const Set_DataSequenceRef_t &rSet = m_aDataSequences[ pTable ];
1435 for (const auto& rItem : rSet)
1436 {
1437 uno::Reference< chart2::data::XDataSequence > xTemp(rItem); // temporary needed for g++ 3.3.5
1438 uno::Reference< util::XModifiable > xRef( xTemp, uno::UNO_QUERY );
1439 if (xRef.is())
1440 {
1441 // mark the sequence as 'dirty' and notify listeners
1442 xRef->setModified( true );
1443 }
1444 }
1445
1446 // tdf#122995 added Immediate-mode to allow non-timer-delayed Chart invalidation
1447 if (bImmediate && !m_bDisposed)
1449}
1450
1451void SwChartDataProvider::DeleteBox( const SwTable *pTable, const SwTableBox &rBox )
1452{
1453 OSL_ENSURE( pTable, "table pointer is NULL" );
1454 if (!pTable)
1455 return;
1456
1457 if (!m_bDisposed)
1459
1461
1462 // iterate over all data-sequences for that table...
1463 Set_DataSequenceRef_t::iterator aIt( rSet.begin() );
1464 Set_DataSequenceRef_t::iterator aEndIt( rSet.end() );
1465 Set_DataSequenceRef_t::iterator aDelIt; // iterator used for deletion when appropriate
1466 while (aIt != aEndIt)
1467 {
1468 SwChartDataSequence *pDataSeq = nullptr;
1469 bool bNowEmpty = false;
1470 bool bSeqDisposed = false;
1471
1472 // check if weak reference is still valid...
1473 uno::Reference< chart2::data::XDataSequence > xTemp(*aIt);
1474 if (xTemp.is())
1475 {
1476 // then delete that table box (check if implementation cursor needs to be adjusted)
1477 pDataSeq = static_cast< SwChartDataSequence * >( xTemp.get() );
1478 if (pDataSeq)
1479 {
1480 try
1481 {
1482 bNowEmpty = pDataSeq->DeleteBox( rBox );
1483 }
1484 catch (const lang::DisposedException&)
1485 {
1486 bNowEmpty = true;
1487 bSeqDisposed = true;
1488 }
1489
1490 if (bNowEmpty)
1491 aDelIt = aIt;
1492 }
1493 }
1494 ++aIt;
1495
1496 if (bNowEmpty)
1497 {
1498 rSet.erase( aDelIt );
1499 if (pDataSeq && !bSeqDisposed)
1500 pDataSeq->dispose(); // the current way to tell chart that sth. got removed
1501 }
1502 }
1503}
1504
1506{
1507 OSL_ENSURE( pTable, "table pointer is NULL" );
1508 if (!pTable)
1509 return;
1510
1511 if (!m_bDisposed)
1513
1518 const Set_DataSequenceRef_t aSet( m_aDataSequences[ pTable ] );
1519
1520 for (const auto& rItem : aSet)
1521 {
1522 uno::Reference< chart2::data::XDataSequence > xTemp(rItem); // temporary needed for g++ 3.3.5
1523 uno::Reference< lang::XComponent > xRef( xTemp, uno::UNO_QUERY );
1524 if (xRef.is())
1525 {
1526 xRef->dispose();
1527 }
1528 }
1529}
1530
1553 const SwTable &rTable,
1554 const SwSelBoxes& rBoxes,
1555 sal_uInt16 nLines, bool bBehind )
1556{
1557 if (rTable.IsTableComplex())
1558 return;
1559
1560 const size_t nBoxes = rBoxes.size();
1561 if (nBoxes < 1 || nLines < 1)
1562 return;
1563
1564 SwTableBox* pFirstBox = rBoxes[0];
1565 SwTableBox* pLastBox = rBoxes.back();
1566
1567 if (!(pFirstBox && pLastBox))
1568 return;
1569
1570 sal_Int32 nFirstCol = -1, nFirstRow = -1, nLastCol = -1, nLastRow = -1;
1571 SwXTextTable::GetCellPosition( pFirstBox->GetName(), nFirstCol, nFirstRow );
1572 SwXTextTable::GetCellPosition( pLastBox->GetName(), nLastCol, nLastRow );
1573
1574 bool bAddCols = false; // default; also to be used if nBoxes == 1 :-/
1575 if (nFirstCol == nLastCol && nFirstRow != nLastRow)
1576 bAddCols = true;
1577 if (nFirstCol != nLastCol && nFirstRow != nLastRow)
1578 return;
1579
1580 //get range of indices in col/rows for new cells
1581 sal_Int32 nFirstNewCol = nFirstCol;
1582 sal_Int32 nFirstNewRow = bBehind ? nFirstRow + 1 : nFirstRow - nLines;
1583 if (bAddCols)
1584 {
1585 OSL_ENSURE( nFirstCol == nLastCol, "column indices seem broken" );
1586 nFirstNewCol = bBehind ? nFirstCol + 1 : nFirstCol - nLines;
1587 nFirstNewRow = nFirstRow;
1588 }
1589
1590 // iterate over all data-sequences for the table
1591 const Set_DataSequenceRef_t &rSet = m_aDataSequences[ &rTable ];
1592 for (const auto& rItem : rSet)
1593 {
1594 uno::Reference< chart2::data::XDataSequence > xTemp(rItem); // temporary needed for g++ 3.3.5
1595 uno::Reference< chart2::data::XTextualDataSequence > xRef( xTemp, uno::UNO_QUERY );
1596 if (xRef.is())
1597 {
1598 const sal_Int32 nLen = xRef->getTextualData().getLength();
1599 if (nLen > 1) // value data-sequence ?
1600 {
1601 auto pDataSeq = comphelper::getFromUnoTunnel<SwChartDataSequence>(xRef);
1602 if (pDataSeq)
1603 {
1604 SwRangeDescriptor aDesc;
1605 pDataSeq->FillRangeDesc( aDesc );
1606
1607 chart::ChartDataRowSource eDRSource = chart::ChartDataRowSource_COLUMNS;
1608 if (aDesc.nTop == aDesc.nBottom && aDesc.nLeft != aDesc.nRight)
1609 eDRSource = chart::ChartDataRowSource_ROWS;
1610
1611 if (!bAddCols && eDRSource == chart::ChartDataRowSource_COLUMNS)
1612 {
1613 // add rows: extend affected columns by newly added row cells
1614 pDataSeq->ExtendTo( true, nFirstNewRow, nLines );
1615 }
1616 else if (bAddCols && eDRSource == chart::ChartDataRowSource_ROWS)
1617 {
1618 // add cols: extend affected rows by newly added column cells
1619 pDataSeq->ExtendTo( false, nFirstNewCol, nLines );
1620 }
1621 }
1622 }
1623 }
1624 }
1625}
1626
1627// XRangeXMLConversion
1628OUString SAL_CALL SwChartDataProvider::convertRangeToXML( const OUString& rRangeRepresentation )
1629{
1630 SolarMutexGuard aGuard;
1631 if (m_bDisposed)
1632 throw lang::DisposedException();
1633
1634 if (rRangeRepresentation.isEmpty())
1635 return OUString();
1636
1637 OUStringBuffer aRes;
1638
1639 // multiple ranges are delimited by a ';' like in
1640 // "Table1.A1:A4;Table1.C2:C5" the same table must be used in all ranges!
1641 SwTable* pFirstFoundTable = nullptr; // to check that only one table will be used
1642 sal_Int32 nPos = 0;
1643 do {
1644 const OUString aRange( rRangeRepresentation.getToken(0, ';', nPos) );
1645 SwFrameFormat *pTableFormat = nullptr; // pointer to table format
1646 std::shared_ptr<SwUnoCursor> pCursor;
1647 GetFormatAndCreateCursorFromRangeRep( m_pDoc, aRange, &pTableFormat, pCursor );
1648 if (!pTableFormat)
1649 throw lang::IllegalArgumentException();
1650 SwTable* pTable = SwTable::FindTable( pTableFormat );
1651 if (pTable->IsTableComplex())
1652 throw uno::RuntimeException("Table too complex.");
1653
1654 // check that there is only one table used in all ranges
1655 if (!pFirstFoundTable)
1656 pFirstFoundTable = pTable;
1657 if (pTable != pFirstFoundTable)
1658 throw lang::IllegalArgumentException();
1659
1660 OUString aTableName;
1661 OUString aStartCell;
1662 OUString aEndCell;
1663 if (!GetTableAndCellsFromRangeRep( aRange, aTableName, aStartCell, aEndCell ))
1664 throw lang::IllegalArgumentException();
1665
1666 sal_Int32 nCol, nRow;
1667 SwXTextTable::GetCellPosition( aStartCell, nCol, nRow );
1668 if (nCol < 0 || nRow < 0)
1669 throw uno::RuntimeException("Cell not found.");
1670
1673 XMLRangeHelper::CellRange aCellRange;
1674 aCellRange.aTableName = aTableName;
1675 aCellRange.aUpperLeft.nColumn = nCol;
1676 aCellRange.aUpperLeft.nRow = nRow;
1677 aCellRange.aUpperLeft.bIsEmpty = false;
1678 if (aStartCell != aEndCell && !aEndCell.isEmpty())
1679 {
1680 SwXTextTable::GetCellPosition( aEndCell, nCol, nRow );
1681 if (nCol < 0 || nRow < 0)
1682 throw uno::RuntimeException("Cell not found.");
1683
1684 aCellRange.aLowerRight.nColumn = nCol;
1685 aCellRange.aLowerRight.nRow = nRow;
1686 aCellRange.aLowerRight.bIsEmpty = false;
1687 }
1688 OUString aTmp( XMLRangeHelper::getXMLStringFromCellRange( aCellRange ) );
1689 if (!aRes.isEmpty()) // in case of multiple ranges add delimiter
1690 aRes.append(" ");
1691 aRes.append(aTmp);
1692 }
1693 while (nPos>0);
1694
1695 return aRes.makeStringAndClear();
1696}
1697
1698OUString SAL_CALL SwChartDataProvider::convertRangeFromXML( const OUString& rXMLRange )
1699{
1700 SolarMutexGuard aGuard;
1701 if (m_bDisposed)
1702 throw lang::DisposedException();
1703
1704 if (rXMLRange.isEmpty())
1705 return OUString();
1706
1707 OUStringBuffer aRes;
1708
1709 // multiple ranges are delimited by a ' ' like in
1710 // "Table1.$A$1:.$A$4 Table1.$C$2:.$C$5" the same table must be used in all ranges!
1711 OUString aFirstFoundTable; // to check that only one table will be used
1712 sal_Int32 nPos = 0;
1713 do
1714 {
1715 OUString aRange( rXMLRange.getToken(0, ' ', nPos) );
1716
1720
1721 // check that there is only one table used in all ranges
1722 if (aFirstFoundTable.isEmpty())
1723 aFirstFoundTable = aCellRange.aTableName;
1724 if (aCellRange.aTableName != aFirstFoundTable)
1725 throw lang::IllegalArgumentException();
1726
1727 OUString aTmp = aCellRange.aTableName + "." +
1728 sw_GetCellName( aCellRange.aUpperLeft.nColumn,
1729 aCellRange.aUpperLeft.nRow );
1730 // does cell range consist of more than a single cell?
1731 if (!aCellRange.aLowerRight.bIsEmpty)
1732 {
1733 aTmp += ":" + sw_GetCellName( aCellRange.aLowerRight.nColumn,
1734 aCellRange.aLowerRight.nRow );
1735 }
1736
1737 if (!aRes.isEmpty()) // in case of multiple ranges add delimiter
1738 aRes.append(";");
1739 aRes.append(aTmp);
1740 }
1741 while (nPos>0);
1742
1743 return aRes.makeStringAndClear();
1744}
1745
1747 const uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > &rLDS ) :
1748 m_aLDS( rLDS )
1749{
1750}
1751
1753{
1754}
1755
1756uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > SAL_CALL SwChartDataSource::getDataSequences( )
1757{
1758 SolarMutexGuard aGuard;
1759 return m_aLDS;
1760}
1761
1763{
1764 return "SwChartDataSource";
1765}
1766
1767sal_Bool SAL_CALL SwChartDataSource::supportsService(const OUString& rServiceName )
1768{
1769 return cppu::supportsService(this, rServiceName);
1770}
1771
1772uno::Sequence< OUString > SAL_CALL SwChartDataSource::getSupportedServiceNames( )
1773{
1774 return { "com.sun.star.chart2.data.DataSource" };
1775}
1776
1778 SwChartDataProvider& rProvider,
1779 SwFrameFormat& rTableFormat,
1780 const std::shared_ptr<SwUnoCursor>& pTableCursor ) :
1781 m_pFormat(&rTableFormat),
1782 m_aRowLabelText( SwResId( STR_CHART2_ROW_LABEL_TEXT ) ),
1783 m_aColLabelText( SwResId( STR_CHART2_COL_LABEL_TEXT ) ),
1784 m_xDataProvider( &rProvider ),
1785 m_pTableCursor( pTableCursor ),
1786 m_pPropSet( aSwMapProvider.GetPropertySet( PROPERTY_MAP_CHART2_DATA_SEQUENCE ) )
1787{
1788 StartListening(rTableFormat.GetNotifier());
1789 m_bDisposed = false;
1790
1791 acquire();
1792 try
1793 {
1794 const SwTable* pTable = SwTable::FindTable( &rTableFormat );
1795 if (pTable)
1796 {
1797 uno::Reference< chart2::data::XDataSequence > xRef(this);
1798 m_xDataProvider->AddDataSequence( *pTable, xRef );
1799 m_xDataProvider->addEventListener( static_cast< lang::XEventListener * >(this) );
1800 }
1801 else {
1802 OSL_FAIL( "table missing" );
1803 }
1804 }
1805 catch (uno::RuntimeException &)
1806 {
1807 // TODO: shouldn't there be a call to release() here?
1808 throw;
1809 }
1810 catch (uno::Exception &)
1811 {
1812 }
1813 release();
1814
1815#if OSL_DEBUG_LEVEL > 0
1816 // check if it can properly convert into a SwUnoTableCursor
1817 // which is required for some functions
1818 SwUnoTableCursor* pUnoTableCursor = dynamic_cast<SwUnoTableCursor*>(&(*m_pTableCursor));
1819 OSL_ENSURE(pUnoTableCursor, "SwChartDataSequence: cursor not SwUnoTableCursor");
1820#endif
1821}
1822
1825 SvtListener(),
1826 m_pFormat( rObj.m_pFormat ),
1827 m_aRole( rObj.m_aRole ),
1828 m_aRowLabelText( SwResId(STR_CHART2_ROW_LABEL_TEXT) ),
1829 m_aColLabelText( SwResId(STR_CHART2_COL_LABEL_TEXT) ),
1830 m_xDataProvider( rObj.m_xDataProvider ),
1831 m_pTableCursor( rObj.m_pTableCursor ),
1832 m_pPropSet( rObj.m_pPropSet )
1833{
1834 if(m_pFormat)
1836 m_bDisposed = false;
1837
1838 acquire();
1839 try
1840 {
1841 const SwTable* pTable = SwTable::FindTable( GetFrameFormat() );
1842 if (pTable)
1843 {
1844 uno::Reference< chart2::data::XDataSequence > xRef(this);
1845 m_xDataProvider->AddDataSequence( *pTable, xRef );
1846 m_xDataProvider->addEventListener( static_cast< lang::XEventListener * >(this) );
1847 }
1848 else {
1849 OSL_FAIL( "table missing" );
1850 }
1851 }
1852 catch (uno::RuntimeException &)
1853 {
1854 // TODO: shouldn't there be a call to release() here?
1855 throw;
1856 }
1857 catch (uno::Exception &)
1858 {
1859 }
1860 release();
1861
1862#if OSL_DEBUG_LEVEL > 0
1863 // check if it can properly convert into a SwUnoTableCursor
1864 // which is required for some functions
1865 SwUnoTableCursor* pUnoTableCursor = dynamic_cast<SwUnoTableCursor*>(&(*m_pTableCursor));
1866 OSL_ENSURE(pUnoTableCursor, "SwChartDataSequence: cursor not SwUnoTableCursor");
1867#endif
1868}
1869
1871{
1872}
1873
1874const uno::Sequence< sal_Int8 > & SwChartDataSequence::getUnoTunnelId()
1875{
1876 static const comphelper::UnoIdInit theSwChartDataSequenceUnoTunnelId;
1877 return theSwChartDataSequenceUnoTunnelId.getSeq();
1878}
1879
1880sal_Int64 SAL_CALL SwChartDataSequence::getSomething( const uno::Sequence< sal_Int8 > &rId )
1881{
1882 return comphelper::getSomethingImpl(rId, this);
1883}
1884
1885
1887{
1888 SolarMutexGuard aGuard;
1889 if (m_bDisposed)
1890 throw lang::DisposedException();
1891
1892 OUString aRes;
1893 SwFrameFormat* pTableFormat = GetFrameFormat();
1894 if (pTableFormat)
1895 {
1896 const OUString aCellRange( GetCellRangeName( *pTableFormat, *m_pTableCursor ) );
1897 OSL_ENSURE( !aCellRange.isEmpty(), "failed to get cell range" );
1898 aRes = pTableFormat->GetName() + "." + aCellRange;
1899 }
1900 return aRes;
1901}
1902
1903uno::Sequence< OUString > SAL_CALL SwChartDataSequence::generateLabel(
1904 chart2::data::LabelOrigin eLabelOrigin )
1905{
1906 SolarMutexGuard aGuard;
1907 if (m_bDisposed)
1908 throw lang::DisposedException();
1909
1910 uno::Sequence< OUString > aLabels;
1911
1912 {
1913 SwRangeDescriptor aDesc;
1914 bool bOk = false;
1915 SwFrameFormat* pTableFormat = GetFrameFormat();
1916 if (!pTableFormat)
1917 throw uno::RuntimeException("No table format found.");
1918 SwTable* pTable = SwTable::FindTable( pTableFormat );
1919 if (!pTable)
1920 throw uno::RuntimeException("No table found.");
1921 if (pTable->IsTableComplex())
1922 throw uno::RuntimeException("Table too complex.");
1923
1924 const OUString aCellRange( GetCellRangeName( *pTableFormat, *m_pTableCursor ) );
1925 OSL_ENSURE( !aCellRange.isEmpty(), "failed to get cell range" );
1926 bOk = FillRangeDescriptor( aDesc, aCellRange );
1927 OSL_ENSURE( bOk, "failed to get SwRangeDescriptor" );
1928
1929 if (bOk)
1930 {
1931 aDesc.Normalize();
1932 sal_Int32 nColSpan = aDesc.nRight - aDesc.nLeft + 1;
1933 sal_Int32 nRowSpan = aDesc.nBottom - aDesc.nTop + 1;
1934 OSL_ENSURE( nColSpan == 1 || nRowSpan == 1,
1935 "unexpected range of selected cells" );
1936
1937 OUString aText; // label text to be returned
1938 bool bReturnEmptyText = false;
1939 bool bUseCol = true;
1940 if (eLabelOrigin == chart2::data::LabelOrigin_COLUMN)
1941 bUseCol = true;
1942 else if (eLabelOrigin == chart2::data::LabelOrigin_ROW)
1943 bUseCol = false;
1944 else if (eLabelOrigin == chart2::data::LabelOrigin_SHORT_SIDE)
1945 {
1946 bUseCol = nColSpan < nRowSpan;
1947 bReturnEmptyText = nColSpan == nRowSpan;
1948 }
1949 else if (eLabelOrigin == chart2::data::LabelOrigin_LONG_SIDE)
1950 {
1951 bUseCol = nColSpan > nRowSpan;
1952 bReturnEmptyText = nColSpan == nRowSpan;
1953 }
1954 else {
1955 OSL_FAIL( "unexpected case" );
1956 }
1957
1958 // build label sequence
1959
1960 sal_Int32 nSeqLen = bUseCol ? nColSpan : nRowSpan;
1961 aLabels.realloc( nSeqLen );
1962 OUString *pLabels = aLabels.getArray();
1963 for (sal_Int32 i = 0; i < nSeqLen; ++i)
1964 {
1965 if (!bReturnEmptyText)
1966 {
1967 aText = bUseCol ? m_aColLabelText : m_aRowLabelText;
1968 sal_Int32 nCol = aDesc.nLeft;
1969 sal_Int32 nRow = aDesc.nTop;
1970 if (bUseCol)
1971 nCol = nCol + i;
1972 else
1973 nRow = nRow + i;
1974 OUString aCellName( sw_GetCellName( nCol, nRow ) );
1975
1976 sal_Int32 nLen = aCellName.getLength();
1977 if (nLen)
1978 {
1979 const sal_Unicode *pBuf = aCellName.getStr();
1980 const sal_Unicode *pEnd = pBuf + nLen;
1981 while (pBuf < pEnd && ('0' > *pBuf || *pBuf > '9'))
1982 ++pBuf;
1983 // start of number found?
1984 if (pBuf < pEnd && ('0' <= *pBuf && *pBuf <= '9'))
1985 {
1986 OUString aRplc;
1987 std::u16string_view aNew;
1988 if (bUseCol)
1989 {
1990 aRplc = "%COLUMNLETTER";
1991 aNew = aCellName.subView(0, pBuf - aCellName.getStr());
1992 }
1993 else
1994 {
1995 aRplc = "%ROWNUMBER";
1996 aNew = std::u16string_view(pBuf, (aCellName.getStr() + nLen) - pBuf);
1997 }
1998 aText = aText.replaceFirst( aRplc, aNew );
1999 }
2000 }
2001 }
2002 pLabels[i] = aText;
2003 }
2004 }
2005 }
2006
2007 return aLabels;
2008}
2009
2011 ::sal_Int32 /*nIndex*/ )
2012{
2013 return 0;
2014}
2015
2016std::vector< css::uno::Reference< css::table::XCell > > SwChartDataSequence::GetCells()
2017{
2018 if (m_bDisposed)
2019 throw lang::DisposedException();
2020 auto pTableFormat(GetFrameFormat());
2021 if(!pTableFormat)
2022 return std::vector< css::uno::Reference< css::table::XCell > >();
2023 auto pTable(SwTable::FindTable(pTableFormat));
2024 if(pTable->IsTableComplex())
2025 return std::vector< css::uno::Reference< css::table::XCell > >();
2026 SwRangeDescriptor aDesc;
2027 if(!FillRangeDescriptor(aDesc, GetCellRangeName(*pTableFormat, *m_pTableCursor)))
2028 return std::vector< css::uno::Reference< css::table::XCell > >();
2029 return SwXCellRange::CreateXCellRange(m_pTableCursor, *pTableFormat, aDesc)->GetCells();
2030}
2031
2032uno::Sequence< OUString > SAL_CALL SwChartDataSequence::getTextualData()
2033{
2034 SolarMutexGuard aGuard;
2035 auto vCells(GetCells());
2036 uno::Sequence< OUString > vTextData(vCells.size());
2037 std::transform(vCells.begin(),
2038 vCells.end(),
2039 vTextData.getArray(),
2040 [] (decltype(vCells)::value_type& xCell)
2041 { return static_cast<SwXCell*>(xCell.get())->getString(); });
2042 return vTextData;
2043}
2044
2045uno::Sequence< uno::Any > SAL_CALL SwChartDataSequence::getData()
2046{
2047 SolarMutexGuard aGuard;
2048 auto vCells(GetCells());
2049 uno::Sequence< uno::Any > vAnyData(vCells.size());
2050 std::transform(vCells.begin(),
2051 vCells.end(),
2052 vAnyData.getArray(),
2053 [] (decltype(vCells)::value_type& xCell)
2054 { return static_cast<SwXCell*>(xCell.get())->GetAny(); });
2055 return vAnyData;
2056}
2057
2058uno::Sequence< double > SAL_CALL SwChartDataSequence::getNumericalData()
2059{
2060 SolarMutexGuard aGuard;
2061 auto vCells(GetCells());
2062 uno::Sequence< double > vNumData(vCells.size());
2063 std::transform(vCells.begin(),
2064 vCells.end(),
2065 vNumData.getArray(),
2066 [] (decltype(vCells)::value_type& xCell)
2067 { return static_cast<SwXCell*>(xCell.get())->GetForcedNumericalValue(); });
2068 return vNumData;
2069}
2070
2071uno::Reference< util::XCloneable > SAL_CALL SwChartDataSequence::createClone( )
2072{
2073 SolarMutexGuard aGuard;
2074 if (m_bDisposed)
2075 throw lang::DisposedException();
2076 return new SwChartDataSequence( *this );
2077}
2078
2079uno::Reference< beans::XPropertySetInfo > SAL_CALL SwChartDataSequence::getPropertySetInfo( )
2080{
2081 SolarMutexGuard aGuard;
2082 if (m_bDisposed)
2083 throw lang::DisposedException();
2084
2085 static uno::Reference< beans::XPropertySetInfo > xRes = m_pPropSet->getPropertySetInfo();
2086 return xRes;
2087}
2088
2090 const OUString& rPropertyName,
2091 const uno::Any& rValue )
2092{
2093 SolarMutexGuard aGuard;
2094 if (m_bDisposed)
2095 throw lang::DisposedException();
2096
2097 if (rPropertyName != UNO_NAME_ROLE)
2098 throw beans::UnknownPropertyException(rPropertyName);
2099
2100 if ( !(rValue >>= m_aRole) )
2101 throw lang::IllegalArgumentException();
2102}
2103
2105 const OUString& rPropertyName )
2106{
2107 SolarMutexGuard aGuard;
2108 if (m_bDisposed)
2109 throw lang::DisposedException();
2110
2111 if (!(rPropertyName == UNO_NAME_ROLE))
2112 throw beans::UnknownPropertyException(rPropertyName);
2113
2114 return uno::Any(m_aRole);
2115}
2116
2118 const OUString& /*rPropertyName*/,
2119 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
2120{
2121 OSL_FAIL( "not implemented" );
2122}
2123
2125 const OUString& /*rPropertyName*/,
2126 const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
2127{
2128 OSL_FAIL( "not implemented" );
2129}
2130
2132 const OUString& /*rPropertyName*/,
2133 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/ )
2134{
2135 OSL_FAIL( "not implemented" );
2136}
2137
2139 const OUString& /*rPropertyName*/,
2140 const uno::Reference< beans::XVetoableChangeListener >& /*xListener*/ )
2141{
2142 OSL_FAIL( "not implemented" );
2143}
2144
2146{
2147 return "SwChartDataSequence";
2148}
2149
2150sal_Bool SAL_CALL SwChartDataSequence::supportsService(const OUString& rServiceName )
2151{
2152 return cppu::supportsService(this, rServiceName);
2153}
2154
2155uno::Sequence< OUString > SAL_CALL SwChartDataSequence::getSupportedServiceNames( )
2156{
2157 return { "com.sun.star.chart2.data.DataSequence" };
2158}
2159
2161{
2162 if(rHint.GetId() == SfxHintId::Dying)
2163 m_pFormat = nullptr;
2164 if(!m_pFormat || !m_pTableCursor)
2165 {
2166 m_pFormat = nullptr;
2167 m_pTableCursor.reset(nullptr);
2168 dispose();
2169 }
2170 else if (rHint.GetId() == SfxHintId::SwLegacyModify)
2171 {
2172 setModified( true );
2173 }
2174}
2175
2177{
2178 SolarMutexGuard aGuard;
2179 if (m_bDisposed)
2180 throw lang::DisposedException();
2181
2182 return true;
2183}
2184
2186 sal_Bool bModified )
2187{
2188 SolarMutexGuard aGuard;
2189 if (m_bDisposed)
2190 throw lang::DisposedException();
2191
2192 if (bModified)
2193 LaunchModifiedEvent( m_aModifyListeners, static_cast< XModifyBroadcaster * >(this) );
2194}
2195
2197 const uno::Reference< util::XModifyListener >& rxListener )
2198{
2199 std::unique_lock aGuard( GetChartMutex() );
2200 if (!m_bDisposed && rxListener.is())
2201 m_aModifyListeners.addInterface( aGuard, rxListener );
2202}
2203
2205 const uno::Reference< util::XModifyListener >& rxListener )
2206{
2207 std::unique_lock aGuard( GetChartMutex() );
2208 if (!m_bDisposed && rxListener.is())
2209 m_aModifyListeners.removeInterface( aGuard, rxListener );
2210}
2211
2212void SAL_CALL SwChartDataSequence::disposing( const lang::EventObject& rSource )
2213{
2214 if (m_bDisposed)
2215 throw lang::DisposedException();
2216 if (rSource.Source == static_cast<cppu::OWeakObject*>(m_xDataProvider.get()))
2217 {
2218 m_xDataProvider.clear();
2219 }
2220}
2221
2223{
2224 bool bMustDispose( false );
2225 {
2226 std::unique_lock aGuard( GetChartMutex() );
2227 bMustDispose = !m_bDisposed;
2228 if (!m_bDisposed)
2229 m_bDisposed = true;
2230 }
2231 if (!bMustDispose)
2232 return;
2233
2234 m_bDisposed = true;
2235 if (m_xDataProvider.is())
2236 {
2237 const SwTable* pTable = SwTable::FindTable( GetFrameFormat() );
2238 if (pTable)
2239 {
2240 uno::Reference< chart2::data::XDataSequence > xRef(this);
2241 m_xDataProvider->RemoveDataSequence( *pTable, xRef );
2242 }
2243 else {
2244 OSL_FAIL( "table missing" );
2245 }
2246
2247 //#i119653# The bug is crashed for an exception thrown by
2248 //SwCharDataSequence::setModified() because
2249 //the SwCharDataSequence object has been disposed.
2250
2251 //Actually, the former design of SwClient will disconnect itself
2252 //from the notification list in its destructor.
2253
2254 //But the SwCharDataSequence won't be destructed but disposed in code
2255 //(the data member SwChartDataSequence::bDisposed will be set to
2256 //TRUE), the relationship between client and modification is not
2257 //released.
2258
2259 //So any notification from modify object will lead to said
2260 //exception threw out. Recorrect the logic of code in
2261 //SwChartDataSequence::Dispose(), release the relationship
2262 //here...
2264 {
2266 m_pFormat = nullptr;
2267 m_pTableCursor.reset(nullptr);
2268 }
2269 }
2270
2271 // require listeners to release references to this object
2272 lang::EventObject aEvtObj( static_cast< chart2::data::XDataSequence * >(this) );
2273 std::unique_lock aGuard( GetChartMutex() );
2274 m_aModifyListeners.disposeAndClear( aGuard, aEvtObj );
2275 m_aEvtListeners.disposeAndClear( aGuard, aEvtObj );
2276}
2277
2279 const uno::Reference< lang::XEventListener >& rxListener )
2280{
2281 std::unique_lock aGuard( GetChartMutex() );
2282 if (!m_bDisposed && rxListener.is())
2283 m_aEvtListeners.addInterface( aGuard, rxListener );
2284}
2285
2287 const uno::Reference< lang::XEventListener >& rxListener )
2288{
2289 std::unique_lock aGuard( GetChartMutex() );
2290 if (!m_bDisposed && rxListener.is())
2291 m_aEvtListeners.removeInterface( aGuard, rxListener );
2292}
2293
2295{
2296 if (m_bDisposed)
2297 throw lang::DisposedException();
2298
2299 // to be set if the last box of the data-sequence was removed here
2300 bool bNowEmpty = false;
2301
2302 // if the implementation cursor gets affected (i.e. the box where it is located
2303 // in gets removed) we need to move it before that... (otherwise it does not need to change)
2304
2305 const SwStartNode* pPointStartNode = m_pTableCursor->GetPoint()->GetNode().FindTableBoxStartNode();
2306 const SwStartNode* pMarkStartNode = m_pTableCursor->GetMark()->GetNode().FindTableBoxStartNode();
2307
2308 if (!m_pTableCursor->HasMark() || (pPointStartNode == rBox.GetSttNd() && pMarkStartNode == rBox.GetSttNd()))
2309 {
2310 bNowEmpty = true;
2311 }
2312 else if (pPointStartNode == rBox.GetSttNd() || pMarkStartNode == rBox.GetSttNd())
2313 {
2314 sal_Int32 nPointRow = -1, nPointCol = -1;
2315 sal_Int32 nMarkRow = -1, nMarkCol = -1;
2316 const SwTable* pTable = SwTable::FindTable( GetFrameFormat() );
2317 OUString aPointCellName( pTable->GetTableBox( pPointStartNode->GetIndex() )->GetName() );
2318 OUString aMarkCellName( pTable->GetTableBox( pMarkStartNode->GetIndex() )->GetName() );
2319
2320 SwXTextTable::GetCellPosition( aPointCellName, nPointCol, nPointRow );
2321 SwXTextTable::GetCellPosition( aMarkCellName, nMarkCol, nMarkRow );
2322 OSL_ENSURE( nPointRow >= 0 && nPointCol >= 0, "invalid row and col" );
2323 OSL_ENSURE( nMarkRow >= 0 && nMarkCol >= 0, "invalid row and col" );
2324
2325 // move vertical or horizontal?
2326 OSL_ENSURE( nPointRow == nMarkRow || nPointCol == nMarkCol,
2327 "row/col indices not matching" );
2328 OSL_ENSURE( nPointRow != nMarkRow || nPointCol != nMarkCol,
2329 "point and mark are identical" );
2330 bool bMoveVertical = (nPointCol == nMarkCol);
2331 bool bMoveHorizontal = (nPointRow == nMarkRow);
2332
2333 // get movement direction
2334 bool bMoveLeft = false; // move left or right?
2335 bool bMoveUp = false; // move up or down?
2336 if (bMoveVertical)
2337 {
2338 if (pPointStartNode == rBox.GetSttNd()) // move point?
2339 bMoveUp = nPointRow > nMarkRow;
2340 else // move mark
2341 bMoveUp = nMarkRow > nPointRow;
2342 }
2343 else if (bMoveHorizontal)
2344 {
2345 if (pPointStartNode == rBox.GetSttNd()) // move point?
2346 bMoveLeft = nPointCol > nMarkCol;
2347 else // move mark
2348 bMoveLeft = nMarkCol > nPointCol;
2349 }
2350 else {
2351 OSL_FAIL( "neither vertical nor horizontal movement" );
2352 }
2353
2354 // get new box (position) to use...
2355 sal_Int32 nRow = (pPointStartNode == rBox.GetSttNd()) ? nPointRow : nMarkRow;
2356 sal_Int32 nCol = (pPointStartNode == rBox.GetSttNd()) ? nPointCol : nMarkCol;
2357 if (bMoveVertical)
2358 nRow += bMoveUp ? -1 : +1;
2359 if (bMoveHorizontal)
2360 nCol += bMoveLeft ? -1 : +1;
2361 const OUString aNewCellName = sw_GetCellName( nCol, nRow );
2362 SwTableBox* pNewBox = const_cast<SwTableBox*>(pTable->GetTableBox( aNewCellName ));
2363
2364 if (pNewBox) // set new position (cell range) to use
2365 {
2366 // This is how you get the first content node of a row:
2367 // First get a SwNodeIndex pointing to the node after SwStartNode of the box...
2368 SwNodeIndex aIdx( *pNewBox->GetSttNd(), +1 );
2369 // This can be a SwContentNode, but might also be a table or section node,
2370 // therefore call GoNext
2371 SwContentNode *pCNd = aIdx.GetNode().GetContentNode();
2372 if (!pCNd)
2373 pCNd = GetFrameFormat()->GetDoc()->GetNodes().GoNext( &aIdx );
2374 // and then one can e.g. create a SwPosition:
2375 SwPosition aNewPos( *pCNd ); // new position to be used with cursor
2376
2377 // if the mark is to be changed, make sure there is one
2378 if (pMarkStartNode == rBox.GetSttNd() && !m_pTableCursor->HasMark())
2380
2381 // set cursor to new position
2382 SwPosition *pPos = (pPointStartNode == rBox.GetSttNd()) ?
2384 if (pPos)
2385 {
2386 *pPos = aNewPos;
2387 }
2388 else {
2389 OSL_FAIL( "neither point nor mark available for change" );
2390 }
2391 }
2392 else {
2393 OSL_FAIL( "failed to get position" );
2394 }
2395 }
2396
2397 return bNowEmpty;
2398}
2399
2401{
2402 SwFrameFormat* pTableFormat = GetFrameFormat();
2403 if(pTableFormat)
2404 {
2405 SwTable* pTable = SwTable::FindTable( pTableFormat );
2406 if(!pTable->IsTableComplex())
2407 {
2408 FillRangeDescriptor( rRangeDesc, GetCellRangeName( *pTableFormat, *m_pTableCursor ) );
2409 }
2410 }
2411}
2412
2427void SwChartDataSequence::ExtendTo( bool bExtendCol,
2428 sal_Int32 nFirstNew, sal_Int32 nCount )
2429{
2430 SwUnoTableCursor* pUnoTableCursor = dynamic_cast<SwUnoTableCursor*>(&(*m_pTableCursor));
2431 if (!pUnoTableCursor)
2432 return;
2433
2434 const SwStartNode *pStartNd = nullptr;
2435 const SwTableBox *pStartBox = nullptr;
2436 const SwTableBox *pEndBox = nullptr;
2437
2438 const SwTable* pTable = SwTable::FindTable( GetFrameFormat() );
2439 OSL_ENSURE( !pTable->IsTableComplex(), "table too complex" );
2440 if (nCount < 1 || nFirstNew < 0 || pTable->IsTableComplex())
2441 return;
2442
2443 // get range descriptor (cell range) for current data-sequence
2444
2445 pStartNd = pUnoTableCursor->GetPoint()->GetNode().FindTableBoxStartNode();
2446 pEndBox = pTable->GetTableBox( pStartNd->GetIndex() );
2447 const OUString aEndBox( pEndBox->GetName() );
2448
2449 pStartNd = pUnoTableCursor->GetMark()->GetNode().FindTableBoxStartNode();
2450 pStartBox = pTable->GetTableBox( pStartNd->GetIndex() );
2451 const OUString aStartBox( pStartBox->GetName() );
2452
2453 SwRangeDescriptor aDesc;
2454 // note that cell range here takes the newly added rows/cols already into account
2455 OUString sDescrip = aStartBox + ":" + aEndBox;
2456 FillRangeDescriptor( aDesc, sDescrip );
2457
2458 bool bChanged = false;
2459 OUString aNewStartCell;
2460 OUString aNewEndCell;
2461 if (bExtendCol && aDesc.nBottom + 1 == nFirstNew)
2462 {
2463 // new column cells adjacent to the bottom of the
2464 // current data-sequence to be added...
2465 OSL_ENSURE( aDesc.nLeft == aDesc.nRight, "data-sequence is not a column" );
2466 aNewStartCell = sw_GetCellName(aDesc.nLeft, aDesc.nTop);
2467 aNewEndCell = sw_GetCellName(aDesc.nRight, aDesc.nBottom + nCount);
2468 bChanged = true;
2469 }
2470 else if (bExtendCol && aDesc.nTop - nCount == nFirstNew)
2471 {
2472 // new column cells adjacent to the top of the
2473 // current data-sequence to be added...
2474 OSL_ENSURE( aDesc.nLeft == aDesc.nRight, "data-sequence is not a column" );
2475 aNewStartCell = sw_GetCellName(aDesc.nLeft, aDesc.nTop - nCount);
2476 aNewEndCell = sw_GetCellName(aDesc.nRight, aDesc.nBottom);
2477 bChanged = true;
2478 }
2479 else if (!bExtendCol && aDesc.nRight + 1 == nFirstNew)
2480 {
2481 // new row cells adjacent to the right of the
2482 // current data-sequence to be added...
2483 OSL_ENSURE( aDesc.nTop == aDesc.nBottom, "data-sequence is not a row" );
2484 aNewStartCell = sw_GetCellName(aDesc.nLeft, aDesc.nTop);
2485 aNewEndCell = sw_GetCellName(aDesc.nRight + nCount, aDesc.nBottom);
2486 bChanged = true;
2487 }
2488 else if (!bExtendCol && aDesc.nLeft - nCount == nFirstNew)
2489 {
2490 // new row cells adjacent to the left of the
2491 // current data-sequence to be added...
2492 OSL_ENSURE( aDesc.nTop == aDesc.nBottom, "data-sequence is not a row" );
2493 aNewStartCell = sw_GetCellName(aDesc.nLeft - nCount, aDesc.nTop);
2494 aNewEndCell = sw_GetCellName(aDesc.nRight, aDesc.nBottom);
2495 bChanged = true;
2496 }
2497
2498 if (bChanged)
2499 {
2500 // move table cursor to new start and end of data-sequence
2501 const SwTableBox *pNewStartBox = pTable->GetTableBox( aNewStartCell );
2502 const SwTableBox *pNewEndBox = pTable->GetTableBox( aNewEndCell );
2503 pUnoTableCursor->SetMark();
2504 pUnoTableCursor->GetPoint()->Assign( *pNewEndBox->GetSttNd() );
2505 pUnoTableCursor->GetMark()->Assign( *pNewStartBox->GetSttNd() );
2506 pUnoTableCursor->Move( fnMoveForward, GoInNode );
2507 pUnoTableCursor->MakeBoxSels();
2508 }
2509}
2510
2512{
2513 m_bDisposed = false;
2514}
2515
2517{
2518}
2519
2520uno::Reference< chart2::data::XDataSequence > SAL_CALL SwChartLabeledDataSequence::getValues( )
2521{
2522 SolarMutexGuard aGuard;
2523 if (m_bDisposed)
2524 throw lang::DisposedException();
2525 return m_xData;
2526}
2527
2529 uno::Reference< chart2::data::XDataSequence >& rxDest,
2530 const uno::Reference< chart2::data::XDataSequence >& rxSource)
2531{
2532 uno::Reference< util::XModifyListener > xML(this);
2533 uno::Reference< lang::XEventListener > xEL(this);
2534
2535 // stop listening to old data-sequence
2536 uno::Reference< util::XModifyBroadcaster > xMB( rxDest, uno::UNO_QUERY );
2537 if (xMB.is())
2538 xMB->removeModifyListener( xML );
2539 uno::Reference< lang::XComponent > xC( rxDest, uno::UNO_QUERY );
2540 if (xC.is())
2541 xC->removeEventListener( xEL );
2542
2543 rxDest = rxSource;
2544
2545 // start listening to new data-sequence
2546 xC.set( rxDest, uno::UNO_QUERY );
2547 if (xC.is())
2548 xC->addEventListener( xEL );
2549 xMB.set( rxDest, uno::UNO_QUERY );
2550 if (xMB.is())
2551 xMB->addModifyListener( xML );
2552}
2553
2555 const uno::Reference< chart2::data::XDataSequence >& rxSequence )
2556{
2557 SolarMutexGuard aGuard;
2558 if (m_bDisposed)
2559 throw lang::DisposedException();
2560
2561 if (m_xData != rxSequence)
2562 {
2563 SetDataSequence( m_xData, rxSequence );
2564 // inform listeners of changes
2565 LaunchModifiedEvent( m_aModifyListeners, static_cast< XModifyBroadcaster * >(this) );
2566 }
2567}
2568
2569uno::Reference< chart2::data::XDataSequence > SAL_CALL SwChartLabeledDataSequence::getLabel( )
2570{
2571 SolarMutexGuard aGuard;
2572 if (m_bDisposed)
2573 throw lang::DisposedException();
2574 return m_xLabels;
2575}
2576
2578 const uno::Reference< chart2::data::XDataSequence >& rxSequence )
2579{
2580 SolarMutexGuard aGuard;
2581 if (m_bDisposed)
2582 throw lang::DisposedException();
2583
2584 if (m_xLabels != rxSequence)
2585 {
2586 SetDataSequence( m_xLabels, rxSequence );
2587 // inform listeners of changes
2588 LaunchModifiedEvent( m_aModifyListeners, static_cast< XModifyBroadcaster * >(this) );
2589 }
2590}
2591
2592uno::Reference< util::XCloneable > SAL_CALL SwChartLabeledDataSequence::createClone( )
2593{
2594 SolarMutexGuard aGuard;
2595 if (m_bDisposed)
2596 throw lang::DisposedException();
2597
2598 uno::Reference< util::XCloneable > xDataCloneable( m_xData, uno::UNO_QUERY );
2599 uno::Reference< util::XCloneable > xLabelsCloneable( m_xLabels, uno::UNO_QUERY );
2601 if (xDataCloneable.is())
2602 {
2603 uno::Reference< chart2::data::XDataSequence > xDataClone( xDataCloneable->createClone(), uno::UNO_QUERY );
2604 pRes->setValues( xDataClone );
2605 }
2606
2607 if (xLabelsCloneable.is())
2608 {
2609 uno::Reference< chart2::data::XDataSequence > xLabelsClone( xLabelsCloneable->createClone(), uno::UNO_QUERY );
2610 pRes->setLabel( xLabelsClone );
2611 }
2612 return pRes;
2613}
2614
2616{
2617 return "SwChartLabeledDataSequence";
2618}
2619
2621 const OUString& rServiceName )
2622{
2623 return cppu::supportsService(this, rServiceName);
2624}
2625
2626uno::Sequence< OUString > SAL_CALL SwChartLabeledDataSequence::getSupportedServiceNames( )
2627{
2628 return { "com.sun.star.chart2.data.LabeledDataSequence" };
2629}
2630
2632 const lang::EventObject& rSource )
2633{
2634 std::unique_lock aGuard( GetChartMutex() );
2635 uno::Reference< uno::XInterface > xRef( rSource.Source );
2636 if (xRef == m_xData)
2637 m_xData.clear();
2638 if (xRef == m_xLabels)
2639 m_xLabels.clear();
2640 if (!m_xData.is() && !m_xLabels.is())
2641 {
2642 aGuard.unlock();
2643 dispose();
2644 }
2645}
2646
2648 const lang::EventObject& rEvent )
2649{
2650 if (rEvent.Source == m_xData || rEvent.Source == m_xLabels)
2651 {
2652 LaunchModifiedEvent( m_aModifyListeners, static_cast< XModifyBroadcaster * >(this) );
2653 }
2654}
2655
2657 const uno::Reference< util::XModifyListener >& rxListener )
2658{
2659 std::unique_lock aGuard( GetChartMutex() );
2660 if (!m_bDisposed && rxListener.is())
2661 m_aModifyListeners.addInterface( aGuard, rxListener );
2662}
2663
2665 const uno::Reference< util::XModifyListener >& rxListener )
2666{
2667 std::unique_lock aGuard( GetChartMutex() );
2668 if (!m_bDisposed && rxListener.is())
2669 m_aModifyListeners.removeInterface( aGuard, rxListener );
2670}
2671
2673{
2674 bool bMustDispose( false );
2675 {
2676 std::unique_lock aGuard( GetChartMutex() );
2677 bMustDispose = !m_bDisposed;
2678 if (!m_bDisposed)
2679 m_bDisposed = true;
2680 }
2681 if (bMustDispose)
2682 {
2683 m_bDisposed = true;
2684
2685 // require listeners to release references to this object
2686 lang::EventObject aEvtObj( static_cast< chart2::data::XLabeledDataSequence * >(this) );
2687 std::unique_lock aGuard( GetChartMutex() );
2688 m_aModifyListeners.disposeAndClear( aGuard, aEvtObj );
2689 m_aEventListeners.disposeAndClear( aGuard, aEvtObj );
2690 }
2691}
2692
2694 const uno::Reference< lang::XEventListener >& rxListener )
2695{
2696 std::unique_lock aGuard( GetChartMutex() );
2697 if (!m_bDisposed && rxListener.is())
2698 m_aEventListeners.addInterface( aGuard, rxListener );
2699}
2700
2702 const uno::Reference< lang::XEventListener >& rxListener )
2703{
2704 std::unique_lock aGuard( GetChartMutex() );
2705 if (!m_bDisposed && rxListener.is())
2706 m_aEventListeners.removeInterface( aGuard, rxListener );
2707}
2708
2709/* 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:129
::comphelper::OInterfaceContainerHelper4< css::lang::XEventListener > m_aEventListeners
Definition: unochart.hxx:128
void InvalidateTable(const SwTable *pTable, bool bImmediate=false)
Definition: unochart.cxx:1425
SwChartDataProvider(const SwChartDataProvider &)=delete
virtual sal_Bool SAL_CALL createDataSourcePossible(const css::uno::Sequence< css::beans::PropertyValue > &aArguments) override
Definition: unochart.cxx:896
virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL createDataSequenceByValueArray(const OUString &aRole, const OUString &aRangeRepresentation, const OUString &aRoleQualifier) override
Definition: unochart.cxx:1351
css::uno::Reference< css::chart2::data::XDataSource > Impl_createDataSource(const css::uno::Sequence< css::beans::PropertyValue > &aArguments, bool bTestOnly=false)
Definition: unochart.cxx:513
std::set< css::uno::WeakReference< css::chart2::data::XDataSequence >, lt_DataSequenceRef > Set_DataSequenceRef_t
Definition: unochart.hxx:117
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
Definition: unochart.cxx:1384
virtual void SAL_CALL dispose() override
Definition: unochart.cxx:1358
virtual OUString SAL_CALL convertRangeToXML(const OUString &aRangeRepresentation) override
Definition: unochart.cxx:1628
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &aListener) override
Definition: unochart.cxx:1392
css::uno::Reference< css::chart2::data::XDataSequence > Impl_createDataSequenceByRangeRepresentation(std::u16string_view aRangeRepresentation, bool bTestOnly=false)
Definition: unochart.cxx:1291
void AddDataSequence(const SwTable &rTable, css::uno::Reference< css::chart2::data::XDataSequence > const &rxDataSequence)
Definition: unochart.cxx:1415
virtual sal_Bool SAL_CALL createDataSequenceByRangeRepresentationPossible(const OUString &aRangeRepresentation) override
Definition: unochart.cxx:1319
virtual css::uno::Reference< css::chart2::data::XDataSource > SAL_CALL createDataSource(const css::uno::Sequence< css::beans::PropertyValue > &aArguments) override
Definition: unochart.cxx:914
virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL detectArguments(const css::uno::Reference< css::chart2::data::XDataSource > &xDataSource) override
Definition: unochart.cxx:957
virtual css::uno::Reference< css::sheet::XRangeSelection > SAL_CALL getRangeSelection() override
Definition: unochart.cxx:1344
virtual OUString SAL_CALL convertRangeFromXML(const OUString &aXMLRange) override
Definition: unochart.cxx:1698
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:1552
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: unochart.cxx:1405
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:930
virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL createDataSequenceByRangeRepresentation(const OUString &aRangeRepresentation) override
Definition: unochart.cxx:1337
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: unochart.cxx:1410
virtual ~SwChartDataProvider() override
Definition: unochart.cxx:509
virtual OUString SAL_CALL getImplementationName() override
Definition: unochart.cxx:1400
Map_Set_DataSequenceRef_t m_aDataSequences
Definition: unochart.hxx:126
void DisposeAllDataSequences(const SwTable *pTable)
Definition: unochart.cxx:1505
void RemoveDataSequence(const SwTable &rTable, css::uno::Reference< css::chart2::data::XDataSequence > const &rxDataSequence)
Definition: unochart.cxx:1420
void DeleteBox(const SwTable *pTable, const SwTableBox &rBox)
Definition: unochart.cxx:1451
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:2427
::comphelper::OInterfaceContainerHelper4< css::lang::XEventListener > m_aEvtListeners
Definition: unochart.hxx:236
virtual css::uno::Sequence< OUString > SAL_CALL getTextualData() override
Definition: unochart.cxx:2032
virtual void Notify(const SfxHint &rHint) override
Definition: unochart.cxx:2160
std::vector< css::uno::Reference< css::table::XCell > > GetCells()
Definition: unochart.cxx:2016
virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override
Definition: unochart.cxx:2071
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: unochart.cxx:2155
virtual void SAL_CALL removeModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
Definition: unochart.cxx:2204
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: unochart.cxx:2212
virtual void SAL_CALL addPropertyChangeListener(const OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &xListener) override
Definition: unochart.cxx:2117
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: unochart.cxx:2150
const SfxItemPropertySet * m_pPropSet
Definition: unochart.hxx:247
virtual OUString SAL_CALL getImplementationName() override
Definition: unochart.cxx:2145
::comphelper::OInterfaceContainerHelper4< css::util::XModifyListener > m_aModifyListeners
Definition: unochart.hxx:237
virtual void SAL_CALL addModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
Definition: unochart.cxx:2196
SwFrameFormat * GetFrameFormat() const
Definition: unochart.hxx:310
SwFrameFormat * m_pFormat
Definition: unochart.hxx:235
virtual css::uno::Sequence< double > SAL_CALL getNumericalData() override
Definition: unochart.cxx:2058
virtual void SAL_CALL setModified(sal_Bool bModified) override
Definition: unochart.cxx:2185
virtual OUString SAL_CALL getSourceRangeRepresentation() override
Definition: unochart.cxx:1886
virtual void SAL_CALL removeVetoableChangeListener(const OUString &PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override
Definition: unochart.cxx:2138
virtual void SAL_CALL setPropertyValue(const OUString &aPropertyName, const css::uno::Any &aValue) override
Definition: unochart.cxx:2089
void FillRangeDesc(SwRangeDescriptor &rRangeDesc) const
Definition: unochart.cxx:2400
OUString m_aRowLabelText
Definition: unochart.hxx:240
virtual void SAL_CALL dispose() override
Definition: unochart.cxx:2222
virtual css::uno::Sequence< css::uno::Any > SAL_CALL getData() override
Definition: unochart.cxx:2045
bool DeleteBox(const SwTableBox &rBox)
Definition: unochart.cxx:2294
css::chart2::data::DataSequenceRole m_aRole
Definition: unochart.hxx:238
SwChartDataSequence(const SwChartDataSequence &rObj)
Definition: unochart.cxx:1823
virtual void SAL_CALL removePropertyChangeListener(const OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &aListener) override
Definition: unochart.cxx:2124
static const css::uno::Sequence< sal_Int8 > & getUnoTunnelId()
Definition: unochart.cxx:1874
sw::UnoCursorPointer m_pTableCursor
Definition: unochart.hxx:245
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
Definition: unochart.cxx:2278
rtl::Reference< SwChartDataProvider > m_xDataProvider
Definition: unochart.hxx:243
virtual ::sal_Int32 SAL_CALL getNumberFormatKeyByIndex(::sal_Int32 nIndex) override
Definition: unochart.cxx:2010
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &aListener) override
Definition: unochart.cxx:2286
virtual ~SwChartDataSequence() override
Definition: unochart.cxx:1870
virtual sal_Int64 SAL_CALL getSomething(const css::uno::Sequence< sal_Int8 > &aIdentifier) override
Definition: unochart.cxx:1880
virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override
Definition: unochart.cxx:2079
virtual void SAL_CALL addVetoableChangeListener(const OUString &PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override
Definition: unochart.cxx:2131
virtual sal_Bool SAL_CALL isModified() override
Definition: unochart.cxx:2176
virtual css::uno::Sequence< OUString > SAL_CALL generateLabel(css::chart2::data::LabelOrigin eLabelOrigin) override
Definition: unochart.cxx:1903
OUString m_aColLabelText
Definition: unochart.hxx:241
virtual css::uno::Any SAL_CALL getPropertyValue(const OUString &PropertyName) override
Definition: unochart.cxx:2104
SwChartDataSource(const SwChartDataSource &)=delete
virtual OUString SAL_CALL getImplementationName() override
Definition: unochart.cxx:1762
virtual ~SwChartDataSource() override
Definition: unochart.cxx:1752
css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > m_aLDS
Definition: unochart.hxx:198
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: unochart.cxx:1772
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: unochart.cxx:1767
virtual css::uno::Sequence< css::uno::Reference< css::chart2::data::XLabeledDataSequence > > SAL_CALL getDataSequences() override
Definition: unochart.cxx:1756
static void DoUpdateAllCharts(SwDoc *pDoc)
Definition: unochart.cxx:52
virtual OUString SAL_CALL getImplementationName() override
Definition: unochart.cxx:2615
virtual void SAL_CALL dispose() override
Definition: unochart.cxx:2672
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
Definition: unochart.cxx:2631
virtual void SAL_CALL modified(const css::lang::EventObject &aEvent) override
Definition: unochart.cxx:2647
css::uno::Reference< css::chart2::data::XDataSequence > m_xData
Definition: unochart.hxx:335
virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone() override
Definition: unochart.cxx:2592
virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL getLabel() override
Definition: unochart.cxx:2569
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
Definition: unochart.cxx:2693
::comphelper::OInterfaceContainerHelper4< css::util::XModifyListener > m_aModifyListeners
Definition: unochart.hxx:333
virtual void SAL_CALL setValues(const css::uno::Reference< css::chart2::data::XDataSequence > &xSequence) override
Definition: unochart.cxx:2554
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: unochart.cxx:2626
::comphelper::OInterfaceContainerHelper4< css::lang::XEventListener > m_aEventListeners
Definition: unochart.hxx:332
virtual void SAL_CALL addModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
Definition: unochart.cxx:2656
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: unochart.cxx:2620
virtual void SAL_CALL setLabel(const css::uno::Reference< css::chart2::data::XDataSequence > &xSequence) override
Definition: unochart.cxx:2577
virtual ~SwChartLabeledDataSequence() override
Definition: unochart.cxx:2516
css::uno::Reference< css::chart2::data::XDataSequence > m_xLabels
Definition: unochart.hxx:336
virtual void SAL_CALL removeModifyListener(const css::uno::Reference< css::util::XModifyListener > &aListener) override
Definition: unochart.cxx:2664
void SetDataSequence(css::uno::Reference< css::chart2::data::XDataSequence > &rxDest, const css::uno::Reference< css::chart2::data::XDataSequence > &rxSource)
Definition: unochart.cxx:2528
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &aListener) override
Definition: unochart.cxx:2701
virtual css::uno::Reference< css::chart2::data::XDataSequence > SAL_CALL getValues() override
Definition: unochart.cxx:2520
SwChartLockController_Helper(const SwChartLockController_Helper &)=delete
void LockUnlockAllCharts(bool bLock)
Definition: unochart.cxx:115
Definition: doc.hxx:192
size_t GetTableFrameFormatCount(bool bUsed) const
Definition: docfmt.cxx:768
IDocumentChartDataProviderAccess const & getIDocumentChartDataProviderAccess() const
Definition: doc.cxx:228
SwNodes & GetNodes()
Definition: doc.hxx:413
std::shared_ptr< SwUnoCursor > CreateUnoCursor(const SwPosition &rPos, bool bTableCursor=false)
Definition: doc.cxx:1774
SwFrameFormat & GetTableFrameFormat(size_t nFormat, bool bUsed) const
Definition: docfmt.cxx:785
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
bool HasWriterListeners() const
Definition: calbck.hxx:202
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:84
SwStartNode * GetStartNode()
Definition: node.hxx:619
SwNodeOffset GetIndex() const
Definition: node.hxx:296
const SwStartNode * FindTableBoxStartNode() const
Definition: node.hxx:202
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:137
SwOLENode * GetOLENode()
Inline methods from Node.hxx.
Definition: ndole.hxx:164
SwContentNode * GetContentNode()
Definition: node.hxx:643
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:710
SwNode & GetEndOfAutotext() const
Section for all Flys/Header/Footers.
Definition: ndarr.hxx:158
SwContentNode * GoNext(SwNodeIndex *) const
Definition: nodes.cxx:1300
SwNodeOffset Count() const
Definition: ndarr.hxx:142
const SwOLEObj & GetOLEObj() const
Definition: ndole.hxx:115
const OUString & GetChartTableName() const
Definition: ndole.hxx:155
svt::EmbeddedObjectRef & GetObject()
Definition: ndole.cxx:991
css::uno::Reference< css::embed::XEmbeddedObject > const & GetOleRef()
Definition: ndole.cxx:940
const OUString & GetCurrentPersistName() const
Definition: ndole.hxx:71
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:612
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:638
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:325
SwTableBox is one table cell in the document model.
Definition: swtable.hxx:419
OUString GetName() const
Definition: swtable.cxx:1996
const SwStartNode * GetSttNd() const
Definition: swtable.hxx:471
SwTableBoxes & GetTabBoxes()
Definition: swtable.hxx:368
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:201
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:204
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:2104
void MakeBoxSels()
Definition: unocrsr.cxx:184
static ::rtl::Reference< SwXCellRange > CreateXCellRange(const sw::UnoCursorPointer &pCursor, SwFrameFormat &rFrameFormat, SwRangeDescriptor const &rDesc)
Definition: unotbl.cxx:3215
static SW_DLLPUBLIC void GetCellPosition(const OUString &rCellName, 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 css::uno::Sequence< sal_Int8 > & getSeq() const
const Value & back() const
size_type size() const
static bool TryRunningState(const css::uno::Reference< css::embed::XEmbeddedObject > &)
SvtBroadcaster & GetNotifier()
Definition: calbck.hxx:101
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)
sal_Int64 getSomethingImpl(const css::uno::Sequence< sal_Int8 > &rId, T *pThis, FallbackToGetSomethingOf< Base >={})
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:1133
SwMoveFnCollection const & fnMoveForward
SwPam::Move()/Find() default argument.
Definition: paminit.cxx:59
std::unique_ptr< uint8_t[]> pLabels
DefTokenId nToken
static SfxItemSet & rSet
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:247
sal_Int32 nBottom
Definition: unotbl.hxx:248
void Normalize()
Definition: unotbl.cxx:537
sal_Int32 nTop
Definition: unotbl.hxx:246
sal_Int32 nRight
Definition: unotbl.hxx:249
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:164
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::lang::XUnoTunnel, css::util::XModifiable, css::lang::XEventListener, css::lang::XComponent > SwChartDataSequenceBaseClass
Definition: unochart.hxx:229
SwUnoPropertyMapProvider aSwMapProvider
Definition: unomap1.cxx:87
#define PROPERTY_MAP_CHART2_DATA_SEQUENCE
Definition: unomap.hxx:117
#define UNO_NAME_ROLE
Definition: unoprnms.hxx:784
int sw_CompareCellRanges(const OUString &rRange1StartCell, const OUString &rRange1EndCell, const OUString &rRange2StartCell, const OUString &rRange2EndCell, bool bCmpColsFirst)
compare position of two cell ranges
Definition: unotbl.cxx:454
int sw_CompareCellsByColFirst(const OUString &rCellName1, const OUString &rCellName2)
compare position of two cells (check columns first)
Definition: unotbl.cxx:427
void sw_NormalizeRange(OUString &rCell1, OUString &rCell2)
cleanup order in a range
Definition: unotbl.cxx:525
OUString sw_GetCellName(sal_Int32 nColumn, sal_Int32 nRow)
get cell name at a specified coordinate
Definition: unotbl.cxx:480