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