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  pDoc->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( pDoc, 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( pDoc->ValidColRow( nCol, nRow ), "ScDetectiveFunc::GetDrawPos - invalid cell address" );
314  nCol = pDoc->SanitizeCol( nCol );
315  nRow = pDoc->SanitizeRow( nRow );
316 
317  Point aPos;
318 
319  switch( eMode )
320  {
322  break;
324  ++nCol;
325  ++nRow;
326  break;
328  aPos.AdjustX(pDoc->GetColWidth( nCol, nTab ) / 4 );
329  aPos.AdjustY(pDoc->GetRowHeight( nRow, nTab ) / 2 );
330  break;
331  }
332 
333  for ( SCCOL i = 0; i < nCol; ++i )
334  aPos.AdjustX(pDoc->GetColWidth( i, nTab ) );
335  aPos.AdjustY(pDoc->GetRowHeight( 0, nRow - 1, nTab ) );
336 
337  aPos.setX( static_cast< long >( aPos.X() * HMM_PER_TWIPS ) );
338  aPos.setY( static_cast< long >( aPos.Y() * HMM_PER_TWIPS ) );
339 
340  if ( pDoc->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 = pDoc->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 = pDoc->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 = pDoc->IsNegativePage( nTab );
486  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 = pDoc->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 = pDoc->IsNegativePage( nTab );
558  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 = pDoc->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 = pDoc->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 = pDoc->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  dynamic_cast< const SdrRectObj* >(pObject) != nullptr )
763  {
764  aObjRect = static_cast<SdrRectObj*>(pObject)->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( pDoc, 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(*pDoc, 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(pDoc, 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( pDoc, 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(*pDoc, 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(pDoc, 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(*pDoc, 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(pDoc, 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(pDoc, ScRange(0,0,0,pDoc->MaxCol(),pDoc->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(pDoc, 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( pDoc, ScRange(0, 0, nTab, pDoc->MaxCol(), pDoc->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(pDoc, 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 = pDoc->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 = pDoc->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 = pDoc->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 = pDoc->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 = pDoc->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  ScDrawLayer* pModel = pDoc->GetDrawLayer();
1244  if (!pModel)
1245  return false;
1246 
1247  SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
1248  OSL_ENSURE(pPage,"Page ?");
1249 
1250  pPage->RecalcObjOrdNums();
1251 
1252  size_t nDelCount = 0;
1253  const size_t nObjCount = pPage->GetObjCount();
1254  if (nObjCount)
1255  {
1256  std::unique_ptr<SdrObject*[]> ppObj(new SdrObject*[nObjCount]);
1257 
1258  SdrObjListIter aIter( pPage, SdrIterMode::Flat );
1259  SdrObject* pObject = aIter.Next();
1260  while (pObject)
1261  {
1262  if ( pObject->GetLayer() == SC_LAYER_INTERN )
1263  {
1264  bool bDoThis = true;
1265  bool bCircle = ( dynamic_cast<const SdrCircObj*>( pObject) != nullptr );
1266  bool bCaption = ScDrawLayer::IsNoteCaption( pObject );
1267  if ( eWhat == ScDetectiveDelete::Detective ) // detective, from menu
1268  bDoThis = !bCaption; // also circles
1269  else if ( eWhat == ScDetectiveDelete::Circles ) // circles, if new created
1270  bDoThis = bCircle;
1271  else if ( eWhat == ScDetectiveDelete::Arrows ) // DetectiveRefresh
1272  bDoThis = !bCaption && !bCircle; // don't include circles
1273  else
1274  {
1275  OSL_FAIL("what?");
1276  }
1277  if ( bDoThis )
1278  ppObj[nDelCount++] = pObject;
1279  }
1280 
1281  pObject = aIter.Next();
1282  }
1283 
1284  for (size_t i=1; i<=nDelCount; ++i)
1285  pModel->AddCalcUndo( std::make_unique<SdrUndoRemoveObj>( *ppObj[nDelCount-i] ) );
1286 
1287  for (size_t i=1; i<=nDelCount; ++i)
1288  pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1289 
1290  ppObj.reset();
1291 
1292  Modified();
1293  }
1294 
1295  return ( nDelCount != 0 );
1296 }
1297 
1298 bool ScDetectiveFunc::MarkInvalid(bool& rOverflow)
1299 {
1300  rOverflow = false;
1301  ScDrawLayer* pModel = pDoc->GetDrawLayer();
1302  if (!pModel)
1303  return false;
1304 
1305  bool bDeleted = DeleteAll( ScDetectiveDelete::Circles ); // just circles
1306 
1307  ScDetectiveData aData( pModel );
1308  long nInsCount = 0;
1309 
1310  // search for valid places
1311  ScDocAttrIterator aAttrIter( pDoc, nTab, 0,0,pDoc->MaxCol(),pDoc->MaxRow() );
1312  SCCOL nCol;
1313  SCROW nRow1;
1314  SCROW nRow2;
1315  const ScPatternAttr* pPattern = aAttrIter.GetNext( nCol, nRow1, nRow2 );
1316  while ( pPattern && nInsCount < SC_DET_MAXCIRCLE )
1317  {
1318  sal_uLong nIndex = pPattern->GetItem(ATTR_VALIDDATA).GetValue();
1319  if (nIndex)
1320  {
1321  const ScValidationData* pData = pDoc->GetValidationEntry( nIndex );
1322  if ( pData )
1323  {
1324  // pass cells in this area
1325 
1326  bool bMarkEmpty = !pData->IsIgnoreBlank();
1327  SCROW nNextRow = nRow1;
1328  SCROW nRow;
1329  ScCellIterator aCellIter( pDoc, ScRange(nCol, nRow1, nTab, nCol, nRow2, nTab) );
1330  for (bool bHas = aCellIter.first(); bHas && nInsCount < SC_DET_MAXCIRCLE; bHas = aCellIter.next())
1331  {
1332  SCROW nCellRow = aCellIter.GetPos().Row();
1333  if ( bMarkEmpty )
1334  for ( nRow = nNextRow; nRow < nCellRow && nInsCount < SC_DET_MAXCIRCLE; nRow++ )
1335  {
1336  DrawCircle( nCol, nRow, aData );
1337  ++nInsCount;
1338  }
1339  ScRefCellValue aCell = aCellIter.getRefCellValue();
1340  if (!pData->IsDataValid(aCell, aCellIter.GetPos()))
1341  {
1342  DrawCircle( nCol, nCellRow, aData );
1343  ++nInsCount;
1344  }
1345  nNextRow = nCellRow + 1;
1346  }
1347  if ( bMarkEmpty )
1348  for ( nRow = nNextRow; nRow <= nRow2 && nInsCount < SC_DET_MAXCIRCLE; nRow++ )
1349  {
1350  DrawCircle( nCol, nRow, aData );
1351  ++nInsCount;
1352  }
1353  }
1354  }
1355 
1356  pPattern = aAttrIter.GetNext( nCol, nRow1, nRow2 );
1357  }
1358 
1359  if ( nInsCount >= SC_DET_MAXCIRCLE )
1360  rOverflow = true;
1361 
1362  return ( bDeleted || nInsCount != 0 );
1363 }
1364 
1365 void ScDetectiveFunc::GetAllPreds(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1366  vector<ScTokenRef>& rRefTokens)
1367 {
1368  ScCellIterator aIter(pDoc, ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab));
1369  for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
1370  {
1371  if (aIter.getType() != CELLTYPE_FORMULA)
1372  continue;
1373 
1374  ScFormulaCell* pFCell = aIter.getFormulaCell();
1375  ScDetectiveRefIter aRefIter(pDoc, pFCell);
1376  for (formula::FormulaToken* p = aRefIter.GetNextRefToken(); p; p = aRefIter.GetNextRefToken())
1377  {
1378  ScTokenRef pRef(p->Clone());
1379  ScRefTokenHelper::join(pDoc, rRefTokens, pRef, aIter.GetPos());
1380  }
1381  }
1382 }
1383 
1384 void ScDetectiveFunc::GetAllSuccs(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
1385  vector<ScTokenRef>& rRefTokens)
1386 {
1387  vector<ScTokenRef> aSrcRange;
1388  aSrcRange.push_back(
1389  ScRefTokenHelper::createRefToken(pDoc, ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab)));
1390 
1391  ScCellIterator aIter(pDoc, ScRange(0, 0, nTab, pDoc->MaxCol(), pDoc->MaxRow(), nTab));
1392  for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
1393  {
1394  if (aIter.getType() != CELLTYPE_FORMULA)
1395  continue;
1396 
1397  ScFormulaCell* pFCell = aIter.getFormulaCell();
1398  ScDetectiveRefIter aRefIter(pDoc, pFCell);
1399  for (formula::FormulaToken* p = aRefIter.GetNextRefToken(); p; p = aRefIter.GetNextRefToken())
1400  {
1401  const ScAddress& aPos = aIter.GetPos();
1402  ScTokenRef pRef(p->Clone());
1403  if (ScRefTokenHelper::intersects(pDoc, aSrcRange, pRef, aPos))
1404  {
1405  // This address is absolute.
1406  pRef = ScRefTokenHelper::createRefToken(pDoc, aPos);
1407  ScRefTokenHelper::join(pDoc, rRefTokens, pRef, ScAddress());
1408  }
1409  }
1410  }
1411 }
1412 
1414 {
1415  // for all caption objects, update attributes and SpecialTextBoxShadow flag
1416  // (on all tables - nTab is ignored!)
1417 
1418  // no undo actions, this is refreshed after undo
1419 
1420  ScDrawLayer* pModel = rDoc.GetDrawLayer();
1421  if (!pModel)
1422  return;
1423 
1424  for( SCTAB nObjTab = 0, nTabCount = rDoc.GetTableCount(); nObjTab < nTabCount; ++nObjTab )
1425  {
1426  SdrPage* pPage = pModel->GetPage( static_cast< sal_uInt16 >( nObjTab ) );
1427  OSL_ENSURE( pPage, "Page ?" );
1428  if( pPage )
1429  {
1430  SdrObjListIter aIter( pPage, SdrIterMode::Flat );
1431  for( SdrObject* pObject = aIter.Next(); pObject; pObject = aIter.Next() )
1432  {
1434  {
1435  ScPostIt* pNote = rDoc.GetNote( pData->maStart );
1436  // caption should exist, we iterate over drawing objects...
1437  OSL_ENSURE( pNote && (pNote->GetCaption() == pObject), "ScDetectiveFunc::UpdateAllComments - invalid cell note" );
1438  if( pNote )
1439  {
1440  ScCommentData aData( rDoc, pModel );
1441  SfxItemSet aAttrColorSet = pObject->GetMergedItemSet();
1442  aAttrColorSet.Put( XFillColorItem( OUString(), GetCommentColor() ) );
1443  aData.UpdateCaptionSet( aAttrColorSet );
1444  pObject->SetMergedItemSetAndBroadcast( aData.GetCaptionSet() );
1445  if( SdrCaptionObj* pCaption = dynamic_cast< SdrCaptionObj* >( pObject ) )
1446  {
1447  pCaption->SetSpecialTextBoxShadow();
1448  pCaption->SetFixedTail();
1449  }
1450  }
1451  }
1452  }
1453  }
1454  }
1455 }
1456 
1458 {
1459  // no undo actions necessary
1460 
1461  ScDrawLayer* pModel = pDoc->GetDrawLayer();
1462  if (!pModel)
1463  return;
1464 
1465  for( SCTAB nObjTab = 0, nTabCount = pDoc->GetTableCount(); nObjTab < nTabCount; ++nObjTab )
1466  {
1467  SdrPage* pPage = pModel->GetPage( static_cast< sal_uInt16 >( nObjTab ) );
1468  OSL_ENSURE( pPage, "Page ?" );
1469  if( pPage )
1470  {
1471  SdrObjListIter aIter( pPage, SdrIterMode::Flat );
1472  for( SdrObject* pObject = aIter.Next(); pObject; pObject = aIter.Next() )
1473  {
1474  if ( pObject->GetLayer() == SC_LAYER_INTERN )
1475  {
1476  bool bArrow = false;
1477  bool bError = false;
1478 
1479  ScAddress aPos;
1480  ScRange aSource;
1481  bool bDummy;
1482  ScDetectiveObjType eType = GetDetectiveObjectType( pObject, nObjTab, aPos, aSource, bDummy );
1483  if ( eType == SC_DETOBJ_ARROW || eType == SC_DETOBJ_TOOTHERTAB )
1484  {
1485  // source is valid, determine error flag from source range
1486 
1487  ScAddress aErrPos;
1488  if ( HasError( aSource, aErrPos ) )
1489  bError = true;
1490  else
1491  bArrow = true;
1492  }
1493  else if ( eType == SC_DETOBJ_FROMOTHERTAB )
1494  {
1495  // source range is no longer known, take error flag from formula itself
1496  // (this means, if the formula has an error, all references to other tables
1497  // are marked red)
1498 
1499  ScAddress aErrPos;
1500  if ( HasError( ScRange( aPos), aErrPos ) )
1501  bError = true;
1502  else
1503  bArrow = true;
1504  }
1505  else if ( eType == SC_DETOBJ_CIRCLE )
1506  {
1507  // circles (error marks) are always red
1508 
1509  bError = true;
1510  }
1511  else if ( eType == SC_DETOBJ_NONE )
1512  {
1513  // frame for area reference has no ObjType, always gets arrow color
1514 
1515  if ( dynamic_cast<const SdrRectObj*>( pObject) != nullptr && dynamic_cast<const SdrCaptionObj*>( pObject) == nullptr )
1516  {
1517  bArrow = true;
1518  }
1519  }
1520 
1521  if ( bArrow || bError )
1522  {
1523  Color nColor = ( bError ? GetErrorColor() : GetArrowColor() );
1524  pObject->SetMergedItem( XLineColorItem( OUString(), nColor ) );
1525 
1526  // repaint only
1527  pObject->ActionChanged();
1528  }
1529  }
1530  }
1531  }
1532  }
1533 }
1534 
1536 {
1537  // find the rectangle for an arrow (always the object directly before the arrow)
1538  // rRange must be initialized to the source cell of the arrow (start of area)
1539 
1540  ScDrawLayer* pModel = pDoc->GetDrawLayer();
1541  if (!pModel) return;
1542 
1543  SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab));
1544  OSL_ENSURE(pPage,"Page ?");
1545  if (!pPage) return;
1546 
1547  // test if the object is a direct page member
1548  if( !(pObject && pObject->getSdrPageFromSdrObject() && (pObject->getSdrPageFromSdrObject() == pObject->getParentSdrObjListFromSdrObject()->getSdrPageFromSdrObjList())) )
1549  return;
1550 
1551  // Is there a previous object?
1552  const size_t nOrdNum = pObject->GetOrdNum();
1553 
1554  if(nOrdNum <= 0)
1555  return;
1556 
1557  SdrObject* pPrevObj = pPage->GetObj(nOrdNum - 1);
1558 
1559  if ( pPrevObj && pPrevObj->GetLayer() == SC_LAYER_INTERN && dynamic_cast<const SdrRectObj*>( pPrevObj) != nullptr )
1560  {
1561  ScDrawObjData* pPrevData = ScDrawLayer::GetObjDataTab( pPrevObj, rRange.aStart.Tab() );
1562  if ( pPrevData && pPrevData->maStart.IsValid() && pPrevData->maEnd.IsValid() && (pPrevData->maStart == rRange.aStart) )
1563  {
1564  rRange.aEnd = pPrevData->maEnd;
1565  return;
1566  }
1567  }
1568 }
1569 
1571  ScAddress& rPosition, ScRange& rSource, bool& rRedLine )
1572 {
1573  rRedLine = false;
1575 
1576  if ( pObject && pObject->GetLayer() == SC_LAYER_INTERN )
1577  {
1578  if ( ScDrawObjData* pData = ScDrawLayer::GetObjDataTab( pObject, nObjTab ) )
1579  {
1580  bool bValidStart = pData->maStart.IsValid();
1581  bool bValidEnd = pData->maEnd.IsValid();
1582 
1583  if ( pObject->IsPolyObj() && pObject->GetPointCount() == 2 )
1584  {
1585  // line object -> arrow
1586 
1587  if ( bValidStart )
1588  eType = bValidEnd ? SC_DETOBJ_ARROW : SC_DETOBJ_TOOTHERTAB;
1589  else if ( bValidEnd )
1590  eType = SC_DETOBJ_FROMOTHERTAB;
1591 
1592  if ( bValidStart )
1593  rSource = pData->maStart;
1594  if ( bValidEnd )
1595  rPosition = pData->maEnd;
1596 
1597  if ( bValidStart && lcl_HasThickLine( *pObject ) )
1598  {
1599  // thick line -> look for frame before this object
1600 
1601  FindFrameForObject( pObject, rSource ); // modifies rSource
1602  }
1603 
1604  Color nObjColor = pObject->GetMergedItem(XATTR_LINECOLOR).GetColorValue();
1605  if ( nObjColor == GetErrorColor() && nObjColor != GetArrowColor() )
1606  rRedLine = true;
1607  }
1608  else if ( dynamic_cast<const SdrCircObj*>( pObject) != nullptr )
1609  {
1610  if ( bValidStart )
1611  {
1612  // cell position is returned in rPosition
1613 
1614  rPosition = pData->maStart;
1615  eType = SC_DETOBJ_CIRCLE;
1616  }
1617  }
1618  }
1619  }
1620 
1621  return eType;
1622 }
1623 
1625  const ScAddress& rPosition, const ScRange& rSource,
1626  bool bRedLine )
1627 {
1628  ScDrawLayer* pModel = pDoc->GetDrawLayer();
1629  if (!pModel) return;
1630  ScDetectiveData aData( pModel );
1631 
1632  switch (eType)
1633  {
1634  case SC_DETOBJ_ARROW:
1636  InsertArrow( rPosition.Col(), rPosition.Row(),
1637  rSource.aStart.Col(), rSource.aStart.Row(),
1638  rSource.aEnd.Col(), rSource.aEnd.Row(),
1639  (eType == SC_DETOBJ_FROMOTHERTAB), bRedLine, aData );
1640  break;
1641  case SC_DETOBJ_TOOTHERTAB:
1642  InsertToOtherTab( rSource.aStart.Col(), rSource.aStart.Row(),
1643  rSource.aEnd.Col(), rSource.aEnd.Row(),
1644  bRedLine, aData );
1645  break;
1646  case SC_DETOBJ_CIRCLE:
1647  DrawCircle( rPosition.Col(), rPosition.Row(), aData );
1648  break;
1649  default:
1650  {
1651  // added to avoid warnings
1652  }
1653  }
1654 }
1655 
1657 {
1658  if (!bColorsInitialized)
1659  InitializeColors();
1660  return nArrowColor;
1661 }
1662 
1664 {
1665  if (!bColorsInitialized)
1666  InitializeColors();
1667  return nErrorColor;
1668 }
1669 
1671 {
1672  if (!bColorsInitialized)
1673  InitializeColors();
1674  return nCommentColor;
1675 }
1676 
1678 {
1679  // may be called several times to update colors from configuration
1680 
1681  const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
1685 
1686  bColorsInitialized = true;
1687 }
1688 
1690 {
1691  return bColorsInitialized;
1692 }
1693 
1695 {
1696  rDisplay += "\n--------\n";
1697 }
1698 
1699 /* 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:50
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:479
void FindFrameForObject(const SdrObject *pObject, ScRange &rRange)
Definition: detfunc.cxx:1535
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:214
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
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
long AdjustLeft(long nHorzMoveDelta)
bool GetDirty() const
sal_uIntPtr sal_uLong
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:1663
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:1624
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:1457
void GetAllPreds(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,::std::vector< ScTokenRef > &rRefTokens)
Definition: detfunc.cxx:1365
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:4164
SdrOnOffItem makeSdrTextAutoGrowHeightItem(bool bAuto)
long AdjustBottom(long nVertMoveDelta)
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:6511
Point GetDrawPos(SCCOL nCol, SCROW nRow, DrawPosMode eMode) const
Definition: detfunc.cxx:311
long Right() const
static bool lcl_HasThickLine(const SdrObject &rObj)
Definition: detfunc.cxx:138
static Color nErrorColor
Definition: detfunc.hxx:51
SdrPage * getSdrPageFromSdrObject() const
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:873
static Color GetArrowColor()
Definition: detfunc.cxx:1656
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.
bool DeletePred(SCCOL nCol, SCROW nRow)
Definition: detfunc.cxx:1228
const ScRefCellValue & getRefCellValue() const
Definition: dociter.hxx:242
void Modified()
Definition: detfunc.cxx:280
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:91
SCTAB Tab() const
Definition: address.hxx:271
long Top() const
SdrOnOffItem makeSdrTextAutoGrowWidthItem(bool bAuto)
ScDocument * pDoc
Definition: detfunc.hxx:55
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
SdrMetricItem makeSdrTextUpperDistItem(long mnHeight)
const SfxPoolItem & GetItem(sal_uInt16 nWhichP) const
Definition: patattr.hxx:70
static bool IsColorsInitialized()
Definition: detfunc.cxx:1689
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:53
#define SC_MOD()
Definition: scmod.hxx:253
SfxItemSet aToTabSet
Definition: detfunc.cxx:99
bool MarkInvalid(bool &rOverflow)
Definition: detfunc.cxx:1298
static Color nCommentColor
Definition: detfunc.hxx:52
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:1413
long Bottom() const
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
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)
ScTokenRef createRefToken(const ScDocument *pDoc, const ScAddress &rAddr)
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 DeleteAll(ScDetectiveDelete eWhat)
Definition: detfunc.cxx:1241
virtual SdrLayerID GetLayer() const
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:1670
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:1384
sal_uInt32 count() const
void SetStreamValid(SCTAB nTab, bool bSet, bool bIgnoreLock=false)
Definition: document.cxx:925
long AdjustRight(long nHorzMoveDelta)
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:1694
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:1677
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
long AdjustTop(long nVertMoveDelta)
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)
long Left() const
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
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:4123
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
SfxItemSet & GetCircleSet()
Definition: detfunc.cxx:111
sal_Int16 SCTAB
Definition: types.hxx:23
ScDetectiveObjType GetDetectiveObjectType(SdrObject *pObject, SCTAB nObjTab, ScAddress &rPosition, ScRange &rSource, bool &rRedLine)
Definition: detfunc.cxx:1570
SdrMetricItem makeSdrShadowXDistItem(long nDist)
bool IsRecording() const
Definition: drwlayer.hxx:134