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