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