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