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