LibreOffice Module sc (master)  1
detfunc.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 <scitems.hxx>
21 #include <svtools/colorcfg.hxx>
22 #include <editeng/eeitem.hxx>
23 #include <editeng/outlobj.hxx>
24 #include <formula/errorcodes.hxx>
25 #include <svx/sdshitm.hxx>
26 #include <svx/sdsxyitm.hxx>
27 #include <svx/sdtditm.hxx>
28 #include <svx/svditer.hxx>
29 #include <svx/svdocapt.hxx>
30 #include <svx/svdocirc.hxx>
31 #include <svx/svdopath.hxx>
32 #include <svx/svdorect.hxx>
33 #include <svx/svdpage.hxx>
34 #include <svx/svdundo.hxx>
35 #include <svx/xfillit0.hxx>
36 #include <svx/xflclit.hxx>
37 #include <svx/xlnclit.hxx>
38 #include <svx/xlnedcit.hxx>
39 #include <svx/xlnedit.hxx>
40 #include <svx/xlnedwit.hxx>
41 #include <svx/xlnstcit.hxx>
42 #include <svx/xlnstit.hxx>
43 #include <svx/xlnstwit.hxx>
44 #include <svx/xlnwtit.hxx>
45 #include <svx/xtable.hxx>
46 #include <svx/sdtagitm.hxx>
47 #include <editeng/outliner.hxx>
48 #include <editeng/editobj.hxx>
49 #include <svx/sxcecitm.hxx>
50 #include <svl/whiter.hxx>
52 
56 
57 #include <detfunc.hxx>
58 #include <document.hxx>
59 #include <dociter.hxx>
60 #include <drwlayer.hxx>
61 #include <userdat.hxx>
62 #include <validat.hxx>
63 #include <formulacell.hxx>
64 #include <docpool.hxx>
65 #include <patattr.hxx>
66 #include <attrib.hxx>
67 #include <scmod.hxx>
68 #include <postit.hxx>
69 #include <rangelst.hxx>
70 #include <reftokenhelper.hxx>
71 #include <formulaiter.hxx>
72 #include <cellvalue.hxx>
73 
74 #include <vector>
75 #include <memory>
76 
77 using ::std::vector;
78 using namespace com::sun::star;
79 
80 // line ends are now created with an empty name.
81 // The checkForUniqueItem method then finds a unique name for the item's value.
82 #define SC_LINEEND_NAME EMPTY_OUSTRING
83 
84 namespace {
85 
86 enum DetInsertResult { // return-values for inserting in one level
87  DET_INS_CONTINUE,
88  DET_INS_INSERTED,
89  DET_INS_EMPTY,
90  DET_INS_CIRCULAR };
91 
92 }
93 
95 {
96 private:
101  SfxItemSet aCircleSet; //TODO: individually ?
102  sal_uInt16 nMaxLevel;
103 
104 public:
105  explicit ScDetectiveData( SdrModel* pModel );
106 
107  SfxItemSet& GetBoxSet() { return aBoxSet; }
108  SfxItemSet& GetArrowSet() { return aArrowSet; }
109  SfxItemSet& GetToTabSet() { return aToTabSet; }
110  SfxItemSet& GetFromTabSet() { return aFromTabSet; }
111  SfxItemSet& GetCircleSet() { return aCircleSet; }
112 
113  void SetMaxLevel( sal_uInt16 nVal ) { nMaxLevel = nVal; }
114  sal_uInt16 GetMaxLevel() const { return nMaxLevel; }
115 };
116 
117 namespace {
118 
119 class ScCommentData
120 {
121 public:
122  ScCommentData( ScDocument& rDoc, SdrModel* pModel );
123 
124  SfxItemSet& GetCaptionSet() { return aCaptionSet; }
125  void UpdateCaptionSet( const SfxItemSet& rItemSet );
126 
127 private:
128  SfxItemSet aCaptionSet;
129 };
130 
131 }
132 
137 
138 static bool lcl_HasThickLine( const SdrObject& rObj )
139 {
140  // thin lines get width 0 -> everything greater 0 is a thick line
141 
142  return rObj.GetMergedItem(XATTR_LINEWIDTH).GetValue() > 0;
143 }
144 
146  aBoxSet( pModel->GetItemPool(), svl::Items<SDRATTR_START, SDRATTR_END>{} ),
147  aArrowSet( pModel->GetItemPool(), svl::Items<SDRATTR_START, SDRATTR_END>{} ),
148  aToTabSet( pModel->GetItemPool(), svl::Items<SDRATTR_START, SDRATTR_END>{} ),
149  aFromTabSet( pModel->GetItemPool(), svl::Items<SDRATTR_START, SDRATTR_END>{} ),
150  aCircleSet( pModel->GetItemPool(), svl::Items<SDRATTR_START, SDRATTR_END>{} ),
151  nMaxLevel(0)
152 {
153 
155  aBoxSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
156 
157  // create default line endings (like XLineEndList::Create)
158  // to be independent from the configured line endings
159 
160  basegfx::B2DPolygon aTriangle;
161  aTriangle.append(basegfx::B2DPoint(10.0, 0.0));
162  aTriangle.append(basegfx::B2DPoint(0.0, 30.0));
163  aTriangle.append(basegfx::B2DPoint(20.0, 30.0));
164  aTriangle.setClosed(true);
165 
166  basegfx::B2DPolygon aSquare;
167  aSquare.append(basegfx::B2DPoint(0.0, 0.0));
168  aSquare.append(basegfx::B2DPoint(10.0, 0.0));
169  aSquare.append(basegfx::B2DPoint(10.0, 10.0));
170  aSquare.append(basegfx::B2DPoint(0.0, 10.0));
171  aSquare.setClosed(true);
172 
174  aCircle.setClosed(true);
175 
176  OUString aName = SC_LINEEND_NAME;
177 
178  aArrowSet.Put( XLineStartItem( aName, basegfx::B2DPolyPolygon(aCircle) ) );
181  aArrowSet.Put( XLineEndItem( aName, basegfx::B2DPolyPolygon(aTriangle) ) );
182  aArrowSet.Put( XLineEndWidthItem( 200 ) );
183  aArrowSet.Put( XLineEndCenterItem( false ) );
184 
185  aToTabSet.Put( XLineStartItem( aName, basegfx::B2DPolyPolygon(aCircle) ) );
188  aToTabSet.Put( XLineEndItem( aName, basegfx::B2DPolyPolygon(aSquare) ) );
189  aToTabSet.Put( XLineEndWidthItem( 300 ) );
190  aToTabSet.Put( XLineEndCenterItem( false ) );
191 
195  aFromTabSet.Put( XLineEndItem( aName, basegfx::B2DPolyPolygon(aTriangle) ) );
197  aFromTabSet.Put( XLineEndCenterItem( false ) );
198 
200  aCircleSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
201  aCircleSet.Put( XLineWidthItem( 55 ) ); // 54 = 1 Pixel
202 }
203 
204 ScCommentData::ScCommentData( ScDocument& rDoc, SdrModel* pModel ) :
205  aCaptionSet( pModel->GetItemPool(), svl::Items<SDRATTR_START, SDRATTR_END, EE_ITEMS_START, EE_ITEMS_END>{} )
206 {
207  basegfx::B2DPolygon aTriangle;
208  aTriangle.append(basegfx::B2DPoint(10.0, 0.0));
209  aTriangle.append(basegfx::B2DPoint(0.0, 30.0));
210  aTriangle.append(basegfx::B2DPoint(20.0, 30.0));
211  aTriangle.setClosed(true);
212 
213  OUString aName = SC_LINEEND_NAME;
214 
215  aCaptionSet.Put( XLineStartItem( aName, basegfx::B2DPolyPolygon(aTriangle) ) );
216  aCaptionSet.Put( XLineStartWidthItem( 200 ) );
217  aCaptionSet.Put( XLineStartCenterItem( false ) );
218  aCaptionSet.Put( XFillStyleItem( drawing::FillStyle_SOLID ) );
220  aCaptionSet.Put( XFillColorItem( OUString(), aYellow ) );
221 
222  // shadow
223  // SdrShadowItem has sal_False, instead the shadow is set for the rectangle
224  // only with SetSpecialTextBoxShadow when the object is created
225  // (item must be set to adjust objects from older files)
226  aCaptionSet.Put( makeSdrShadowItem( false ) );
227  aCaptionSet.Put( makeSdrShadowXDistItem( 100 ) );
228  aCaptionSet.Put( makeSdrShadowYDistItem( 100 ) );
229 
230  // text attributes
231  aCaptionSet.Put( makeSdrTextLeftDistItem( 100 ) );
232  aCaptionSet.Put( makeSdrTextRightDistItem( 100 ) );
233  aCaptionSet.Put( makeSdrTextUpperDistItem( 100 ) );
234  aCaptionSet.Put( makeSdrTextLowerDistItem( 100 ) );
235 
236  aCaptionSet.Put( makeSdrTextAutoGrowWidthItem( false ) );
237  aCaptionSet.Put( makeSdrTextAutoGrowHeightItem( true ) );
238 
239  // do use the default cell style, so the user has a chance to
240  // modify the font for the annotations
241  rDoc.GetPool()->GetDefaultItem(ATTR_PATTERN).FillEditItemSet( &aCaptionSet );
242 
243  // support the best position for the tail connector now that
244  // that notes can be resized and repositioned.
245  aCaptionSet.Put( SdrCaptionEscDirItem( SdrCaptionEscDir::BestFit) );
246 }
247 
248 void ScCommentData::UpdateCaptionSet( const SfxItemSet& rItemSet )
249 {
250  SfxWhichIter aWhichIter( rItemSet );
251  const SfxPoolItem* pPoolItem = nullptr;
252 
253  for( sal_uInt16 nWhich = aWhichIter.FirstWhich(); nWhich > 0; nWhich = aWhichIter.NextWhich() )
254  {
255  if(rItemSet.GetItemState(nWhich, false, &pPoolItem) == SfxItemState::SET)
256  {
257  switch(nWhich)
258  {
259  case SDRATTR_SHADOW:
260  // use existing Caption default - appears that setting this
261  // to true screws up the tail appearance. See also comment
262  // for default setting above.
263  break;
264  case SDRATTR_SHADOWXDIST:
265  // use existing Caption default - svx sets a value of 35
266  // but default 100 gives a better appearance.
267  break;
268  case SDRATTR_SHADOWYDIST:
269  // use existing Caption default - svx sets a value of 35
270  // but default 100 gives a better appearance.
271  break;
272 
273  default:
274  aCaptionSet.Put(*pPoolItem);
275  }
276  }
277  }
278 }
279 
281 {
282  rDoc.SetStreamValid(nTab, false);
283 }
284 
285 static bool Intersect( SCCOL nStartCol1, SCROW nStartRow1, SCCOL nEndCol1, SCROW nEndRow1,
286  SCCOL nStartCol2, SCROW nStartRow2, SCCOL nEndCol2, SCROW nEndRow2 )
287 {
288  return nEndCol1 >= nStartCol2 && nEndCol2 >= nStartCol1 &&
289  nEndRow1 >= nStartRow2 && nEndRow2 >= nStartRow1;
290 }
291 
292 bool ScDetectiveFunc::HasError( const ScRange& rRange, ScAddress& rErrPos )
293 {
294  rErrPos = rRange.aStart;
295  FormulaError nError = FormulaError::NONE;
296 
297  ScCellIterator aIter( rDoc, rRange);
298  for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
299  {
300  if (aIter.getType() != CELLTYPE_FORMULA)
301  continue;
302 
303  nError = aIter.getFormulaCell()->GetErrCode();
304  if (nError != FormulaError::NONE)
305  rErrPos = aIter.GetPos();
306  }
307 
308  return (nError != FormulaError::NONE);
309 }
310 
312 {
313  OSL_ENSURE( rDoc.ValidColRow( nCol, nRow ), "ScDetectiveFunc::GetDrawPos - invalid cell address" );
314  nCol = rDoc.SanitizeCol( nCol );
315  nRow = rDoc.SanitizeRow( nRow );
316 
317  Point aPos;
318 
319  switch( eMode )
320  {
322  break;
324  ++nCol;
325  ++nRow;
326  break;
328  aPos.AdjustX(rDoc.GetColWidth( nCol, nTab ) / 4 );
329  aPos.AdjustY(rDoc.GetRowHeight( nRow, nTab ) / 2 );
330  break;
331  }
332 
333  for ( SCCOL i = 0; i < nCol; ++i )
334  aPos.AdjustX(rDoc.GetColWidth( i, nTab ) );
335  aPos.AdjustY(rDoc.GetRowHeight( 0, nRow - 1, nTab ) );
336 
337  aPos.setX( static_cast< tools::Long >( aPos.X() * HMM_PER_TWIPS ) );
338  aPos.setY( static_cast< tools::Long >( aPos.Y() * HMM_PER_TWIPS ) );
339 
340  if ( rDoc.IsNegativePage( nTab ) )
341  aPos.setX( aPos.X() * -1 );
342 
343  return aPos;
344 }
345 
347 {
348  tools::Rectangle aRect(
349  GetDrawPos( ::std::min( nCol1, nCol2 ), ::std::min( nRow1, nRow2 ), DrawPosMode::TopLeft ),
350  GetDrawPos( ::std::max( nCol1, nCol2 ), ::std::max( nRow1, nRow2 ), DrawPosMode::BottomRight ) );
351  aRect.Justify(); // reorder left/right in RTL sheets
352  return aRect;
353 }
354 
356 {
357  return GetDrawRect( nCol, nRow, nCol, nRow );
358 }
359 
360 static bool lcl_IsOtherTab( const basegfx::B2DPolyPolygon& rPolyPolygon )
361 {
362  // test if rPolygon is the line end for "other table" (rectangle)
363  if(1 == rPolyPolygon.count())
364  {
365  const basegfx::B2DPolygon& aSubPoly(rPolyPolygon.getB2DPolygon(0));
366 
367  // #i73305# circle consists of 4 segments, too, distinguishable from square by
368  // the use of control points
369  if(4 == aSubPoly.count() && aSubPoly.isClosed() && !aSubPoly.areControlPointsUsed())
370  {
371  return true;
372  }
373  }
374 
375  return false;
376 }
377 
379  SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab )
380 {
381  bool bStartAlien = ( rStart.Tab() != nTab );
382  bool bEndAlien = ( nEndTab != nTab );
383 
384  if (bStartAlien && bEndAlien)
385  {
386  OSL_FAIL("bStartAlien && bEndAlien");
387  return true;
388  }
389 
390  tools::Rectangle aStartRect;
391  tools::Rectangle aEndRect;
392  if (!bStartAlien)
393  aStartRect = GetDrawRect( rStart.Col(), rStart.Row() );
394  if (!bEndAlien)
395  aEndRect = GetDrawRect( nEndCol, nEndRow );
396 
397  ScDrawLayer* pModel = rDoc.GetDrawLayer();
398  SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
399  OSL_ENSURE(pPage,"Page ?");
400 
401  bool bFound = false;
402  SdrObjListIter aIter( pPage, SdrIterMode::Flat );
403  SdrObject* pObject = aIter.Next();
404  while (pObject && !bFound)
405  {
406  if ( pObject->GetLayer()==SC_LAYER_INTERN &&
407  pObject->IsPolyObj() && pObject->GetPointCount()==2 )
408  {
409  const SfxItemSet& rSet = pObject->GetMergedItemSet();
410 
411  bool bObjStartAlien =
412  lcl_IsOtherTab( rSet.Get(XATTR_LINESTART).GetLineStartValue() );
413  bool bObjEndAlien =
414  lcl_IsOtherTab( rSet.Get(XATTR_LINEEND).GetLineEndValue() );
415 
416  bool bStartHit = bStartAlien ? bObjStartAlien :
417  ( !bObjStartAlien && aStartRect.IsInside(pObject->GetPoint(0)) );
418  bool bEndHit = bEndAlien ? bObjEndAlien :
419  ( !bObjEndAlien && aEndRect.IsInside(pObject->GetPoint(1)) );
420 
421  if ( bStartHit && bEndHit )
422  bFound = true;
423  }
424  pObject = aIter.Next();
425  }
426 
427  return bFound;
428 }
429 
431 {
432  if ( pObject->GetLayer()==SC_LAYER_INTERN &&
433  pObject->IsPolyObj() && pObject->GetPointCount()==2 )
434  {
435  const SfxItemSet& rSet = pObject->GetMergedItemSet();
436 
437  bool bObjStartAlien =
438  lcl_IsOtherTab( rSet.Get(XATTR_LINESTART).GetLineStartValue() );
439  bool bObjEndAlien =
440  lcl_IsOtherTab( rSet.Get(XATTR_LINEEND).GetLineEndValue() );
441 
442  return !bObjStartAlien && !bObjEndAlien;
443  }
444 
445  return false;
446 }
447 
448 // InsertXXX: called from DrawEntry/DrawAlienEntry and InsertObject
449 
451  SCCOL nRefStartCol, SCROW nRefStartRow,
452  SCCOL nRefEndCol, SCROW nRefEndRow,
453  bool bFromOtherTab, bool bRed,
454  ScDetectiveData& rData )
455 {
456  ScDrawLayer* pModel = rDoc.GetDrawLayer();
457  SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
458 
459  bool bArea = ( nRefStartCol != nRefEndCol || nRefStartRow != nRefEndRow );
460  if (bArea && !bFromOtherTab)
461  {
462  // insert the rectangle before the arrow - this is relied on in FindFrameForObject
463 
464  tools::Rectangle aRect = GetDrawRect( nRefStartCol, nRefStartRow, nRefEndCol, nRefEndRow );
465  SdrRectObj* pBox = new SdrRectObj(
466  *pModel,
467  aRect);
468 
470 
471  pBox->SetLayer( SC_LAYER_INTERN );
472  pPage->InsertObject( pBox );
473  pModel->AddCalcUndo( std::make_unique<SdrUndoInsertObj>( *pBox ) );
474 
476  pData->maStart.Set( nRefStartCol, nRefStartRow, nTab);
477  pData->maEnd.Set( nRefEndCol, nRefEndRow, nTab);
478  }
479 
480  Point aStartPos = GetDrawPos( nRefStartCol, nRefStartRow, DrawPosMode::DetectiveArrow );
481  Point aEndPos = GetDrawPos( nCol, nRow, DrawPosMode::DetectiveArrow );
482 
483  if (bFromOtherTab)
484  {
485  bool bNegativePage = rDoc.IsNegativePage( nTab );
486  tools::Long nPageSign = bNegativePage ? -1 : 1;
487 
488  aStartPos = Point( aEndPos.X() - 1000 * nPageSign, aEndPos.Y() - 1000 );
489  if (aStartPos.X() * nPageSign < 0)
490  aStartPos.AdjustX(2000 * nPageSign );
491  if (aStartPos.Y() < 0)
492  aStartPos.AdjustY(2000 );
493  }
494 
495  SfxItemSet& rAttrSet = bFromOtherTab ? rData.GetFromTabSet() : rData.GetArrowSet();
496 
497  if (bArea && !bFromOtherTab)
498  rAttrSet.Put( XLineWidthItem( 50 ) ); // range
499  else
500  rAttrSet.Put( XLineWidthItem( 0 ) ); // single reference
501 
502  Color nColor = ( bRed ? GetErrorColor() : GetArrowColor() );
503  rAttrSet.Put( XLineColorItem( OUString(), nColor ) );
504 
505  basegfx::B2DPolygon aTempPoly;
506  aTempPoly.append(basegfx::B2DPoint(aStartPos.X(), aStartPos.Y()));
507  aTempPoly.append(basegfx::B2DPoint(aEndPos.X(), aEndPos.Y()));
508  SdrPathObj* pArrow = new SdrPathObj(
509  *pModel,
510  OBJ_LINE,
511  basegfx::B2DPolyPolygon(aTempPoly));
512  pArrow->NbcSetLogicRect(tools::Rectangle::Justify(aStartPos,aEndPos)); //TODO: needed ???
513  pArrow->SetMergedItemSetAndBroadcast(rAttrSet);
514 
515  pArrow->SetLayer( SC_LAYER_INTERN );
516  pPage->InsertObject( pArrow );
517  pModel->AddCalcUndo( std::make_unique<SdrUndoInsertObj>( *pArrow ) );
518 
520  if (bFromOtherTab)
521  pData->maStart.SetInvalid();
522  else
523  pData->maStart.Set( nRefStartCol, nRefStartRow, nTab);
524 
525  pData->maEnd.Set( nCol, nRow, nTab);
527 
528  Modified();
529 }
530 
531 void ScDetectiveFunc::InsertToOtherTab( SCCOL nStartCol, SCROW nStartRow,
532  SCCOL nEndCol, SCROW nEndRow, bool bRed,
533  ScDetectiveData& rData )
534 {
535  ScDrawLayer* pModel = rDoc.GetDrawLayer();
536  SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
537 
538  bool bArea = ( nStartCol != nEndCol || nStartRow != nEndRow );
539  if (bArea)
540  {
541  tools::Rectangle aRect = GetDrawRect( nStartCol, nStartRow, nEndCol, nEndRow );
542  SdrRectObj* pBox = new SdrRectObj(
543  *pModel,
544  aRect);
545 
547 
548  pBox->SetLayer( SC_LAYER_INTERN );
549  pPage->InsertObject( pBox );
550  pModel->AddCalcUndo( std::make_unique<SdrUndoInsertObj>( *pBox ) );
551 
553  pData->maStart.Set( nStartCol, nStartRow, nTab);
554  pData->maEnd.Set( nEndCol, nEndRow, nTab);
555  }
556 
557  bool bNegativePage = rDoc.IsNegativePage( nTab );
558  tools::Long nPageSign = bNegativePage ? -1 : 1;
559 
560  Point aStartPos = GetDrawPos( nStartCol, nStartRow, DrawPosMode::DetectiveArrow );
561  Point aEndPos( aStartPos.X() + 1000 * nPageSign, aStartPos.Y() - 1000 );
562  if (aEndPos.Y() < 0)
563  aEndPos.AdjustY(2000 );
564 
565  SfxItemSet& rAttrSet = rData.GetToTabSet();
566  if (bArea)
567  rAttrSet.Put( XLineWidthItem( 50 ) ); // range
568  else
569  rAttrSet.Put( XLineWidthItem( 0 ) ); // single reference
570 
571  Color nColor = ( bRed ? GetErrorColor() : GetArrowColor() );
572  rAttrSet.Put( XLineColorItem( OUString(), nColor ) );
573 
574  basegfx::B2DPolygon aTempPoly;
575  aTempPoly.append(basegfx::B2DPoint(aStartPos.X(), aStartPos.Y()));
576  aTempPoly.append(basegfx::B2DPoint(aEndPos.X(), aEndPos.Y()));
577  SdrPathObj* pArrow = new SdrPathObj(
578  *pModel,
579  OBJ_LINE,
580  basegfx::B2DPolyPolygon(aTempPoly));
581  pArrow->NbcSetLogicRect(tools::Rectangle::Justify(aStartPos,aEndPos)); //TODO: needed ???
582 
583  pArrow->SetMergedItemSetAndBroadcast(rAttrSet);
584 
585  pArrow->SetLayer( SC_LAYER_INTERN );
586  pPage->InsertObject( pArrow );
587  pModel->AddCalcUndo( std::make_unique<SdrUndoInsertObj>( *pArrow ) );
588 
589  ScDrawObjData* pData = ScDrawLayer::GetObjData( pArrow, true );
590  pData->maStart.Set( nStartCol, nStartRow, nTab);
591  pData->maEnd.SetInvalid();
592 
593  Modified();
594 }
595 
596 // DrawEntry: formula from this spreadsheet,
597 // reference on this or other
598 // DrawAlienEntry: formula from other spreadsheet,
599 // reference on this
600 
601 // return FALSE: there was already an arrow
602 
604  const ScRange& rRef,
605  ScDetectiveData& rData )
606 {
607  if ( HasArrow( rRef.aStart, nCol, nRow, nTab ) )
608  return false;
609 
610  ScAddress aErrorPos;
611  bool bError = HasError( rRef, aErrorPos );
612  bool bAlien = ( rRef.aEnd.Tab() < nTab || rRef.aStart.Tab() > nTab );
613 
614  InsertArrow( nCol, nRow,
615  rRef.aStart.Col(), rRef.aStart.Row(),
616  rRef.aEnd.Col(), rRef.aEnd.Row(),
617  bAlien, bError, rData );
618  return true;
619 }
620 
622  ScDetectiveData& rData )
623 {
624  if ( HasArrow( rRef.aStart, 0, 0, nTab+1 ) )
625  return false;
626 
627  ScAddress aErrorPos;
628  bool bError = HasError( rRef, aErrorPos );
629 
630  InsertToOtherTab( rRef.aStart.Col(), rRef.aStart.Row(),
631  rRef.aEnd.Col(), rRef.aEnd.Row(),
632  bError, rData );
633  return true;
634 }
635 
637 {
638  ScDrawLayer* pModel = rDoc.GetDrawLayer();
639  SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
640 
641  tools::Rectangle aRect = GetDrawRect( nCol, nRow );
642  aRect.AdjustLeft( -250 );
643  aRect.AdjustRight(250 );
644  aRect.AdjustTop( -70 );
645  aRect.AdjustBottom(70 );
646 
647  SdrCircObj* pCircle = new SdrCircObj(
648  *pModel,
649  SdrCircKind::Full,
650  aRect);
651  SfxItemSet& rAttrSet = rData.GetCircleSet();
652 
653  pCircle->SetMergedItemSetAndBroadcast(rAttrSet);
654 
655  pCircle->SetLayer( SC_LAYER_INTERN );
656  pPage->InsertObject( pCircle );
657  pModel->AddCalcUndo( std::make_unique<SdrUndoInsertObj>( *pCircle ) );
658 
659  ScDrawObjData* pData = ScDrawLayer::GetObjData( pCircle, true );
660  pData->maStart.Set( nCol, nRow, nTab);
661  pData->maEnd.SetInvalid();
663 
664  Modified();
665 }
666 
667 void ScDetectiveFunc::DeleteArrowsAt( SCCOL nCol, SCROW nRow, bool bDestPnt )
668 {
669  tools::Rectangle aRect = GetDrawRect( nCol, nRow );
670 
671  ScDrawLayer* pModel = rDoc.GetDrawLayer();
672  SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
673  OSL_ENSURE(pPage,"Page ?");
674 
675  pPage->RecalcObjOrdNums();
676 
677  const size_t nObjCount = pPage->GetObjCount();
678  if (!nObjCount)
679  return;
680 
681  size_t nDelCount = 0;
682  std::unique_ptr<SdrObject*[]> ppObj(new SdrObject*[nObjCount]);
683 
684  SdrObjListIter aIter( pPage, SdrIterMode::Flat );
685  SdrObject* pObject = aIter.Next();
686  while (pObject)
687  {
688  if ( pObject->GetLayer()==SC_LAYER_INTERN &&
689  pObject->IsPolyObj() && pObject->GetPointCount()==2 )
690  {
691  if (aRect.IsInside(pObject->GetPoint(bDestPnt ? 1 : 0))) // start/destinationpoint
692  ppObj[nDelCount++] = pObject;
693  }
694 
695  pObject = aIter.Next();
696  }
697 
698  const bool bRecording = pModel->IsRecording();
699 
700  if (bRecording)
701  {
702  for (size_t i=1; i<=nDelCount; ++i)
703  pModel->AddCalcUndo(std::make_unique<SdrUndoDelObj>(*ppObj[nDelCount-i]));
704  }
705 
706  for (size_t i=1; i<=nDelCount; ++i)
707  {
708  // remove the object from the drawing page, delete if undo is disabled
709  SdrObject* pObj = pPage->RemoveObject(ppObj[nDelCount-i]->GetOrdNum());
710  if( !bRecording )
711  SdrObject::Free( pObj );
712  }
713 
714  ppObj.reset();
715 
716  Modified();
717 }
718 
719  // delete box around reference
720 
721 #define SC_DET_TOLERANCE 50
722 
723 static bool RectIsPoints( const tools::Rectangle& rRect, const Point& rStart, const Point& rEnd )
724 {
725  return rRect.Left() >= rStart.X() - SC_DET_TOLERANCE
726  && rRect.Left() <= rStart.X() + SC_DET_TOLERANCE
727  && rRect.Right() >= rEnd.X() - SC_DET_TOLERANCE
728  && rRect.Right() <= rEnd.X() + SC_DET_TOLERANCE
729  && rRect.Top() >= rStart.Y() - SC_DET_TOLERANCE
730  && rRect.Top() <= rStart.Y() + SC_DET_TOLERANCE
731  && rRect.Bottom() >= rEnd.Y() - SC_DET_TOLERANCE
732  && rRect.Bottom() <= rEnd.Y() + SC_DET_TOLERANCE;
733 }
734 
735 #undef SC_DET_TOLERANCE
736 
737 void ScDetectiveFunc::DeleteBox( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
738 {
739  tools::Rectangle aCornerRect = GetDrawRect( nCol1, nRow1, nCol2, nRow2 );
740  Point aStartCorner = aCornerRect.TopLeft();
741  Point aEndCorner = aCornerRect.BottomRight();
742  tools::Rectangle aObjRect;
743 
744  ScDrawLayer* pModel = rDoc.GetDrawLayer();
745  SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
746  OSL_ENSURE(pPage,"Page ?");
747 
748  pPage->RecalcObjOrdNums();
749 
750  const size_t nObjCount = pPage->GetObjCount();
751  if (!nObjCount)
752  return;
753 
754  size_t nDelCount = 0;
755  std::unique_ptr<SdrObject*[]> ppObj(new SdrObject*[nObjCount]);
756 
757  SdrObjListIter aIter( pPage, SdrIterMode::Flat );
758  SdrObject* pObject = aIter.Next();
759  while (pObject)
760  {
761  if ( pObject->GetLayer() == SC_LAYER_INTERN )
762  if ( auto pSdrRectObj = dynamic_cast< const SdrRectObj* >(pObject) )
763  {
764  aObjRect = pSdrRectObj->GetLogicRect();
765  aObjRect.Justify();
766  if ( RectIsPoints( aObjRect, aStartCorner, aEndCorner ) )
767  ppObj[nDelCount++] = pObject;
768  }
769 
770  pObject = aIter.Next();
771  }
772 
773  for (size_t i=1; i<=nDelCount; ++i)
774  pModel->AddCalcUndo( std::make_unique<SdrUndoRemoveObj>( *ppObj[nDelCount-i] ) );
775 
776  for (size_t i=1; i<=nDelCount; ++i)
777  pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
778 
779  ppObj.reset();
780 
781  Modified();
782 }
783 
785  ScDetectiveData& rData, sal_uInt16 nLevel )
786 {
787  sal_uInt16 nResult = DET_INS_EMPTY;
788 
789  ScCellIterator aIter( rDoc, rRef);
790  for (bool bHasCell = aIter.first(); bHasCell; bHasCell = aIter.next())
791  {
792  if (aIter.getType() != CELLTYPE_FORMULA)
793  continue;
794 
795  const ScAddress& rPos = aIter.GetPos();
796  switch (InsertPredLevel(rPos.Col(), rPos.Row(), rData, nLevel))
797  {
798  case DET_INS_INSERTED:
799  nResult = DET_INS_INSERTED;
800  break;
801  case DET_INS_CONTINUE:
802  if (nResult != DET_INS_INSERTED)
803  nResult = DET_INS_CONTINUE;
804  break;
805  case DET_INS_CIRCULAR:
806  if (nResult == DET_INS_EMPTY)
807  nResult = DET_INS_CIRCULAR;
808  break;
809  default:
810  ;
811  }
812  }
813 
814  return nResult;
815 }
816 
818  sal_uInt16 nLevel )
819 {
820  ScRefCellValue aCell(rDoc, ScAddress(nCol, nRow, nTab));
821  if (aCell.meType != CELLTYPE_FORMULA)
822  return DET_INS_EMPTY;
823 
824  ScFormulaCell* pFCell = aCell.mpFormula;
825  if (pFCell->IsRunning())
826  return DET_INS_CIRCULAR;
827 
828  if (pFCell->GetDirty())
829  pFCell->Interpret(); // can't be called after SetRunning
830  pFCell->SetRunning(true);
831 
832  sal_uInt16 nResult = DET_INS_EMPTY;
833 
834  ScDetectiveRefIter aIter(rDoc, pFCell);
835  ScRange aRef;
836  while ( aIter.GetNextRef( aRef ) )
837  {
838  if (DrawEntry( nCol, nRow, aRef, rData ))
839  {
840  nResult = DET_INS_INSERTED; // insert new arrow
841  }
842  else
843  {
844  // continue
845 
846  if ( nLevel < rData.GetMaxLevel() )
847  {
848  sal_uInt16 nSubResult;
849  bool bArea = (aRef.aStart != aRef.aEnd);
850  if (bArea)
851  nSubResult = InsertPredLevelArea( aRef, rData, nLevel+1 );
852  else
853  nSubResult = InsertPredLevel( aRef.aStart.Col(), aRef.aStart.Row(),
854  rData, nLevel+1 );
855 
856  switch (nSubResult)
857  {
858  case DET_INS_INSERTED:
859  nResult = DET_INS_INSERTED;
860  break;
861  case DET_INS_CONTINUE:
862  if (nResult != DET_INS_INSERTED)
863  nResult = DET_INS_CONTINUE;
864  break;
865  case DET_INS_CIRCULAR:
866  if (nResult == DET_INS_EMPTY)
867  nResult = DET_INS_CIRCULAR;
868  break;
869  // DET_INS_EMPTY: no change
870  }
871  }
872  else // nMaxLevel reached
873  if (nResult != DET_INS_INSERTED)
874  nResult = DET_INS_CONTINUE;
875  }
876  }
877 
878  pFCell->SetRunning(false);
879 
880  return nResult;
881 }
882 
884  sal_uInt16 nLevel, sal_uInt16 nDeleteLevel )
885 {
886  sal_uInt16 nResult = nLevel;
887 
888  ScCellIterator aCellIter( rDoc, rRef);
889  for (bool bHasCell = aCellIter.first(); bHasCell; bHasCell = aCellIter.next())
890  {
891  if (aCellIter.getType() != CELLTYPE_FORMULA)
892  continue;
893 
894  sal_uInt16 nTemp = FindPredLevel(aCellIter.GetPos().Col(), aCellIter.GetPos().Row(), nLevel, nDeleteLevel);
895  if (nTemp > nResult)
896  nResult = nTemp;
897  }
898 
899  return nResult;
900 }
901 
902  // nDeleteLevel != 0 -> delete
903 
904 sal_uInt16 ScDetectiveFunc::FindPredLevel( SCCOL nCol, SCROW nRow, sal_uInt16 nLevel, sal_uInt16 nDeleteLevel )
905 {
906  OSL_ENSURE( nLevel<1000, "Level" );
907 
908  ScRefCellValue aCell(rDoc, ScAddress(nCol, nRow, nTab));
909  if (aCell.meType != CELLTYPE_FORMULA)
910  return nLevel;
911 
912  ScFormulaCell* pFCell = aCell.mpFormula;
913  if (pFCell->IsRunning())
914  return nLevel;
915 
916  if (pFCell->GetDirty())
917  pFCell->Interpret(); // can't be called after SetRunning
918  pFCell->SetRunning(true);
919 
920  sal_uInt16 nResult = nLevel;
921  bool bDelete = ( nDeleteLevel && nLevel == nDeleteLevel-1 );
922 
923  if ( bDelete )
924  {
925  DeleteArrowsAt( nCol, nRow, true ); // arrows, that are pointing here
926  }
927 
928  ScDetectiveRefIter aIter(rDoc, pFCell);
929  ScRange aRef;
930  while ( aIter.GetNextRef( aRef) )
931  {
932  bool bArea = ( aRef.aStart != aRef.aEnd );
933 
934  if ( bDelete ) // delete frame ?
935  {
936  if (bArea)
937  {
938  DeleteBox( aRef.aStart.Col(), aRef.aStart.Row(), aRef.aEnd.Col(), aRef.aEnd.Row() );
939  }
940  }
941  else // continue searching
942  {
943  if ( HasArrow( aRef.aStart, nCol,nRow,nTab ) )
944  {
945  sal_uInt16 nTemp;
946  if (bArea)
947  nTemp = FindPredLevelArea( aRef, nLevel+1, nDeleteLevel );
948  else
949  nTemp = FindPredLevel( aRef.aStart.Col(),aRef.aStart.Row(),
950  nLevel+1, nDeleteLevel );
951  if (nTemp > nResult)
952  nResult = nTemp;
953  }
954  }
955  }
956 
957  pFCell->SetRunning(false);
958 
959  return nResult;
960 }
961 
963  sal_uInt16 nLevel )
964 {
965  ScRefCellValue aCell(rDoc, ScAddress(nCol, nRow, nTab));
966  if (aCell.meType != CELLTYPE_FORMULA)
967  return DET_INS_EMPTY;
968 
969  ScFormulaCell* pFCell = aCell.mpFormula;
970  if (pFCell->IsRunning())
971  return DET_INS_CIRCULAR;
972 
973  if (pFCell->GetDirty())
974  pFCell->Interpret(); // can't be called after SetRunning
975  pFCell->SetRunning(true);
976 
977  sal_uInt16 nResult = DET_INS_EMPTY;
978 
979  ScDetectiveRefIter aIter(rDoc, pFCell);
980  ScRange aRef;
981  ScAddress aErrorPos;
982  bool bHasError = false;
983  while ( aIter.GetNextRef( aRef ) )
984  {
985  if (HasError( aRef, aErrorPos ))
986  {
987  bHasError = true;
988  if (DrawEntry( nCol, nRow, ScRange( aErrorPos), rData ))
989  nResult = DET_INS_INSERTED;
990 
991  if ( nLevel < rData.GetMaxLevel() ) // hits most of the time
992  {
993  if (InsertErrorLevel( aErrorPos.Col(), aErrorPos.Row(),
994  rData, nLevel+1 ) == DET_INS_INSERTED)
995  nResult = DET_INS_INSERTED;
996  }
997  }
998  }
999 
1000  pFCell->SetRunning(false);
1001 
1002  // leaves ?
1003  if (!bHasError)
1004  if (InsertPredLevel( nCol, nRow, rData, rData.GetMaxLevel() ) == DET_INS_INSERTED)
1005  nResult = DET_INS_INSERTED;
1006 
1007  return nResult;
1008 }
1009 
1010 sal_uInt16 ScDetectiveFunc::InsertSuccLevel( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1011  ScDetectiveData& rData, sal_uInt16 nLevel )
1012 {
1013  // over the entire document.
1014 
1015  sal_uInt16 nResult = DET_INS_EMPTY;
1016  ScCellIterator aCellIter(rDoc, ScRange(0,0,0,rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB)); // all sheets
1017  for (bool bHas = aCellIter.first(); bHas; bHas = aCellIter.next())
1018  {
1019  if (aCellIter.getType() != CELLTYPE_FORMULA)
1020  continue;
1021 
1022  ScFormulaCell* pFCell = aCellIter.getFormulaCell();
1023  bool bRunning = pFCell->IsRunning();
1024 
1025  if (pFCell->GetDirty())
1026  pFCell->Interpret(); // can't be called after SetRunning
1027  pFCell->SetRunning(true);
1028 
1029  ScDetectiveRefIter aIter(rDoc, pFCell);
1030  ScRange aRef;
1031  while ( aIter.GetNextRef( aRef) )
1032  {
1033  if (aRef.aStart.Tab() <= nTab && aRef.aEnd.Tab() >= nTab)
1034  {
1035  if (Intersect( nCol1,nRow1,nCol2,nRow2,
1036  aRef.aStart.Col(),aRef.aStart.Row(),
1037  aRef.aEnd.Col(),aRef.aEnd.Row() ))
1038  {
1039  bool bAlien = ( aCellIter.GetPos().Tab() != nTab );
1040  bool bDrawRet;
1041  if (bAlien)
1042  bDrawRet = DrawAlienEntry( aRef, rData );
1043  else
1044  bDrawRet = DrawEntry( aCellIter.GetPos().Col(), aCellIter.GetPos().Row(),
1045  aRef, rData );
1046  if (bDrawRet)
1047  {
1048  nResult = DET_INS_INSERTED; // insert new arrow
1049  }
1050  else
1051  {
1052  if (bRunning)
1053  {
1054  if (nResult == DET_INS_EMPTY)
1055  nResult = DET_INS_CIRCULAR;
1056  }
1057  else
1058  {
1059 
1060  if ( nLevel < rData.GetMaxLevel() )
1061  {
1062  sal_uInt16 nSubResult = InsertSuccLevel(
1063  aCellIter.GetPos().Col(), aCellIter.GetPos().Row(),
1064  aCellIter.GetPos().Col(), aCellIter.GetPos().Row(),
1065  rData, nLevel+1 );
1066  switch (nSubResult)
1067  {
1068  case DET_INS_INSERTED:
1069  nResult = DET_INS_INSERTED;
1070  break;
1071  case DET_INS_CONTINUE:
1072  if (nResult != DET_INS_INSERTED)
1073  nResult = DET_INS_CONTINUE;
1074  break;
1075  case DET_INS_CIRCULAR:
1076  if (nResult == DET_INS_EMPTY)
1077  nResult = DET_INS_CIRCULAR;
1078  break;
1079  // DET_INS_EMPTY: leave unchanged
1080  }
1081  }
1082  else // nMaxLevel reached
1083  if (nResult != DET_INS_INSERTED)
1084  nResult = DET_INS_CONTINUE;
1085  }
1086  }
1087  }
1088  }
1089  }
1090  pFCell->SetRunning(bRunning);
1091  }
1092 
1093  return nResult;
1094 }
1095 
1096 sal_uInt16 ScDetectiveFunc::FindSuccLevel( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1097  sal_uInt16 nLevel, sal_uInt16 nDeleteLevel )
1098 {
1099  OSL_ENSURE( nLevel<1000, "Level" );
1100 
1101  sal_uInt16 nResult = nLevel;
1102  bool bDelete = ( nDeleteLevel && nLevel == nDeleteLevel-1 );
1103 
1104  ScCellIterator aCellIter( rDoc, ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab) );
1105  for (bool bHas = aCellIter.first(); bHas; bHas = aCellIter.next())
1106  {
1107  if (aCellIter.getType() != CELLTYPE_FORMULA)
1108  continue;
1109 
1110  ScFormulaCell* pFCell = aCellIter.getFormulaCell();
1111  bool bRunning = pFCell->IsRunning();
1112 
1113  if (pFCell->GetDirty())
1114  pFCell->Interpret(); // can't be called after SetRunning
1115  pFCell->SetRunning(true);
1116 
1117  ScDetectiveRefIter aIter(rDoc, pFCell);
1118  ScRange aRef;
1119  while ( aIter.GetNextRef( aRef) )
1120  {
1121  if (aRef.aStart.Tab() <= nTab && aRef.aEnd.Tab() >= nTab)
1122  {
1123  if (Intersect( nCol1,nRow1,nCol2,nRow2,
1124  aRef.aStart.Col(),aRef.aStart.Row(),
1125  aRef.aEnd.Col(),aRef.aEnd.Row() ))
1126  {
1127  if ( bDelete ) // arrows, that are starting here
1128  {
1129  if (aRef.aStart != aRef.aEnd)
1130  {
1131  DeleteBox( aRef.aStart.Col(), aRef.aStart.Row(),
1132  aRef.aEnd.Col(), aRef.aEnd.Row() );
1133  }
1134  DeleteArrowsAt( aRef.aStart.Col(), aRef.aStart.Row(), false );
1135  }
1136  else if ( !bRunning &&
1137  HasArrow( aRef.aStart,
1138  aCellIter.GetPos().Col(),aCellIter.GetPos().Row(),aCellIter.GetPos().Tab() ) )
1139  {
1140  sal_uInt16 nTemp = FindSuccLevel( aCellIter.GetPos().Col(), aCellIter.GetPos().Row(),
1141  aCellIter.GetPos().Col(), aCellIter.GetPos().Row(),
1142  nLevel+1, nDeleteLevel );
1143  if (nTemp > nResult)
1144  nResult = nTemp;
1145  }
1146  }
1147  }
1148  }
1149 
1150  pFCell->SetRunning(bRunning);
1151  }
1152 
1153  return nResult;
1154 }
1155 
1157 {
1158  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1159  if (!pModel)
1160  return false;
1161 
1162  ScDetectiveData aData( pModel );
1163 
1164  sal_uInt16 nMaxLevel = 0;
1165  sal_uInt16 nResult = DET_INS_CONTINUE;
1166  while (nResult == DET_INS_CONTINUE && nMaxLevel < 1000)
1167  {
1168  aData.SetMaxLevel( nMaxLevel );
1169  nResult = InsertPredLevel( nCol, nRow, aData, 0 );
1170  ++nMaxLevel;
1171  }
1172 
1173  return ( nResult == DET_INS_INSERTED );
1174 }
1175 
1177 {
1178  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1179  if (!pModel)
1180  return false;
1181 
1182  ScDetectiveData aData( pModel );
1183 
1184  sal_uInt16 nMaxLevel = 0;
1185  sal_uInt16 nResult = DET_INS_CONTINUE;
1186  while (nResult == DET_INS_CONTINUE && nMaxLevel < 1000)
1187  {
1188  aData.SetMaxLevel( nMaxLevel );
1189  nResult = InsertSuccLevel( nCol, nRow, nCol, nRow, aData, 0 );
1190  ++nMaxLevel;
1191  }
1192 
1193  return ( nResult == DET_INS_INSERTED );
1194 }
1195 
1197 {
1198  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1199  if (!pModel)
1200  return false;
1201 
1202  ScRange aRange( nCol, nRow, nTab );
1203  ScAddress aErrPos;
1204  if ( !HasError( aRange,aErrPos ) )
1205  return false;
1206 
1207  ScDetectiveData aData( pModel );
1208 
1209  aData.SetMaxLevel( 1000 );
1210  sal_uInt16 nResult = InsertErrorLevel( nCol, nRow, aData, 0 );
1211 
1212  return ( nResult == DET_INS_INSERTED );
1213 }
1214 
1216 {
1217  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1218  if (!pModel)
1219  return false;
1220 
1221  sal_uInt16 nLevelCount = FindSuccLevel( nCol, nRow, nCol, nRow, 0, 0 );
1222  if ( nLevelCount )
1223  FindSuccLevel( nCol, nRow, nCol, nRow, 0, nLevelCount ); // delete
1224 
1225  return ( nLevelCount != 0 );
1226 }
1227 
1229 {
1230  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1231  if (!pModel)
1232  return false;
1233 
1234  sal_uInt16 nLevelCount = FindPredLevel( nCol, nRow, 0, 0 );
1235  if ( nLevelCount )
1236  FindPredLevel( nCol, nRow, 0, nLevelCount ); // delete
1237 
1238  return ( nLevelCount != 0 );
1239 }
1240 
1242 {
1243  tools::Rectangle aRect = GetDrawRect(nCol, nRow);
1244  aRect.AdjustLeft(-250);
1245  aRect.AdjustRight(250);
1246  aRect.AdjustTop(-70);
1247  aRect.AdjustBottom(70);
1248 
1249  Point aStartCorner = aRect.TopLeft();
1250  Point aEndCorner = aRect.BottomRight();
1251 
1252  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1253  if (!pModel)
1254  return false;
1255 
1256  SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
1257  OSL_ENSURE(pPage, "Page ?");
1258 
1259  pPage->RecalcObjOrdNums();
1260 
1261  const size_t nObjCount = pPage->GetObjCount();
1262  size_t nDelCount = 0;
1263  if (nObjCount)
1264  {
1265  std::unique_ptr<SdrObject*[]> ppObj(new SdrObject*[nObjCount]);
1266 
1267  SdrObjListIter aIter(pPage, SdrIterMode::Flat);
1268  SdrObject* pObject = aIter.Next();
1269  while (pObject)
1270  {
1271  if (pObject->GetLayer() == SC_LAYER_INTERN)
1272  if (auto pSdrCircObj = dynamic_cast<const SdrCircObj*>(pObject) )
1273  {
1274  tools::Rectangle aObjRect = pSdrCircObj->GetLogicRect();
1275  if (RectIsPoints(aObjRect, aStartCorner, aEndCorner))
1276  ppObj[nDelCount++] = pObject;
1277  }
1278 
1279  pObject = aIter.Next();
1280  }
1281 
1282  for (size_t i = 1; i <= nDelCount; ++i)
1283  pModel->AddCalcUndo(std::make_unique<SdrUndoRemoveObj>(*ppObj[nDelCount - i]));
1284 
1285  for (size_t i = 1; i <= nDelCount; ++i)
1286  pPage->RemoveObject(ppObj[nDelCount - i]->GetOrdNum());
1287 
1288  ppObj.reset();
1289 
1290  Modified();
1291  }
1292 
1293  return (nDelCount != 0);
1294 }
1295 
1297 {
1298  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1299  if (!pModel)
1300  return false;
1301 
1302  SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
1303  OSL_ENSURE(pPage,"Page ?");
1304 
1305  pPage->RecalcObjOrdNums();
1306 
1307  size_t nDelCount = 0;
1308  const size_t nObjCount = pPage->GetObjCount();
1309  if (nObjCount)
1310  {
1311  std::unique_ptr<SdrObject*[]> ppObj(new SdrObject*[nObjCount]);
1312 
1313  SdrObjListIter aIter( pPage, SdrIterMode::Flat );
1314  SdrObject* pObject = aIter.Next();
1315  while (pObject)
1316  {
1317  if ( pObject->GetLayer() == SC_LAYER_INTERN )
1318  {
1319  bool bDoThis = true;
1320  bool bCircle = ( dynamic_cast<const SdrCircObj*>( pObject) != nullptr );
1321  bool bCaption = ScDrawLayer::IsNoteCaption( pObject );
1322  if ( eWhat == ScDetectiveDelete::Detective ) // detective, from menu
1323  bDoThis = !bCaption; // also circles
1324  else if ( eWhat == ScDetectiveDelete::Circles ) // circles, if new created
1325  bDoThis = bCircle;
1326  else if ( eWhat == ScDetectiveDelete::Arrows ) // DetectiveRefresh
1327  bDoThis = !bCaption && !bCircle; // don't include circles
1328  else
1329  {
1330  OSL_FAIL("what?");
1331  }
1332  if ( bDoThis )
1333  ppObj[nDelCount++] = pObject;
1334  }
1335 
1336  pObject = aIter.Next();
1337  }
1338 
1339  for (size_t i=1; i<=nDelCount; ++i)
1340  pModel->AddCalcUndo( std::make_unique<SdrUndoRemoveObj>( *ppObj[nDelCount-i] ) );
1341 
1342  for (size_t i=1; i<=nDelCount; ++i)
1343  pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1344 
1345  ppObj.reset();
1346 
1347  Modified();
1348  }
1349 
1350  return ( nDelCount != 0 );
1351 }
1352 
1353 bool ScDetectiveFunc::MarkInvalid(bool& rOverflow)
1354 {
1355  rOverflow = false;
1356  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1357  if (!pModel)
1358  return false;
1359 
1360  bool bDeleted = DeleteAll( ScDetectiveDelete::Circles ); // just circles
1361 
1362  ScDetectiveData aData( pModel );
1363  tools::Long nInsCount = 0;
1364 
1365  // search for valid places
1366  ScDocAttrIterator aAttrIter( rDoc, nTab, 0,0,rDoc.MaxCol(),rDoc.MaxRow() );
1367  SCCOL nCol;
1368  SCROW nRow1;
1369  SCROW nRow2;
1370  const ScPatternAttr* pPattern = aAttrIter.GetNext( nCol, nRow1, nRow2 );
1371  while ( pPattern && nInsCount < SC_DET_MAXCIRCLE )
1372  {
1373  sal_uLong nIndex = pPattern->GetItem(ATTR_VALIDDATA).GetValue();
1374  if (nIndex)
1375  {
1376  const ScValidationData* pData = rDoc.GetValidationEntry( nIndex );
1377  if ( pData )
1378  {
1379  // pass cells in this area
1380 
1381  bool bMarkEmpty = !pData->IsIgnoreBlank();
1382  SCROW nNextRow = nRow1;
1383  SCROW nRow;
1384  ScCellIterator aCellIter( rDoc, ScRange(nCol, nRow1, nTab, nCol, nRow2, nTab) );
1385  for (bool bHas = aCellIter.first(); bHas && nInsCount < SC_DET_MAXCIRCLE; bHas = aCellIter.next())
1386  {
1387  SCROW nCellRow = aCellIter.GetPos().Row();
1388  if ( bMarkEmpty )
1389  for ( nRow = nNextRow; nRow < nCellRow && nInsCount < SC_DET_MAXCIRCLE; nRow++ )
1390  {
1391  DrawCircle( nCol, nRow, aData );
1392  ++nInsCount;
1393  }
1394  ScRefCellValue aCell = aCellIter.getRefCellValue();
1395  if (!pData->IsDataValid(aCell, aCellIter.GetPos()))
1396  {
1397  DrawCircle( nCol, nCellRow, aData );
1398  ++nInsCount;
1399  }
1400  nNextRow = nCellRow + 1;
1401  }
1402  if ( bMarkEmpty )
1403  for ( nRow = nNextRow; nRow <= nRow2 && nInsCount < SC_DET_MAXCIRCLE; nRow++ )
1404  {
1405  DrawCircle( nCol, nRow, aData );
1406  ++nInsCount;
1407  }
1408  }
1409  }
1410 
1411  pPattern = aAttrIter.GetNext( nCol, nRow1, nRow2 );
1412  }
1413 
1414  if ( nInsCount >= SC_DET_MAXCIRCLE )
1415  rOverflow = true;
1416 
1417  return ( bDeleted || nInsCount != 0 );
1418 }
1419 
1420 void ScDetectiveFunc::GetAllPreds(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1421  vector<ScTokenRef>& rRefTokens)
1422 {
1423  ScCellIterator aIter(rDoc, ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab));
1424  for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
1425  {
1426  if (aIter.getType() != CELLTYPE_FORMULA)
1427  continue;
1428 
1429  ScFormulaCell* pFCell = aIter.getFormulaCell();
1430  ScDetectiveRefIter aRefIter(rDoc, pFCell);
1431  for (formula::FormulaToken* p = aRefIter.GetNextRefToken(); p; p = aRefIter.GetNextRefToken())
1432  {
1433  ScTokenRef pRef(p->Clone());
1434  ScRefTokenHelper::join(&rDoc, rRefTokens, pRef, aIter.GetPos());
1435  }
1436  }
1437 }
1438 
1439 void ScDetectiveFunc::GetAllSuccs(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1440  vector<ScTokenRef>& rRefTokens)
1441 {
1442  vector<ScTokenRef> aSrcRange;
1443  aSrcRange.push_back(
1444  ScRefTokenHelper::createRefToken(rDoc, ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab)));
1445 
1446  ScCellIterator aIter(rDoc, ScRange(0, 0, nTab, rDoc.MaxCol(), rDoc.MaxRow(), nTab));
1447  for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
1448  {
1449  if (aIter.getType() != CELLTYPE_FORMULA)
1450  continue;
1451 
1452  ScFormulaCell* pFCell = aIter.getFormulaCell();
1453  ScDetectiveRefIter aRefIter(rDoc, pFCell);
1454  for (formula::FormulaToken* p = aRefIter.GetNextRefToken(); p; p = aRefIter.GetNextRefToken())
1455  {
1456  const ScAddress& aPos = aIter.GetPos();
1457  ScTokenRef pRef(p->Clone());
1458  if (ScRefTokenHelper::intersects(&rDoc, aSrcRange, pRef, aPos))
1459  {
1460  // This address is absolute.
1461  pRef = ScRefTokenHelper::createRefToken(rDoc, aPos);
1462  ScRefTokenHelper::join(&rDoc, rRefTokens, pRef, ScAddress());
1463  }
1464  }
1465  }
1466 }
1467 
1469 {
1470  // for all caption objects, update attributes and SpecialTextBoxShadow flag
1471  // (on all tables - nTab is ignored!)
1472 
1473  // no undo actions, this is refreshed after undo
1474 
1475  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1476  if (!pModel)
1477  return;
1478 
1479  for( SCTAB nObjTab = 0, nTabCount = rDoc.GetTableCount(); nObjTab < nTabCount; ++nObjTab )
1480  {
1481  SdrPage* pPage = pModel->GetPage( static_cast< sal_uInt16 >( nObjTab ) );
1482  OSL_ENSURE( pPage, "Page ?" );
1483  if( pPage )
1484  {
1485  SdrObjListIter aIter( pPage, SdrIterMode::Flat );
1486  for( SdrObject* pObject = aIter.Next(); pObject; pObject = aIter.Next() )
1487  {
1489  {
1490  ScPostIt* pNote = rDoc.GetNote( pData->maStart );
1491  // caption should exist, we iterate over drawing objects...
1492  OSL_ENSURE( pNote && (pNote->GetCaption() == pObject), "ScDetectiveFunc::UpdateAllComments - invalid cell note" );
1493  if( pNote )
1494  {
1495  ScCommentData aData( rDoc, pModel );
1496  SfxItemSet aAttrColorSet = pObject->GetMergedItemSet();
1497  aAttrColorSet.Put( XFillColorItem( OUString(), GetCommentColor() ) );
1498  aData.UpdateCaptionSet( aAttrColorSet );
1499  pObject->SetMergedItemSetAndBroadcast( aData.GetCaptionSet() );
1500  if( SdrCaptionObj* pCaption = dynamic_cast< SdrCaptionObj* >( pObject ) )
1501  {
1502  pCaption->SetSpecialTextBoxShadow();
1503  pCaption->SetFixedTail();
1504  }
1505  }
1506  }
1507  }
1508  }
1509  }
1510 }
1511 
1513 {
1514  // no undo actions necessary
1515 
1516  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1517  if (!pModel)
1518  return;
1519 
1520  for( SCTAB nObjTab = 0, nTabCount = rDoc.GetTableCount(); nObjTab < nTabCount; ++nObjTab )
1521  {
1522  SdrPage* pPage = pModel->GetPage( static_cast< sal_uInt16 >( nObjTab ) );
1523  OSL_ENSURE( pPage, "Page ?" );
1524  if( pPage )
1525  {
1526  SdrObjListIter aIter( pPage, SdrIterMode::Flat );
1527  for( SdrObject* pObject = aIter.Next(); pObject; pObject = aIter.Next() )
1528  {
1529  if ( pObject->GetLayer() == SC_LAYER_INTERN )
1530  {
1531  bool bArrow = false;
1532  bool bError = false;
1533 
1534  ScAddress aPos;
1535  ScRange aSource;
1536  bool bDummy;
1537  ScDetectiveObjType eType = GetDetectiveObjectType( pObject, nObjTab, aPos, aSource, bDummy );
1538  if ( eType == SC_DETOBJ_ARROW || eType == SC_DETOBJ_TOOTHERTAB )
1539  {
1540  // source is valid, determine error flag from source range
1541 
1542  ScAddress aErrPos;
1543  if ( HasError( aSource, aErrPos ) )
1544  bError = true;
1545  else
1546  bArrow = true;
1547  }
1548  else if ( eType == SC_DETOBJ_FROMOTHERTAB )
1549  {
1550  // source range is no longer known, take error flag from formula itself
1551  // (this means, if the formula has an error, all references to other tables
1552  // are marked red)
1553 
1554  ScAddress aErrPos;
1555  if ( HasError( ScRange( aPos), aErrPos ) )
1556  bError = true;
1557  else
1558  bArrow = true;
1559  }
1560  else if ( eType == SC_DETOBJ_CIRCLE )
1561  {
1562  // circles (error marks) are always red
1563 
1564  bError = true;
1565  }
1566  else if ( eType == SC_DETOBJ_NONE )
1567  {
1568  // frame for area reference has no ObjType, always gets arrow color
1569 
1570  if ( dynamic_cast<const SdrRectObj*>( pObject) != nullptr && dynamic_cast<const SdrCaptionObj*>( pObject) == nullptr )
1571  {
1572  bArrow = true;
1573  }
1574  }
1575 
1576  if ( bArrow || bError )
1577  {
1578  Color nColor = ( bError ? GetErrorColor() : GetArrowColor() );
1579  pObject->SetMergedItem( XLineColorItem( OUString(), nColor ) );
1580 
1581  // repaint only
1582  pObject->ActionChanged();
1583  }
1584  }
1585  }
1586  }
1587  }
1588 }
1589 
1591 {
1592  // find the rectangle for an arrow (always the object directly before the arrow)
1593  // rRange must be initialized to the source cell of the arrow (start of area)
1594 
1595  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1596  if (!pModel) return;
1597 
1598  SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
1599  OSL_ENSURE(pPage,"Page ?");
1600  if (!pPage) return;
1601 
1602  // test if the object is a direct page member
1603  if( !(pObject && pObject->getSdrPageFromSdrObject() && (pObject->getSdrPageFromSdrObject() == pObject->getParentSdrObjListFromSdrObject()->getSdrPageFromSdrObjList())) )
1604  return;
1605 
1606  // Is there a previous object?
1607  const size_t nOrdNum = pObject->GetOrdNum();
1608 
1609  if(nOrdNum <= 0)
1610  return;
1611 
1612  SdrObject* pPrevObj = pPage->GetObj(nOrdNum - 1);
1613 
1614  if ( pPrevObj && pPrevObj->GetLayer() == SC_LAYER_INTERN && dynamic_cast<const SdrRectObj*>( pPrevObj) != nullptr )
1615  {
1616  ScDrawObjData* pPrevData = ScDrawLayer::GetObjDataTab( pPrevObj, rRange.aStart.Tab() );
1617  if ( pPrevData && pPrevData->maStart.IsValid() && pPrevData->maEnd.IsValid() && (pPrevData->maStart == rRange.aStart) )
1618  {
1619  rRange.aEnd = pPrevData->maEnd;
1620  return;
1621  }
1622  }
1623 }
1624 
1626  ScAddress& rPosition, ScRange& rSource, bool& rRedLine )
1627 {
1628  rRedLine = false;
1630 
1631  if ( pObject && pObject->GetLayer() == SC_LAYER_INTERN )
1632  {
1633  if ( ScDrawObjData* pData = ScDrawLayer::GetObjDataTab( pObject, nObjTab ) )
1634  {
1635  bool bValidStart = pData->maStart.IsValid();
1636  bool bValidEnd = pData->maEnd.IsValid();
1637 
1638  if ( pObject->IsPolyObj() && pObject->GetPointCount() == 2 )
1639  {
1640  // line object -> arrow
1641 
1642  if ( bValidStart )
1643  eType = bValidEnd ? SC_DETOBJ_ARROW : SC_DETOBJ_TOOTHERTAB;
1644  else if ( bValidEnd )
1645  eType = SC_DETOBJ_FROMOTHERTAB;
1646 
1647  if ( bValidStart )
1648  rSource = pData->maStart;
1649  if ( bValidEnd )
1650  rPosition = pData->maEnd;
1651 
1652  if ( bValidStart && lcl_HasThickLine( *pObject ) )
1653  {
1654  // thick line -> look for frame before this object
1655 
1656  FindFrameForObject( pObject, rSource ); // modifies rSource
1657  }
1658 
1659  Color nObjColor = pObject->GetMergedItem(XATTR_LINECOLOR).GetColorValue();
1660  if ( nObjColor == GetErrorColor() && nObjColor != GetArrowColor() )
1661  rRedLine = true;
1662  }
1663  else if (dynamic_cast<const SdrCircObj*>(pObject) != nullptr)
1664  {
1665  if (bValidStart)
1666  {
1667  // cell position is returned in rPosition
1668  rPosition = pData->maStart;
1669  eType = SC_DETOBJ_CIRCLE;
1670  }
1671  }
1672  else if (dynamic_cast<const SdrRectObj*>(pObject) != nullptr)
1673  {
1674  if (bValidStart)
1675  {
1676  // cell position is returned in rPosition
1677  rPosition = pData->maStart;
1678  eType = SC_DETOBJ_RECTANGLE;
1679  }
1680  }
1681  }
1682  }
1683 
1684  return eType;
1685 }
1686 
1688  const ScAddress& rPosition, const ScRange& rSource,
1689  bool bRedLine )
1690 {
1691  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1692  if (!pModel) return;
1693  ScDetectiveData aData( pModel );
1694 
1695  switch (eType)
1696  {
1697  case SC_DETOBJ_ARROW:
1699  InsertArrow( rPosition.Col(), rPosition.Row(),
1700  rSource.aStart.Col(), rSource.aStart.Row(),
1701  rSource.aEnd.Col(), rSource.aEnd.Row(),
1702  (eType == SC_DETOBJ_FROMOTHERTAB), bRedLine, aData );
1703  break;
1704  case SC_DETOBJ_TOOTHERTAB:
1705  InsertToOtherTab( rSource.aStart.Col(), rSource.aStart.Row(),
1706  rSource.aEnd.Col(), rSource.aEnd.Row(),
1707  bRedLine, aData );
1708  break;
1709  case SC_DETOBJ_CIRCLE:
1710  DrawCircle( rPosition.Col(), rPosition.Row(), aData );
1711  break;
1712  default:
1713  {
1714  // added to avoid warnings
1715  }
1716  }
1717 }
1718 
1720 {
1721  if (!bColorsInitialized)
1722  InitializeColors();
1723  return nArrowColor;
1724 }
1725 
1727 {
1728  if (!bColorsInitialized)
1729  InitializeColors();
1730  return nErrorColor;
1731 }
1732 
1734 {
1735  if (!bColorsInitialized)
1736  InitializeColors();
1737  return nCommentColor;
1738 }
1739 
1741 {
1742  // may be called several times to update colors from configuration
1743 
1744  const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
1748 
1749  bColorsInitialized = true;
1750 }
1751 
1753 {
1754  return bColorsInitialized;
1755 }
1756 
1758 {
1759  rDisplay += "\n--------\n";
1760 }
1761 
1762 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
tools::Rectangle GetDrawRect(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const
Definition: detfunc.cxx:346
bool ShowPred(SCCOL nCol, SCROW nRow)
Definition: detfunc.cxx:1156
Point TopLeft() const
static Color nArrowColor
Definition: detfunc.hxx:51
void DeleteBox(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2)
Definition: detfunc.cxx:737
bool IsDataValid(const OUString &rTest, const ScPatternAttr &rPattern, const ScAddress &rPos) const
Definition: validat.cxx:526
void FindFrameForObject(const SdrObject *pObject, ScRange &rRange)
Definition: detfunc.cxx:1590
SfxItemSet aFromTabSet
Definition: detfunc.cxx:100
SCCOL SanitizeCol(SCCOL nCol) const
Definition: document.hxx:881
ScDetectiveData(SdrModel *pModel)
Definition: detfunc.cxx:145
sal_Int32 nIndex
void append(const basegfx::B2DPoint &rPoint, sal_uInt32 nCount)
ScAddress aStart
Definition: address.hxx:500
SfxItemSet & GetBoxSet()
Definition: detfunc.cxx:107
constexpr TypedWhichId< XLineEndItem > XATTR_LINEEND(XATTR_LINE_FIRST+5)
constexpr TypedWhichId< ScPatternAttr > ATTR_PATTERN(156)
#define EMPTY_OUSTRING
Definition: global.hxx:215
constexpr TypedWhichId< XLineStartItem > XATTR_LINESTART(XATTR_LINE_FIRST+4)
bool ShowSucc(SCCOL nCol, SCROW nRow)
Definition: detfunc.cxx:1176
SC_DLLPUBLIC bool IsNegativePage(SCTAB nTab) const
Definition: document.cxx:1002
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
SCROW Row() const
Definition: address.hxx:262
SfxItemSet & GetFromTabSet()
Definition: detfunc.cxx:110
const char aData[]
DetInsertResult
Definition: detfunc.cxx:86
std::unique_ptr< ContentProperties > pData
sal_uInt16 InsertPredLevelArea(const ScRange &rRef, ScDetectiveData &rData, sal_uInt16 nLevel)
Definition: detfunc.cxx:784
#define SC_DET_MAXCIRCLE
Definition: detfunc.hxx:35
virtual bool IsPolyObj() const
sal_uInt16 FindPredLevel(SCCOL nCol, SCROW nRow, sal_uInt16 nLevel, sal_uInt16 nDeleteLevel)
Definition: detfunc.cxx:904
bool GetDirty() const
sal_uIntPtr sal_uLong
long Long
static ScDrawObjData * GetObjData(SdrObject *pObj, bool bCreate=false)
Definition: drwlayer.cxx:2282
constexpr TypedWhichId< XLineWidthItem > XATTR_LINEWIDTH(XATTR_LINE_FIRST+2)
SdrObject * GetObj(size_t nNum) const
static bool IsNonAlienArrow(const SdrObject *pObject)
Definition: detfunc.cxx:430
void RecalcObjOrdNums()
CALCNOTESBACKGROUND
sal_uInt16 InsertErrorLevel(SCCOL nCol, SCROW nRow, ScDetectiveData &rData, sal_uInt16 nLevel)
Definition: detfunc.cxx:962
size_t GetObjCount() const
constexpr sal_uInt16 EE_ITEMS_END(EE_FEATURE_END)
static Color GetErrorColor()
Definition: detfunc.cxx:1726
void SC_DLLPUBLIC join(const ScDocument *pDoc,::std::vector< ScTokenRef > &rTokens, const ScTokenRef &pToken, const ScAddress &rPos)
void InsertObject(ScDetectiveObjType eType, const ScAddress &rPosition, const ScRange &rSource, bool bRedLine)
Definition: detfunc.cxx:1687
ScAddress aEnd
Definition: address.hxx:501
This is very similar to ScCellValue, except that it references the original value instead of copying ...
Definition: cellvalue.hxx:104
SfxItemSet aArrowSet
Definition: detfunc.cxx:98
void UpdateAllArrowColors()
on all tables
Definition: detfunc.cxx:1512
void GetAllPreds(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,::std::vector< ScTokenRef > &rRefTokens)
Definition: detfunc.cxx:1420
static bool lcl_IsOtherTab(const basegfx::B2DPolyPolygon &rPolyPolygon)
Definition: detfunc.cxx:360
virtual sal_uInt32 GetPointCount() const
static void Free(SdrObject *&_rpObject)
virtual void InsertObject(SdrObject *pObj, size_t nPos=SAL_MAX_SIZE)
CALCDETECTIVEERROR
EmbeddedObjectRef * pObject
ScAddress maStart
Definition: userdat.hxx:38
ScFormulaCell * getFormulaCell()
Definition: dociter.hxx:239
constexpr sal_uInt16 SDRATTR_START(XATTR_START)
SC_DLLPUBLIC sal_uInt16 GetRowHeight(SCROW nRow, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4161
SdrOnOffItem makeSdrTextAutoGrowHeightItem(bool bAuto)
CellType getType() const
Definition: dociter.hxx:236
SC_DLLPUBLIC const ScValidationData * GetValidationEntry(sal_uLong nIndex) const
Definition: documen4.cxx:871
SfxItemSet & GetToTabSet()
Definition: detfunc.cxx:109
bool ShowError(SCCOL nCol, SCROW nRow)
Definition: detfunc.cxx:1196
B2DPolygon const & getB2DPolygon(sal_uInt32 nIndex) const
SC_DLLPUBLIC ScPostIt * GetNote(const ScAddress &rPos)
Notes.
Definition: document.cxx:6508
Point GetDrawPos(SCCOL nCol, SCROW nRow, DrawPosMode eMode) const
Definition: detfunc.cxx:311
static bool lcl_HasThickLine(const SdrObject &rObj)
Definition: detfunc.cxx:138
static Color nErrorColor
Definition: detfunc.hxx:52
tools::Long Left() const
SdrPage * getSdrPageFromSdrObject() const
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:873
static Color GetArrowColor()
Definition: detfunc.cxx:1719
sal_uInt16 InsertSuccLevel(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScDetectiveData &rData, sal_uInt16 nLevel)
Definition: detfunc.cxx:1010
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:314
Additional class containing cell annotation data.
Definition: postit.hxx:160
FormulaError GetErrCode()
Top-left edge of the cell.
tools::Long Bottom() const
bool DeletePred(SCCOL nCol, SCROW nRow)
Definition: detfunc.cxx:1228
const ScRefCellValue & getRefCellValue() const
Definition: dociter.hxx:242
void Modified()
Definition: detfunc.cxx:280
ScTokenRef createRefToken(const ScDocument &rDoc, const ScAddress &rAddr)
bool DrawEntry(SCCOL nCol, SCROW nRow, const ScRange &rRef, ScDetectiveData &rData)
DrawEntry / DrawAlienEntry check for existing arrows and errors.
Definition: detfunc.cxx:603
Walk through all cells in an area.
Definition: dociter.hxx:208
ScFormulaCell * mpFormula
Definition: cellvalue.hxx:111
#define HMM_PER_TWIPS
Definition: global.hxx:92
SCTAB Tab() const
Definition: address.hxx:271
SdrOnOffItem makeSdrTextAutoGrowWidthItem(bool bAuto)
void SetMaxLevel(sal_uInt16 nVal)
Definition: detfunc.cxx:113
sal_uInt16 nMaxLevel
Definition: detfunc.cxx:102
constexpr TypedWhichId< SdrOnOffItem > SDRATTR_SHADOW(SDRATTR_SHADOW_FIRST+0)
sal_uInt16 FindSuccLevel(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uInt16 nLevel, sal_uInt16 nDeleteLevel)
Definition: detfunc.cxx:1096
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
SdrMetricItem makeSdrTextUpperDistItem(long mnHeight)
const SfxPoolItem & GetItem(sal_uInt16 nWhichP) const
Definition: patattr.hxx:70
static bool IsColorsInitialized()
Definition: detfunc.cxx:1752
DocumentType eType
bool IsValid() const
Definition: address.hxx:293
constexpr TypedWhichId< SfxUInt32Item > ATTR_VALIDDATA(153)
void DrawCircle(SCCOL nCol, SCROW nRow, ScDetectiveData &rData)
Definition: detfunc.cxx:636
Point BottomRight() const
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1059
virtual void SetLayer(SdrLayerID nLayer)
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:872
OBJ_LINE
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
int i
Bottom-right edge of the cell.
ScDetectiveObjType
Definition: detfunc.hxx:39
void Set(SCCOL nCol, SCROW nRow, SCTAB nTab)
Definition: address.hxx:406
sal_Int16 SCCOL
Definition: types.hxx:22
static ScDrawObjData * GetNoteCaptionData(SdrObject *pObj, SCTAB nTab)
Returns the object data, if the passed object is a cell note caption.
Definition: drwlayer.cxx:2315
Iterator for references in a formula cell.
Definition: formulaiter.hxx:32
static bool bColorsInitialized
Definition: detfunc.hxx:54
#define SC_MOD()
Definition: scmod.hxx:253
SfxItemSet aToTabSet
Definition: detfunc.cxx:99
bool MarkInvalid(bool &rOverflow)
Definition: detfunc.cxx:1353
static Color nCommentColor
Definition: detfunc.hxx:53
const SdrPage * GetPage(sal_uInt16 nPgNum) const
bool Interpret(SCROW nStartOffset=-1, SCROW nEndOffset=-1)
constexpr sal_uInt16 EE_ITEMS_START(OWN_ATTR_VALUE_END+1)
void SetMergedItemSetAndBroadcast(const SfxItemSet &rSet, bool bClearAllItems=false)
static void UpdateAllComments(ScDocument &rDoc)
on all tables
Definition: detfunc.cxx:1468
sal_uInt32 GetOrdNum() const
constexpr TypedWhichId< SdrMetricItem > SDRATTR_SHADOWYDIST(SDRATTR_SHADOW_FIRST+3)
void AddCalcUndo(std::unique_ptr< SdrUndoAction > pUndo)
Definition: drwlayer.cxx:1242
bool IsInside(const Point &rPOINT) const
SfxItemSet aBoxSet
Definition: detfunc.cxx:97
bool IsRunning() const
const SfxPoolItem & GetMergedItem(const sal_uInt16 nWhich) const
const SCTAB MAXTAB
Definition: address.hxx:71
tools::Long Top() const
sal_uInt16 InsertPredLevel(SCCOL nCol, SCROW nRow, ScDetectiveData &rData, sal_uInt16 nLevel)
Definition: detfunc.cxx:817
sal_uInt16 GetMaxLevel() const
Definition: detfunc.cxx:114
static bool RectIsPoints(const tools::Rectangle &rRect, const Point &rStart, const Point &rEnd)
Definition: detfunc.cxx:723
virtual SdrObject * RemoveObject(size_t nObjNum)
sal_uInt16 FindPredLevelArea(const ScRange &rRef, sal_uInt16 nLevel, sal_uInt16 nDeleteLevel)
Definition: detfunc.cxx:883
FormulaError
SdrMetricItem makeSdrShadowYDistItem(long nDist)
SCCOL Col() const
Definition: address.hxx:267
bool DeleteCirclesAt(SCCOL nCol, SCROW nRow)
Definition: detfunc.cxx:1241
bool DeleteAll(ScDetectiveDelete eWhat)
Definition: detfunc.cxx:1296
virtual SdrLayerID GetLayer() const
tools::Long AdjustTop(tools::Long nVertMoveDelta)
bool DeleteSucc(SCCOL nCol, SCROW nRow)
Definition: detfunc.cxx:1215
SCROW SanitizeRow(SCROW nRow) const
Definition: document.hxx:882
const ScAddress & GetPos() const
Definition: dociter.hxx:234
bool ValidColRow(SCCOL nCol, SCROW nRow) const
Definition: document.hxx:877
CellType meType
Definition: cellvalue.hxx:106
static Color GetCommentColor()
Definition: detfunc.cxx:1733
SdrObject * Next()
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
constexpr TypedWhichId< SdrMetricItem > SDRATTR_SHADOWXDIST(SDRATTR_SHADOW_FIRST+2)
void setClosed(bool bNew)
sal_Int32 SCROW
Definition: types.hxx:18
constexpr sal_uInt16 SDRATTR_END(SDRATTR_SOFTEDGE_LAST)
SfxItemSet aCircleSet
Definition: detfunc.cxx:101
ScDetectiveDelete
Definition: detfunc.hxx:37
SdrCaptionObj * GetCaption() const
Returns an existing note caption object.
Definition: postit.hxx:237
void GetAllSuccs(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,::std::vector< ScTokenRef > &rRefTokens)
Definition: detfunc.cxx:1439
sal_uInt32 count() const
void SetStreamValid(SCTAB nTab, bool bSet, bool bIgnoreLock=false)
Definition: document.cxx:925
static bool Intersect(SCCOL nStartCol1, SCROW nStartRow1, SCCOL nEndCol1, SCROW nEndRow1, SCCOL nStartCol2, SCROW nStartRow2, SCCOL nEndCol2, SCROW nEndRow2)
Definition: detfunc.cxx:285
bool GetNextRef(ScRange &rRange)
Definition: formulaiter.cxx:52
ColorConfigValue GetColorValue(ColorConfigEntry eEntry, bool bSmart=true) const
static void AppendChangTrackNoteSeparator(OUString &str)
Definition: detfunc.cxx:1757
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
bool HasError(const ScRange &rRange, ScAddress &rErrPos)
Definition: detfunc.cxx:292
static ScDrawObjData * GetObjDataTab(SdrObject *pObj, SCTAB nTab)
Definition: drwlayer.cxx:2296
static void InitializeColors()
Definition: detfunc.cxx:1740
bool HasArrow(const ScAddress &rStart, SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab)
Definition: detfunc.cxx:378
OUString aName
const SfxItemSet & GetMergedItemSet() const
Position inside cell for detective arrows.
constexpr SdrLayerID SC_LAYER_INTERN(2)
::boost::intrusive_ptr< formula::FormulaToken > ScTokenRef
Definition: types.hxx:30
virtual SdrPage * getSdrPageFromSdrObjList() const
SfxItemSet & GetArrowSet()
Definition: detfunc.cxx:108
void * p
These need to be in global namespace just like their respective types are.
bool DrawAlienEntry(const ScRange &rRef, ScDetectiveData &rData)
Definition: detfunc.cxx:621
SdrOnOffItem makeSdrShadowItem(bool bShadow)
void SetInvalid()
Definition: address.hxx:287
formula::FormulaToken * GetNextRefToken()
Definition: formulaiter.cxx:67
SdrMetricItem makeSdrTextLeftDistItem(long mnHeight)
void DeleteArrowsAt(SCCOL nCol, SCROW nRow, bool bDestPnt)
Definition: detfunc.cxx:667
bool SC_DLLPUBLIC intersects(const ScDocument *pDoc, const ::std::vector< ScTokenRef > &rTokens, const ScTokenRef &pToken, const ScAddress &rPos)
SdrMetricItem makeSdrTextRightDistItem(long mnHeight)
static bool IsNoteCaption(SdrObject *pObj)
Returns true, if the passed object is the caption of a cell note.
Definition: drwlayer.cxx:2309
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
void InsertToOtherTab(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, bool bRed, ScDetectiveData &rData)
Definition: detfunc.cxx:531
SdrObjList * getParentSdrObjListFromSdrObject() const
bool IsIgnoreBlank() const
Definition: conditio.hxx:372
void SetRunning(bool bVal)
#define SC_LINEEND_NAME
Definition: detfunc.cxx:82
virtual void NbcSetLogicRect(const tools::Rectangle &rRect) override
SC_DLLPUBLIC sal_uInt16 GetColWidth(SCCOL nCol, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4120
ScAddress maEnd
Definition: userdat.hxx:39
#define SC_DET_TOLERANCE
Definition: detfunc.cxx:721
SdrMetricItem makeSdrTextLowerDistItem(long mnHeight)
constexpr TypedWhichId< XLineColorItem > XATTR_LINECOLOR(XATTR_LINE_FIRST+3)
virtual Point GetPoint(sal_uInt32 i) const
B2DPolygon createPolygonFromEllipse(const B2DPoint &rCenter, double fRadiusX, double fRadiusY, sal_uInt32 nStartQuadrant=0)
void InsertArrow(SCCOL nCol, SCROW nRow, SCCOL nRefStartCol, SCROW nRefStartRow, SCCOL nRefEndCol, SCROW nRefEndRow, bool bFromOtherTab, bool bRed, ScDetectiveData &rData)
called from DrawEntry/DrawAlienEntry and InsertObject
Definition: detfunc.cxx:450
tools::Long Right() const
SfxItemSet & GetCircleSet()
Definition: detfunc.cxx:111
sal_Int16 SCTAB
Definition: types.hxx:23
ScDocument & rDoc
Definition: detfunc.hxx:56
ScDetectiveObjType GetDetectiveObjectType(SdrObject *pObject, SCTAB nObjTab, ScAddress &rPosition, ScRange &rSource, bool &rRedLine)
Definition: detfunc.cxx:1625
SdrMetricItem makeSdrShadowXDistItem(long nDist)
bool IsRecording() const
Definition: drwlayer.hxx:134