diff options
Diffstat (limited to 'sc/source/core/tool/detfunc.cxx')
-rw-r--r-- | sc/source/core/tool/detfunc.cxx | 1742 |
1 files changed, 0 insertions, 1742 deletions
diff --git a/sc/source/core/tool/detfunc.cxx b/sc/source/core/tool/detfunc.cxx deleted file mode 100644 index ecd36b7f5..000000000 --- a/sc/source/core/tool/detfunc.cxx +++ /dev/null @@ -1,1742 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER(update_precomp.py): autogen include statement, do not remove -#include "precompiled_sc.hxx" - -// INCLUDE --------------------------------------------------------------- - -#include "scitems.hxx" -#include <svtools/colorcfg.hxx> -#include <editeng/eeitem.hxx> -#include <editeng/outlobj.hxx> -#include <svx/sdshitm.hxx> -#include <svx/sdsxyitm.hxx> -#include <svx/sdtditm.hxx> -#include <svx/svditer.hxx> -#include <svx/svdocapt.hxx> -#include <svx/svdocirc.hxx> -#include <svx/svdopath.hxx> -#include <svx/svdorect.hxx> -#include <svx/svdpage.hxx> -#include <svx/svdundo.hxx> -#include <svx/xfillit0.hxx> -#include <svx/xflclit.hxx> -#include <svx/xlnclit.hxx> -#include <svx/xlnedcit.hxx> -#include <svx/xlnedit.hxx> -#include <svx/xlnedwit.hxx> -#include <svx/xlnstcit.hxx> -#include <svx/xlnstit.hxx> -#include <svx/xlnstwit.hxx> -#include <svx/xlnwtit.hxx> -#include <svx/xtable.hxx> -#include <editeng/outliner.hxx> -#include <editeng/editobj.hxx> -#include <svx/sxcecitm.hxx> -#include <svl/whiter.hxx> -#include <editeng/writingmodeitem.hxx> - -#include <basegfx/point/b2dpoint.hxx> -#include <basegfx/polygon/b2dpolygontools.hxx> -#include <basegfx/polygon/b2dpolygon.hxx> - -#include "detfunc.hxx" -#include "document.hxx" -#include "dociter.hxx" -#include "drwlayer.hxx" -#include "userdat.hxx" -#include "validat.hxx" -#include "cell.hxx" -#include "docpool.hxx" -#include "patattr.hxx" -#include "attrib.hxx" -#include "scmod.hxx" -#include "postit.hxx" -#include "rangelst.hxx" -#include "reftokenhelper.hxx" - -#include <vector> - -using ::std::vector; - -//------------------------------------------------------------------------ - -// line ends are now created with an empty name. -// The checkForUniqueItem method then finds a unique name for the item's value. -#define SC_LINEEND_NAME EMPTY_STRING - -//------------------------------------------------------------------------ - -enum DetInsertResult { // Return-Werte beim Einfuegen in einen Level - DET_INS_CONTINUE, - DET_INS_INSERTED, - DET_INS_EMPTY, - DET_INS_CIRCULAR }; - - -//------------------------------------------------------------------------ - -class ScDetectiveData -{ -private: - SfxItemSet aBoxSet; - SfxItemSet aArrowSet; - SfxItemSet aToTabSet; - SfxItemSet aFromTabSet; - SfxItemSet aCircleSet; //! einzeln ? - sal_uInt16 nMaxLevel; - -public: - ScDetectiveData( SdrModel* pModel ); - - SfxItemSet& GetBoxSet() { return aBoxSet; } - SfxItemSet& GetArrowSet() { return aArrowSet; } - SfxItemSet& GetToTabSet() { return aToTabSet; } - SfxItemSet& GetFromTabSet() { return aFromTabSet; } - SfxItemSet& GetCircleSet() { return aCircleSet; } - - void SetMaxLevel( sal_uInt16 nVal ) { nMaxLevel = nVal; } - sal_uInt16 GetMaxLevel() const { return nMaxLevel; } -}; - -class ScCommentData -{ -public: - ScCommentData( ScDocument& rDoc, SdrModel* pModel ); - - SfxItemSet& GetCaptionSet() { return aCaptionSet; } - void UpdateCaptionSet( const SfxItemSet& rItemSet ); - -private: - SfxItemSet aCaptionSet; -}; - -//------------------------------------------------------------------------ - -ColorData ScDetectiveFunc::nArrowColor = 0; -ColorData ScDetectiveFunc::nErrorColor = 0; -ColorData ScDetectiveFunc::nCommentColor = 0; -sal_Bool ScDetectiveFunc::bColorsInitialized = false; - -//------------------------------------------------------------------------ - -sal_Bool lcl_HasThickLine( SdrObject& rObj ) -{ - // thin lines get width 0 -> everything greater 0 is a thick line - - return ( ((const XLineWidthItem&)rObj.GetMergedItem(XATTR_LINEWIDTH)).GetValue() > 0 ); -} - -//------------------------------------------------------------------------ - -ScDetectiveData::ScDetectiveData( SdrModel* pModel ) : - aBoxSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ), - aArrowSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ), - aToTabSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ), - aFromTabSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ), - aCircleSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END ) -{ - nMaxLevel = 0; - - aBoxSet.Put( XLineColorItem( EMPTY_STRING, Color( ScDetectiveFunc::GetArrowColor() ) ) ); - aBoxSet.Put( XFillStyleItem( XFILL_NONE ) ); - - // Standard-Linienenden (wie aus XLineEndList::Create) selber zusammenbasteln, - // um von den konfigurierten Linienenden unabhaengig zu sein - - basegfx::B2DPolygon aTriangle; - aTriangle.append(basegfx::B2DPoint(10.0, 0.0)); - aTriangle.append(basegfx::B2DPoint(0.0, 30.0)); - aTriangle.append(basegfx::B2DPoint(20.0, 30.0)); - aTriangle.setClosed(true); - - basegfx::B2DPolygon aSquare; - aSquare.append(basegfx::B2DPoint(0.0, 0.0)); - aSquare.append(basegfx::B2DPoint(10.0, 0.0)); - aSquare.append(basegfx::B2DPoint(10.0, 10.0)); - aSquare.append(basegfx::B2DPoint(0.0, 10.0)); - aSquare.setClosed(true); - - basegfx::B2DPolygon aCircle(basegfx::tools::createPolygonFromEllipse(basegfx::B2DPoint(0.0, 0.0), 100.0, 100.0)); - aCircle.setClosed(true); - - String aName = SC_LINEEND_NAME; - - aArrowSet.Put( XLineStartItem( aName, basegfx::B2DPolyPolygon(aCircle) ) ); - aArrowSet.Put( XLineStartWidthItem( 200 ) ); - aArrowSet.Put( XLineStartCenterItem( sal_True ) ); - aArrowSet.Put( XLineEndItem( aName, basegfx::B2DPolyPolygon(aTriangle) ) ); - aArrowSet.Put( XLineEndWidthItem( 200 ) ); - aArrowSet.Put( XLineEndCenterItem( false ) ); - - aToTabSet.Put( XLineStartItem( aName, basegfx::B2DPolyPolygon(aCircle) ) ); - aToTabSet.Put( XLineStartWidthItem( 200 ) ); - aToTabSet.Put( XLineStartCenterItem( sal_True ) ); - aToTabSet.Put( XLineEndItem( aName, basegfx::B2DPolyPolygon(aSquare) ) ); - aToTabSet.Put( XLineEndWidthItem( 300 ) ); - aToTabSet.Put( XLineEndCenterItem( false ) ); - - aFromTabSet.Put( XLineStartItem( aName, basegfx::B2DPolyPolygon(aSquare) ) ); - aFromTabSet.Put( XLineStartWidthItem( 300 ) ); - aFromTabSet.Put( XLineStartCenterItem( sal_True ) ); - aFromTabSet.Put( XLineEndItem( aName, basegfx::B2DPolyPolygon(aTriangle) ) ); - aFromTabSet.Put( XLineEndWidthItem( 200 ) ); - aFromTabSet.Put( XLineEndCenterItem( false ) ); - - aCircleSet.Put( XLineColorItem( String(), Color( ScDetectiveFunc::GetErrorColor() ) ) ); - aCircleSet.Put( XFillStyleItem( XFILL_NONE ) ); - sal_uInt16 nWidth = 55; // 54 = 1 Pixel - aCircleSet.Put( XLineWidthItem( nWidth ) ); -} - -ScCommentData::ScCommentData( ScDocument& rDoc, SdrModel* pModel ) : - aCaptionSet( pModel->GetItemPool(), SDRATTR_START, SDRATTR_END, EE_ITEMS_START, EE_ITEMS_END, 0, 0 ) -{ - basegfx::B2DPolygon aTriangle; - aTriangle.append(basegfx::B2DPoint(10.0, 0.0)); - aTriangle.append(basegfx::B2DPoint(0.0, 30.0)); - aTriangle.append(basegfx::B2DPoint(20.0, 30.0)); - aTriangle.setClosed(true); - - String aName = SC_LINEEND_NAME; - - aCaptionSet.Put( XLineStartItem( aName, basegfx::B2DPolyPolygon(aTriangle) ) ); - aCaptionSet.Put( XLineStartWidthItem( 200 ) ); - aCaptionSet.Put( XLineStartCenterItem( false ) ); - aCaptionSet.Put( XFillStyleItem( XFILL_SOLID ) ); - Color aYellow( ScDetectiveFunc::GetCommentColor() ); - aCaptionSet.Put( XFillColorItem( String(), aYellow ) ); - - // shadow - // SdrShadowItem has sal_False, instead the shadow is set for the rectangle - // only with SetSpecialTextBoxShadow when the object is created - // (item must be set to adjust objects from older files) - aCaptionSet.Put( SdrShadowItem( false ) ); - aCaptionSet.Put( SdrShadowXDistItem( 100 ) ); - aCaptionSet.Put( SdrShadowYDistItem( 100 ) ); - - // text attributes - aCaptionSet.Put( SdrTextLeftDistItem( 100 ) ); - aCaptionSet.Put( SdrTextRightDistItem( 100 ) ); - aCaptionSet.Put( SdrTextUpperDistItem( 100 ) ); - aCaptionSet.Put( SdrTextLowerDistItem( 100 ) ); - - aCaptionSet.Put( SdrTextAutoGrowWidthItem( false ) ); - aCaptionSet.Put( SdrTextAutoGrowHeightItem( sal_True ) ); - - // do use the default cell style, so the user has a chance to - // modify the font for the annotations - ((const ScPatternAttr&)rDoc.GetPool()->GetDefaultItem(ATTR_PATTERN)). - FillEditItemSet( &aCaptionSet ); - - // support the best position for the tail connector now that - // that notes can be resized and repositioned. - aCaptionSet.Put( SdrCaptionEscDirItem( SDRCAPT_ESCBESTFIT) ); -} - -void ScCommentData::UpdateCaptionSet( const SfxItemSet& rItemSet ) -{ - SfxWhichIter aWhichIter( rItemSet ); - const SfxPoolItem* pPoolItem = 0; - - for( sal_uInt16 nWhich = aWhichIter.FirstWhich(); nWhich > 0; nWhich = aWhichIter.NextWhich() ) - { - if(rItemSet.GetItemState(nWhich, false, &pPoolItem) == SFX_ITEM_SET) - { - switch(nWhich) - { - case SDRATTR_SHADOW: - // use existing Caption default - appears that setting this - // to true screws up the tail appearance. See also comment - // for default setting above. - break; - case SDRATTR_SHADOWXDIST: - // use existing Caption default - svx sets a value of 35 - // but default 100 gives a better appearance. - break; - case SDRATTR_SHADOWYDIST: - // use existing Caption default - svx sets a value of 35 - // but default 100 gives a better appearance. - break; - - default: - aCaptionSet.Put(*pPoolItem); - } - } - } -} - -//------------------------------------------------------------------------ - -void ScDetectiveFunc::Modified() -{ - if (pDoc->IsStreamValid(nTab)) - pDoc->SetStreamValid(nTab, false); -} - -inline sal_Bool Intersect( SCCOL nStartCol1, SCROW nStartRow1, SCCOL nEndCol1, SCROW nEndRow1, - SCCOL nStartCol2, SCROW nStartRow2, SCCOL nEndCol2, SCROW nEndRow2 ) -{ - return nEndCol1 >= nStartCol2 && nEndCol2 >= nStartCol1 && - nEndRow1 >= nStartRow2 && nEndRow2 >= nStartRow1; -} - -sal_Bool ScDetectiveFunc::HasError( const ScRange& rRange, ScAddress& rErrPos ) -{ - rErrPos = rRange.aStart; - sal_uInt16 nError = 0; - - ScCellIterator aCellIter( pDoc, rRange); - ScBaseCell* pCell = aCellIter.GetFirst(); - while (pCell) - { - if (pCell->GetCellType() == CELLTYPE_FORMULA) - { - nError = ((ScFormulaCell*)pCell)->GetErrCode(); - if (nError) - rErrPos.Set( aCellIter.GetCol(), aCellIter.GetRow(), aCellIter.GetTab() ); - } - pCell = aCellIter.GetNext(); - } - - return (nError != 0); -} - -Point ScDetectiveFunc::GetDrawPos( SCCOL nCol, SCROW nRow, DrawPosMode eMode ) const -{ - OSL_ENSURE( ValidColRow( nCol, nRow ), "ScDetectiveFunc::GetDrawPos - invalid cell address" ); - SanitizeCol( nCol ); - SanitizeRow( nRow ); - - Point aPos; - - switch( eMode ) - { - case DRAWPOS_TOPLEFT: - break; - case DRAWPOS_BOTTOMRIGHT: - ++nCol; - ++nRow; - break; - case DRAWPOS_DETARROW: - aPos.X() += pDoc->GetColWidth( nCol, nTab ) / 4; - aPos.Y() += pDoc->GetRowHeight( nRow, nTab ) / 2; - break; - case DRAWPOS_CAPTIONLEFT: - aPos.X() += 6; - break; - case DRAWPOS_CAPTIONRIGHT: - { - // find right end of passed cell position - const ScMergeAttr* pMerge = static_cast< const ScMergeAttr* >( pDoc->GetAttr( nCol, nRow, nTab, ATTR_MERGE ) ); - if ( pMerge->GetColMerge() > 1 ) - nCol = nCol + pMerge->GetColMerge(); - else - ++nCol; - aPos.X() -= 6; - } - break; - } - - for ( SCCOL i = 0; i < nCol; ++i ) - aPos.X() += pDoc->GetColWidth( i, nTab ); - aPos.Y() += pDoc->GetRowHeight( 0, nRow - 1, nTab ); - - aPos.X() = static_cast< long >( aPos.X() * HMM_PER_TWIPS ); - aPos.Y() = static_cast< long >( aPos.Y() * HMM_PER_TWIPS ); - - if ( pDoc->IsNegativePage( nTab ) ) - aPos.X() *= -1; - - return aPos; -} - -Rectangle ScDetectiveFunc::GetDrawRect( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const -{ - Rectangle aRect( - GetDrawPos( ::std::min( nCol1, nCol2 ), ::std::min( nRow1, nRow2 ), DRAWPOS_TOPLEFT ), - GetDrawPos( ::std::max( nCol1, nCol2 ), ::std::max( nRow1, nRow2 ), DRAWPOS_BOTTOMRIGHT ) ); - aRect.Justify(); // reorder left/right in RTL sheets - return aRect; -} - -Rectangle ScDetectiveFunc::GetDrawRect( SCCOL nCol, SCROW nRow ) const -{ - return GetDrawRect( nCol, nRow, nCol, nRow ); -} - -sal_Bool lcl_IsOtherTab( const basegfx::B2DPolyPolygon& rPolyPolygon ) -{ - // test if rPolygon is the line end for "other table" (rectangle) - if(1L == rPolyPolygon.count()) - { - const basegfx::B2DPolygon aSubPoly(rPolyPolygon.getB2DPolygon(0L)); - - // #i73305# circle consists of 4 segments, too, distinguishable from square by - // the use of control points - if(4L == aSubPoly.count() && aSubPoly.isClosed() && !aSubPoly.areControlPointsUsed()) - { - return true; - } - } - - return false; -} - -sal_Bool ScDetectiveFunc::HasArrow( const ScAddress& rStart, - SCCOL nEndCol, SCROW nEndRow, SCTAB nEndTab ) -{ - sal_Bool bStartAlien = ( rStart.Tab() != nTab ); - sal_Bool bEndAlien = ( nEndTab != nTab ); - - if (bStartAlien && bEndAlien) - { - OSL_FAIL("bStartAlien && bEndAlien"); - return true; - } - - Rectangle aStartRect; - Rectangle aEndRect; - if (!bStartAlien) - aStartRect = GetDrawRect( rStart.Col(), rStart.Row() ); - if (!bEndAlien) - aEndRect = GetDrawRect( nEndCol, nEndRow ); - - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); - OSL_ENSURE(pPage,"Page ?"); - - sal_Bool bFound = false; - SdrObjListIter aIter( *pPage, IM_FLAT ); - SdrObject* pObject = aIter.Next(); - while (pObject && !bFound) - { - if ( pObject->GetLayer()==SC_LAYER_INTERN && - pObject->IsPolyObj() && pObject->GetPointCount()==2 ) - { - const SfxItemSet& rSet = pObject->GetMergedItemSet(); - - sal_Bool bObjStartAlien = - lcl_IsOtherTab( ((const XLineStartItem&)rSet.Get(XATTR_LINESTART)).GetLineStartValue() ); - sal_Bool bObjEndAlien = - lcl_IsOtherTab( ((const XLineEndItem&)rSet.Get(XATTR_LINEEND)).GetLineEndValue() ); - - sal_Bool bStartHit = bStartAlien ? bObjStartAlien : - ( !bObjStartAlien && aStartRect.IsInside(pObject->GetPoint(0)) ); - sal_Bool bEndHit = bEndAlien ? bObjEndAlien : - ( !bObjEndAlien && aEndRect.IsInside(pObject->GetPoint(1)) ); - - if ( bStartHit && bEndHit ) - bFound = sal_True; - } - pObject = aIter.Next(); - } - - return bFound; -} - -sal_Bool ScDetectiveFunc::IsNonAlienArrow( SdrObject* pObject ) -{ - if ( pObject->GetLayer()==SC_LAYER_INTERN && - pObject->IsPolyObj() && pObject->GetPointCount()==2 ) - { - const SfxItemSet& rSet = pObject->GetMergedItemSet(); - - sal_Bool bObjStartAlien = - lcl_IsOtherTab( ((const XLineStartItem&)rSet.Get(XATTR_LINESTART)).GetLineStartValue() ); - sal_Bool bObjEndAlien = - lcl_IsOtherTab( ((const XLineEndItem&)rSet.Get(XATTR_LINEEND)).GetLineEndValue() ); - - return !bObjStartAlien && !bObjEndAlien; - } - - return false; -} - -//------------------------------------------------------------------------ - -// InsertXXX: called from DrawEntry/DrawAlienEntry and InsertObject - -sal_Bool ScDetectiveFunc::InsertArrow( SCCOL nCol, SCROW nRow, - SCCOL nRefStartCol, SCROW nRefStartRow, - SCCOL nRefEndCol, SCROW nRefEndRow, - sal_Bool bFromOtherTab, sal_Bool bRed, - ScDetectiveData& rData ) -{ - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); - - sal_Bool bArea = ( nRefStartCol != nRefEndCol || nRefStartRow != nRefEndRow ); - if (bArea && !bFromOtherTab) - { - // insert the rectangle before the arrow - this is relied on in FindFrameForObject - - Rectangle aRect = GetDrawRect( nRefStartCol, nRefStartRow, nRefEndCol, nRefEndRow ); - SdrRectObj* pBox = new SdrRectObj( aRect ); - - pBox->SetMergedItemSetAndBroadcast(rData.GetBoxSet()); - - pBox->SetLayer( SC_LAYER_INTERN ); - pPage->InsertObject( pBox ); - pModel->AddCalcUndo( new SdrUndoInsertObj( *pBox ) ); - - ScDrawObjData* pData = ScDrawLayer::GetObjData( pBox, sal_True ); - pData->maStart.Set( nRefStartCol, nRefStartRow, nTab); - pData->maEnd.Set( nRefEndCol, nRefEndRow, nTab); - } - - Point aStartPos = GetDrawPos( nRefStartCol, nRefStartRow, DRAWPOS_DETARROW ); - Point aEndPos = GetDrawPos( nCol, nRow, DRAWPOS_DETARROW ); - - if (bFromOtherTab) - { - sal_Bool bNegativePage = pDoc->IsNegativePage( nTab ); - long nPageSign = bNegativePage ? -1 : 1; - - aStartPos = Point( aEndPos.X() - 1000 * nPageSign, aEndPos.Y() - 1000 ); - if (aStartPos.X() * nPageSign < 0) - aStartPos.X() += 2000 * nPageSign; - if (aStartPos.Y() < 0) - aStartPos.Y() += 2000; - } - - SfxItemSet& rAttrSet = bFromOtherTab ? rData.GetFromTabSet() : rData.GetArrowSet(); - - if (bArea && !bFromOtherTab) - rAttrSet.Put( XLineWidthItem( 50 ) ); // Bereich - else - rAttrSet.Put( XLineWidthItem( 0 ) ); // einzelne Referenz - - ColorData nColorData = ( bRed ? GetErrorColor() : GetArrowColor() ); - rAttrSet.Put( XLineColorItem( String(), Color( nColorData ) ) ); - - basegfx::B2DPolygon aTempPoly; - aTempPoly.append(basegfx::B2DPoint(aStartPos.X(), aStartPos.Y())); - aTempPoly.append(basegfx::B2DPoint(aEndPos.X(), aEndPos.Y())); - SdrPathObj* pArrow = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aTempPoly)); - pArrow->NbcSetLogicRect(Rectangle(aStartPos,aEndPos)); //! noetig ??? - pArrow->SetMergedItemSetAndBroadcast(rAttrSet); - - pArrow->SetLayer( SC_LAYER_INTERN ); - pPage->InsertObject( pArrow ); - pModel->AddCalcUndo( new SdrUndoInsertObj( *pArrow ) ); - - ScDrawObjData* pData = ScDrawLayer::GetObjData( pArrow, sal_True ); - if (bFromOtherTab) - pData->maStart.SetInvalid(); - else - pData->maStart.Set( nRefStartCol, nRefStartRow, nTab); - - pData->maEnd.Set( nCol, nRow, nTab); - - Modified(); - return sal_True; -} - -sal_Bool ScDetectiveFunc::InsertToOtherTab( SCCOL nStartCol, SCROW nStartRow, - SCCOL nEndCol, SCROW nEndRow, sal_Bool bRed, - ScDetectiveData& rData ) -{ - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); - - sal_Bool bArea = ( nStartCol != nEndCol || nStartRow != nEndRow ); - if (bArea) - { - Rectangle aRect = GetDrawRect( nStartCol, nStartRow, nEndCol, nEndRow ); - SdrRectObj* pBox = new SdrRectObj( aRect ); - - pBox->SetMergedItemSetAndBroadcast(rData.GetBoxSet()); - - pBox->SetLayer( SC_LAYER_INTERN ); - pPage->InsertObject( pBox ); - pModel->AddCalcUndo( new SdrUndoInsertObj( *pBox ) ); - - ScDrawObjData* pData = ScDrawLayer::GetObjData( pBox, sal_True ); - pData->maStart.Set( nStartCol, nStartRow, nTab); - pData->maEnd.Set( nEndCol, nEndRow, nTab); - } - - sal_Bool bNegativePage = pDoc->IsNegativePage( nTab ); - long nPageSign = bNegativePage ? -1 : 1; - - Point aStartPos = GetDrawPos( nStartCol, nStartRow, DRAWPOS_DETARROW ); - Point aEndPos = Point( aStartPos.X() + 1000 * nPageSign, aStartPos.Y() - 1000 ); - if (aEndPos.Y() < 0) - aEndPos.Y() += 2000; - - SfxItemSet& rAttrSet = rData.GetToTabSet(); - if (bArea) - rAttrSet.Put( XLineWidthItem( 50 ) ); // Bereich - else - rAttrSet.Put( XLineWidthItem( 0 ) ); // einzelne Referenz - - ColorData nColorData = ( bRed ? GetErrorColor() : GetArrowColor() ); - rAttrSet.Put( XLineColorItem( String(), Color( nColorData ) ) ); - - basegfx::B2DPolygon aTempPoly; - aTempPoly.append(basegfx::B2DPoint(aStartPos.X(), aStartPos.Y())); - aTempPoly.append(basegfx::B2DPoint(aEndPos.X(), aEndPos.Y())); - SdrPathObj* pArrow = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aTempPoly)); - pArrow->NbcSetLogicRect(Rectangle(aStartPos,aEndPos)); //! noetig ??? - - pArrow->SetMergedItemSetAndBroadcast(rAttrSet); - - pArrow->SetLayer( SC_LAYER_INTERN ); - pPage->InsertObject( pArrow ); - pModel->AddCalcUndo( new SdrUndoInsertObj( *pArrow ) ); - - ScDrawObjData* pData = ScDrawLayer::GetObjData( pArrow, sal_True ); - pData->maStart.Set( nStartCol, nStartRow, nTab); - pData->maEnd.SetInvalid(); - - Modified(); - return sal_True; -} - -//------------------------------------------------------------------------ - -// DrawEntry: Formel auf dieser Tabelle, -// Referenz auf dieser oder anderer -// DrawAlienEntry: Formel auf anderer Tabelle, -// Referenz auf dieser - -// return FALSE: da war schon ein Pfeil - -sal_Bool ScDetectiveFunc::DrawEntry( SCCOL nCol, SCROW nRow, - const ScRange& rRef, - ScDetectiveData& rData ) -{ - if ( HasArrow( rRef.aStart, nCol, nRow, nTab ) ) - return false; - - ScAddress aErrorPos; - sal_Bool bError = HasError( rRef, aErrorPos ); - sal_Bool bAlien = ( rRef.aEnd.Tab() < nTab || rRef.aStart.Tab() > nTab ); - - return InsertArrow( nCol, nRow, - rRef.aStart.Col(), rRef.aStart.Row(), - rRef.aEnd.Col(), rRef.aEnd.Row(), - bAlien, bError, rData ); -} - -sal_Bool ScDetectiveFunc::DrawAlienEntry( const ScRange& rRef, - ScDetectiveData& rData ) -{ - if ( HasArrow( rRef.aStart, 0, 0, nTab+1 ) ) - return false; - - ScAddress aErrorPos; - sal_Bool bError = HasError( rRef, aErrorPos ); - - return InsertToOtherTab( rRef.aStart.Col(), rRef.aStart.Row(), - rRef.aEnd.Col(), rRef.aEnd.Row(), - bError, rData ); -} - -void ScDetectiveFunc::DrawCircle( SCCOL nCol, SCROW nRow, ScDetectiveData& rData ) -{ - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); - - Rectangle aRect = GetDrawRect( nCol, nRow ); - aRect.Left() -= 250; - aRect.Right() += 250; - aRect.Top() -= 70; - aRect.Bottom() += 70; - - SdrCircObj* pCircle = new SdrCircObj( OBJ_CIRC, aRect ); - SfxItemSet& rAttrSet = rData.GetCircleSet(); - - pCircle->SetMergedItemSetAndBroadcast(rAttrSet); - - pCircle->SetLayer( SC_LAYER_INTERN ); - pPage->InsertObject( pCircle ); - pModel->AddCalcUndo( new SdrUndoInsertObj( *pCircle ) ); - - ScDrawObjData* pData = ScDrawLayer::GetObjData( pCircle, sal_True ); - pData->maStart.Set( nCol, nRow, nTab); - pData->maEnd.SetInvalid(); - - Modified(); -} - -void ScDetectiveFunc::DeleteArrowsAt( SCCOL nCol, SCROW nRow, sal_Bool bDestPnt ) -{ - Rectangle aRect = GetDrawRect( nCol, nRow ); - - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); - OSL_ENSURE(pPage,"Page ?"); - - pPage->RecalcObjOrdNums(); - - sal_uLong nObjCount = pPage->GetObjCount(); - if (nObjCount) - { - long nDelCount = 0; - SdrObject** ppObj = new SdrObject*[nObjCount]; - - SdrObjListIter aIter( *pPage, IM_FLAT ); - SdrObject* pObject = aIter.Next(); - while (pObject) - { - if ( pObject->GetLayer()==SC_LAYER_INTERN && - pObject->IsPolyObj() && pObject->GetPointCount()==2 ) - { - if (aRect.IsInside(pObject->GetPoint(bDestPnt))) // Start/Zielpunkt - ppObj[nDelCount++] = pObject; - } - - pObject = aIter.Next(); - } - - long i; - for (i=1; i<=nDelCount; i++) - pModel->AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) ); - - for (i=1; i<=nDelCount; i++) - pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() ); - - delete[] ppObj; - - Modified(); - } -} - - // Box um Referenz loeschen - -#define SC_DET_TOLERANCE 50 - -inline sal_Bool RectIsPoints( const Rectangle& rRect, const Point& rStart, const Point& rEnd ) -{ - return rRect.Left() >= rStart.X() - SC_DET_TOLERANCE - && rRect.Left() <= rStart.X() + SC_DET_TOLERANCE - && rRect.Right() >= rEnd.X() - SC_DET_TOLERANCE - && rRect.Right() <= rEnd.X() + SC_DET_TOLERANCE - && rRect.Top() >= rStart.Y() - SC_DET_TOLERANCE - && rRect.Top() <= rStart.Y() + SC_DET_TOLERANCE - && rRect.Bottom() >= rEnd.Y() - SC_DET_TOLERANCE - && rRect.Bottom() <= rEnd.Y() + SC_DET_TOLERANCE; -} - -#undef SC_DET_TOLERANCE - -void ScDetectiveFunc::DeleteBox( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) -{ - Rectangle aCornerRect = GetDrawRect( nCol1, nRow1, nCol2, nRow2 ); - Point aStartCorner = aCornerRect.TopLeft(); - Point aEndCorner = aCornerRect.BottomRight(); - Rectangle aObjRect; - - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); - OSL_ENSURE(pPage,"Page ?"); - - pPage->RecalcObjOrdNums(); - - sal_uLong nObjCount = pPage->GetObjCount(); - if (nObjCount) - { - long nDelCount = 0; - SdrObject** ppObj = new SdrObject*[nObjCount]; - - SdrObjListIter aIter( *pPage, IM_FLAT ); - SdrObject* pObject = aIter.Next(); - while (pObject) - { - if ( pObject->GetLayer() == SC_LAYER_INTERN && - pObject->Type() == TYPE(SdrRectObj) ) - { - aObjRect = ((SdrRectObj*)pObject)->GetLogicRect(); - aObjRect.Justify(); - if ( RectIsPoints( aObjRect, aStartCorner, aEndCorner ) ) - ppObj[nDelCount++] = pObject; - } - - pObject = aIter.Next(); - } - - long i; - for (i=1; i<=nDelCount; i++) - pModel->AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) ); - - for (i=1; i<=nDelCount; i++) - pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() ); - - delete[] ppObj; - - Modified(); - } -} - -//------------------------------------------------------------------------ - -sal_uInt16 ScDetectiveFunc::InsertPredLevelArea( const ScRange& rRef, - ScDetectiveData& rData, sal_uInt16 nLevel ) -{ - sal_uInt16 nResult = DET_INS_EMPTY; - - ScCellIterator aCellIter( pDoc, rRef); - ScBaseCell* pCell = aCellIter.GetFirst(); - while (pCell) - { - if (pCell->GetCellType() == CELLTYPE_FORMULA) - switch( InsertPredLevel( aCellIter.GetCol(), aCellIter.GetRow(), rData, nLevel ) ) - { - case DET_INS_INSERTED: - nResult = DET_INS_INSERTED; - break; - case DET_INS_CONTINUE: - if (nResult != DET_INS_INSERTED) - nResult = DET_INS_CONTINUE; - break; - case DET_INS_CIRCULAR: - if (nResult == DET_INS_EMPTY) - nResult = DET_INS_CIRCULAR; - break; - } - - pCell = aCellIter.GetNext(); - } - - return nResult; -} - -sal_uInt16 ScDetectiveFunc::InsertPredLevel( SCCOL nCol, SCROW nRow, ScDetectiveData& rData, - sal_uInt16 nLevel ) -{ - ScBaseCell* pCell; - pDoc->GetCell( nCol, nRow, nTab, pCell ); - if (!pCell) - return DET_INS_EMPTY; - if (pCell->GetCellType() != CELLTYPE_FORMULA) - return DET_INS_EMPTY; - - ScFormulaCell* pFCell = (ScFormulaCell*)pCell; - if (pFCell->IsRunning()) - return DET_INS_CIRCULAR; - - if (pFCell->GetDirty()) - pFCell->Interpret(); // nach SetRunning geht's nicht mehr! - pFCell->SetRunning(sal_True); - - sal_uInt16 nResult = DET_INS_EMPTY; - - ScDetectiveRefIter aIter( (ScFormulaCell*) pCell ); - ScRange aRef; - while ( aIter.GetNextRef( aRef ) ) - { - if (DrawEntry( nCol, nRow, aRef, rData )) - { - nResult = DET_INS_INSERTED; // neuer Pfeil eingetragen - } - else - { - // weiterverfolgen - - if ( nLevel < rData.GetMaxLevel() ) - { - sal_uInt16 nSubResult; - sal_Bool bArea = (aRef.aStart != aRef.aEnd); - if (bArea) - nSubResult = InsertPredLevelArea( aRef, rData, nLevel+1 ); - else - nSubResult = InsertPredLevel( aRef.aStart.Col(), aRef.aStart.Row(), - rData, nLevel+1 ); - - switch (nSubResult) - { - case DET_INS_INSERTED: - nResult = DET_INS_INSERTED; - break; - case DET_INS_CONTINUE: - if (nResult != DET_INS_INSERTED) - nResult = DET_INS_CONTINUE; - break; - case DET_INS_CIRCULAR: - if (nResult == DET_INS_EMPTY) - nResult = DET_INS_CIRCULAR; - break; - // DET_INS_EMPTY: unveraendert lassen - } - } - else // nMaxLevel erreicht - if (nResult != DET_INS_INSERTED) - nResult = DET_INS_CONTINUE; - } - } - - pFCell->SetRunning(false); - - return nResult; -} - -sal_uInt16 ScDetectiveFunc::FindPredLevelArea( const ScRange& rRef, - sal_uInt16 nLevel, sal_uInt16 nDeleteLevel ) -{ - sal_uInt16 nResult = nLevel; - - ScCellIterator aCellIter( pDoc, rRef); - ScBaseCell* pCell = aCellIter.GetFirst(); - while (pCell) - { - if (pCell->GetCellType() == CELLTYPE_FORMULA) - { - sal_uInt16 nTemp = FindPredLevel( aCellIter.GetCol(), aCellIter.GetRow(), nLevel, nDeleteLevel ); - if (nTemp > nResult) - nResult = nTemp; - } - pCell = aCellIter.GetNext(); - } - - return nResult; -} - - // nDeleteLevel != 0 -> loeschen - -sal_uInt16 ScDetectiveFunc::FindPredLevel( SCCOL nCol, SCROW nRow, sal_uInt16 nLevel, sal_uInt16 nDeleteLevel ) -{ - OSL_ENSURE( nLevel<1000, "Level" ); - - ScBaseCell* pCell; - pDoc->GetCell( nCol, nRow, nTab, pCell ); - if (!pCell) - return nLevel; - if (pCell->GetCellType() != CELLTYPE_FORMULA) - return nLevel; - - ScFormulaCell* pFCell = (ScFormulaCell*)pCell; - if (pFCell->IsRunning()) - return nLevel; - - if (pFCell->GetDirty()) - pFCell->Interpret(); // nach SetRunning geht's nicht mehr! - pFCell->SetRunning(sal_True); - - sal_uInt16 nResult = nLevel; - sal_Bool bDelete = ( nDeleteLevel && nLevel == nDeleteLevel-1 ); - - if ( bDelete ) - { - DeleteArrowsAt( nCol, nRow, sal_True ); // Pfeile, die hierher zeigen - } - - ScDetectiveRefIter aIter( (ScFormulaCell*) pCell ); - ScRange aRef; - while ( aIter.GetNextRef( aRef) ) - { - sal_Bool bArea = ( aRef.aStart != aRef.aEnd ); - - if ( bDelete ) // Rahmen loeschen ? - { - if (bArea) - { - DeleteBox( aRef.aStart.Col(), aRef.aStart.Row(), aRef.aEnd.Col(), aRef.aEnd.Row() ); - } - } - else // weitersuchen - { - if ( HasArrow( aRef.aStart, nCol,nRow,nTab ) ) - { - sal_uInt16 nTemp; - if (bArea) - nTemp = FindPredLevelArea( aRef, nLevel+1, nDeleteLevel ); - else - nTemp = FindPredLevel( aRef.aStart.Col(),aRef.aStart.Row(), - nLevel+1, nDeleteLevel ); - if (nTemp > nResult) - nResult = nTemp; - } - } - } - - pFCell->SetRunning(false); - - return nResult; -} - -//------------------------------------------------------------------------ - -sal_uInt16 ScDetectiveFunc::InsertErrorLevel( SCCOL nCol, SCROW nRow, ScDetectiveData& rData, - sal_uInt16 nLevel ) -{ - ScBaseCell* pCell; - pDoc->GetCell( nCol, nRow, nTab, pCell ); - if (!pCell) - return DET_INS_EMPTY; - if (pCell->GetCellType() != CELLTYPE_FORMULA) - return DET_INS_EMPTY; - - ScFormulaCell* pFCell = (ScFormulaCell*)pCell; - if (pFCell->IsRunning()) - return DET_INS_CIRCULAR; - - if (pFCell->GetDirty()) - pFCell->Interpret(); // nach SetRunning geht's nicht mehr! - pFCell->SetRunning(sal_True); - - sal_uInt16 nResult = DET_INS_EMPTY; - - ScDetectiveRefIter aIter( (ScFormulaCell*) pCell ); - ScRange aRef; - ScAddress aErrorPos; - sal_Bool bHasError = false; - while ( aIter.GetNextRef( aRef ) ) - { - if (HasError( aRef, aErrorPos )) - { - bHasError = sal_True; - if (DrawEntry( nCol, nRow, ScRange( aErrorPos), rData )) - nResult = DET_INS_INSERTED; - - // und weiterverfolgen - - if ( nLevel < rData.GetMaxLevel() ) // praktisch immer - { - if (InsertErrorLevel( aErrorPos.Col(), aErrorPos.Row(), - rData, nLevel+1 ) == DET_INS_INSERTED) - nResult = DET_INS_INSERTED; - } - } - } - - pFCell->SetRunning(false); - - // Blaetter ? - if (!bHasError) - if (InsertPredLevel( nCol, nRow, rData, rData.GetMaxLevel() ) == DET_INS_INSERTED) - nResult = DET_INS_INSERTED; - - return nResult; -} - -//------------------------------------------------------------------------ - -sal_uInt16 ScDetectiveFunc::InsertSuccLevel( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, - ScDetectiveData& rData, sal_uInt16 nLevel ) -{ - // ueber ganzes Dokument - - sal_uInt16 nResult = DET_INS_EMPTY; - ScCellIterator aCellIter( pDoc, 0,0,0, MAXCOL,MAXROW,MAXTAB ); // alle Tabellen - ScBaseCell* pCell = aCellIter.GetFirst(); - while (pCell) - { - if (pCell->GetCellType() == CELLTYPE_FORMULA) - { - ScFormulaCell* pFCell = (ScFormulaCell*)pCell; - sal_Bool bRunning = pFCell->IsRunning(); - - if (pFCell->GetDirty()) - pFCell->Interpret(); // nach SetRunning geht's nicht mehr! - pFCell->SetRunning(sal_True); - - ScDetectiveRefIter aIter( (ScFormulaCell*) pCell ); - ScRange aRef; - while ( aIter.GetNextRef( aRef) ) - { - if (aRef.aStart.Tab() <= nTab && aRef.aEnd.Tab() >= nTab) - { - if (Intersect( nCol1,nRow1,nCol2,nRow2, - aRef.aStart.Col(),aRef.aStart.Row(), - aRef.aEnd.Col(),aRef.aEnd.Row() )) - { - sal_Bool bAlien = ( aCellIter.GetTab() != nTab ); - sal_Bool bDrawRet; - if (bAlien) - bDrawRet = DrawAlienEntry( aRef, rData ); - else - bDrawRet = DrawEntry( aCellIter.GetCol(), aCellIter.GetRow(), - aRef, rData ); - if (bDrawRet) - { - nResult = DET_INS_INSERTED; // neuer Pfeil eingetragen - } - else - { - if (bRunning) - { - if (nResult == DET_INS_EMPTY) - nResult = DET_INS_CIRCULAR; - } - else - { - // weiterverfolgen - - if ( nLevel < rData.GetMaxLevel() ) - { - sal_uInt16 nSubResult = InsertSuccLevel( - aCellIter.GetCol(), aCellIter.GetRow(), - aCellIter.GetCol(), aCellIter.GetRow(), - rData, nLevel+1 ); - switch (nSubResult) - { - case DET_INS_INSERTED: - nResult = DET_INS_INSERTED; - break; - case DET_INS_CONTINUE: - if (nResult != DET_INS_INSERTED) - nResult = DET_INS_CONTINUE; - break; - case DET_INS_CIRCULAR: - if (nResult == DET_INS_EMPTY) - nResult = DET_INS_CIRCULAR; - break; - // DET_INS_EMPTY: unveraendert lassen - } - } - else // nMaxLevel erreicht - if (nResult != DET_INS_INSERTED) - nResult = DET_INS_CONTINUE; - } - } - } - } - } - pFCell->SetRunning(bRunning); - } - pCell = aCellIter.GetNext(); - } - - return nResult; -} - -sal_uInt16 ScDetectiveFunc::FindSuccLevel( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, - sal_uInt16 nLevel, sal_uInt16 nDeleteLevel ) -{ - OSL_ENSURE( nLevel<1000, "Level" ); - - sal_uInt16 nResult = nLevel; - sal_Bool bDelete = ( nDeleteLevel && nLevel == nDeleteLevel-1 ); - - ScCellIterator aCellIter( pDoc, 0,0, nTab, MAXCOL,MAXROW, nTab ); - ScBaseCell* pCell = aCellIter.GetFirst(); - while (pCell) - { - if (pCell->GetCellType() == CELLTYPE_FORMULA) - { - ScFormulaCell* pFCell = (ScFormulaCell*)pCell; - sal_Bool bRunning = pFCell->IsRunning(); - - if (pFCell->GetDirty()) - pFCell->Interpret(); // nach SetRunning geht's nicht mehr! - pFCell->SetRunning(sal_True); - - ScDetectiveRefIter aIter( (ScFormulaCell*) pCell ); - ScRange aRef; - while ( aIter.GetNextRef( aRef) ) - { - if (aRef.aStart.Tab() <= nTab && aRef.aEnd.Tab() >= nTab) - { - if (Intersect( nCol1,nRow1,nCol2,nRow2, - aRef.aStart.Col(),aRef.aStart.Row(), - aRef.aEnd.Col(),aRef.aEnd.Row() )) - { - if ( bDelete ) // Pfeile, die hier anfangen - { - if (aRef.aStart != aRef.aEnd) - { - DeleteBox( aRef.aStart.Col(), aRef.aStart.Row(), - aRef.aEnd.Col(), aRef.aEnd.Row() ); - } - DeleteArrowsAt( aRef.aStart.Col(), aRef.aStart.Row(), false ); - } - else if ( !bRunning && - HasArrow( aRef.aStart, - aCellIter.GetCol(),aCellIter.GetRow(),aCellIter.GetTab() ) ) - { - sal_uInt16 nTemp = FindSuccLevel( aCellIter.GetCol(), aCellIter.GetRow(), - aCellIter.GetCol(), aCellIter.GetRow(), - nLevel+1, nDeleteLevel ); - if (nTemp > nResult) - nResult = nTemp; - } - } - } - } - - pFCell->SetRunning(bRunning); - } - pCell = aCellIter.GetNext(); - } - - return nResult; -} - - -// -// -------------------------------------------------------------------------------- -// - -sal_Bool ScDetectiveFunc::ShowPred( SCCOL nCol, SCROW nRow ) -{ - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - if (!pModel) - return false; - - ScDetectiveData aData( pModel ); - - sal_uInt16 nMaxLevel = 0; - sal_uInt16 nResult = DET_INS_CONTINUE; - while (nResult == DET_INS_CONTINUE && nMaxLevel < 1000) - { - aData.SetMaxLevel( nMaxLevel ); - nResult = InsertPredLevel( nCol, nRow, aData, 0 ); - ++nMaxLevel; - } - - return ( nResult == DET_INS_INSERTED ); -} - -sal_Bool ScDetectiveFunc::ShowSucc( SCCOL nCol, SCROW nRow ) -{ - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - if (!pModel) - return false; - - ScDetectiveData aData( pModel ); - - sal_uInt16 nMaxLevel = 0; - sal_uInt16 nResult = DET_INS_CONTINUE; - while (nResult == DET_INS_CONTINUE && nMaxLevel < 1000) - { - aData.SetMaxLevel( nMaxLevel ); - nResult = InsertSuccLevel( nCol, nRow, nCol, nRow, aData, 0 ); - ++nMaxLevel; - } - - return ( nResult == DET_INS_INSERTED ); -} - -sal_Bool ScDetectiveFunc::ShowError( SCCOL nCol, SCROW nRow ) -{ - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - if (!pModel) - return false; - - ScRange aRange( nCol, nRow, nTab ); - ScAddress aErrPos; - if ( !HasError( aRange,aErrPos ) ) - return false; - - ScDetectiveData aData( pModel ); - - aData.SetMaxLevel( 1000 ); - sal_uInt16 nResult = InsertErrorLevel( nCol, nRow, aData, 0 ); - - return ( nResult == DET_INS_INSERTED ); -} - -sal_Bool ScDetectiveFunc::DeleteSucc( SCCOL nCol, SCROW nRow ) -{ - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - if (!pModel) - return false; - - sal_uInt16 nLevelCount = FindSuccLevel( nCol, nRow, nCol, nRow, 0, 0 ); - if ( nLevelCount ) - FindSuccLevel( nCol, nRow, nCol, nRow, 0, nLevelCount ); // loeschen - - return ( nLevelCount != 0 ); -} - -sal_Bool ScDetectiveFunc::DeletePred( SCCOL nCol, SCROW nRow ) -{ - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - if (!pModel) - return false; - - sal_uInt16 nLevelCount = FindPredLevel( nCol, nRow, 0, 0 ); - if ( nLevelCount ) - FindPredLevel( nCol, nRow, 0, nLevelCount ); // loeschen - - return ( nLevelCount != 0 ); -} - -sal_Bool ScDetectiveFunc::DeleteAll( ScDetectiveDelete eWhat ) -{ - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - if (!pModel) - return false; - - SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); - OSL_ENSURE(pPage,"Page ?"); - - pPage->RecalcObjOrdNums(); - - long nDelCount = 0; - sal_uLong nObjCount = pPage->GetObjCount(); - if (nObjCount) - { - SdrObject** ppObj = new SdrObject*[nObjCount]; - - SdrObjListIter aIter( *pPage, IM_FLAT ); - SdrObject* pObject = aIter.Next(); - while (pObject) - { - if ( pObject->GetLayer() == SC_LAYER_INTERN ) - { - sal_Bool bDoThis = sal_True; - if ( eWhat != SC_DET_ALL ) - { - sal_Bool bCircle = ( pObject->ISA(SdrCircObj) ); - sal_Bool bCaption = ScDrawLayer::IsNoteCaption( pObject ); - if ( eWhat == SC_DET_DETECTIVE ) // Detektiv, aus Menue - bDoThis = !bCaption; // auch Kreise - else if ( eWhat == SC_DET_CIRCLES ) // Kreise, wenn neue erzeugt werden - bDoThis = bCircle; - else if ( eWhat == SC_DET_ARROWS ) // DetectiveRefresh - bDoThis = !bCaption && !bCircle; // don't include circles - else - { - OSL_FAIL("wat?"); - } - } - if ( bDoThis ) - ppObj[nDelCount++] = pObject; - } - - pObject = aIter.Next(); - } - - long i; - for (i=1; i<=nDelCount; i++) - pModel->AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) ); - - for (i=1; i<=nDelCount; i++) - pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() ); - - delete[] ppObj; - - Modified(); - } - - return ( nDelCount != 0 ); -} - -sal_Bool ScDetectiveFunc::MarkInvalid(sal_Bool& rOverflow) -{ - rOverflow = false; - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - if (!pModel) - return false; - - sal_Bool bDeleted = DeleteAll( SC_DET_CIRCLES ); // nur die Kreise - - ScDetectiveData aData( pModel ); - long nInsCount = 0; - - // Stellen suchen, wo Gueltigkeit definiert ist - - ScDocAttrIterator aAttrIter( pDoc, nTab, 0,0,MAXCOL,MAXROW ); - SCCOL nCol; - SCROW nRow1; - SCROW nRow2; - const ScPatternAttr* pPattern = aAttrIter.GetNext( nCol, nRow1, nRow2 ); - while ( pPattern && nInsCount < SC_DET_MAXCIRCLE ) - { - sal_uLong nIndex = ((const SfxUInt32Item&)pPattern->GetItem(ATTR_VALIDDATA)).GetValue(); - if (nIndex) - { - const ScValidationData* pData = pDoc->GetValidationEntry( nIndex ); - if ( pData ) - { - // Zellen in dem Bereich durchgehen - - sal_Bool bMarkEmpty = !pData->IsIgnoreBlank(); - SCROW nNextRow = nRow1; - SCROW nRow; - ScCellIterator aCellIter( pDoc, nCol,nRow1,nTab, nCol,nRow2,nTab ); - ScBaseCell* pCell = aCellIter.GetFirst(); - while ( pCell && nInsCount < SC_DET_MAXCIRCLE ) - { - SCROW nCellRow = aCellIter.GetRow(); - if ( bMarkEmpty ) - for ( nRow = nNextRow; nRow < nCellRow && nInsCount < SC_DET_MAXCIRCLE; nRow++ ) - { - DrawCircle( nCol, nRow, aData ); - ++nInsCount; - } - if ( !pData->IsDataValid( pCell, ScAddress( nCol, nCellRow, nTab ) ) ) - { - DrawCircle( nCol, nCellRow, aData ); - ++nInsCount; - } - nNextRow = nCellRow + 1; - pCell = aCellIter.GetNext(); - } - if ( bMarkEmpty ) - for ( nRow = nNextRow; nRow <= nRow2 && nInsCount < SC_DET_MAXCIRCLE; nRow++ ) - { - DrawCircle( nCol, nRow, aData ); - ++nInsCount; - } - } - } - - pPattern = aAttrIter.GetNext( nCol, nRow1, nRow2 ); - } - - if ( nInsCount >= SC_DET_MAXCIRCLE ) - rOverflow = sal_True; - - return ( bDeleted || nInsCount != 0 ); -} - -void ScDetectiveFunc::GetAllPreds(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, - vector<ScTokenRef>& rRefTokens) -{ - ScCellIterator aCellIter(pDoc, nCol1, nRow1, nTab, nCol2, nRow2, nTab); - for (ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell = aCellIter.GetNext()) - { - if (pCell->GetCellType() != CELLTYPE_FORMULA) - continue; - - ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); - ScDetectiveRefIter aRefIter(pFCell); - for (ScToken* p = aRefIter.GetNextRefToken(); p; p = aRefIter.GetNextRefToken()) - { - ScTokenRef pRef(static_cast<ScToken*>(p->Clone())); - ScRefTokenHelper::join(rRefTokens, pRef); - } - } -} - -void ScDetectiveFunc::GetAllSuccs(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, - vector<ScTokenRef>& rRefTokens) -{ - vector<ScTokenRef> aSrcRange; - aSrcRange.push_back( - ScRefTokenHelper::createRefToken(ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab))); - - ScCellIterator aCellIter(pDoc, 0, 0, nTab, MAXCOL, MAXROW, nTab); - for (ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell = aCellIter.GetNext()) - { - if (pCell->GetCellType() != CELLTYPE_FORMULA) - continue; - - ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); - ScDetectiveRefIter aRefIter(pFCell); - for (ScToken* p = aRefIter.GetNextRefToken(); p; p = aRefIter.GetNextRefToken()) - { - ScTokenRef pRef(static_cast<ScToken*>(p->Clone())); - if (ScRefTokenHelper::intersects(aSrcRange, pRef)) - { - pRef = ScRefTokenHelper::createRefToken(aCellIter.GetPos()); - ScRefTokenHelper::join(rRefTokens, pRef); - } - } - } -} - -void ScDetectiveFunc::UpdateAllComments( ScDocument& rDoc ) -{ - // for all caption objects, update attributes and SpecialTextBoxShadow flag - // (on all tables - nTab is ignored!) - - // no undo actions, this is refreshed after undo - - ScDrawLayer* pModel = rDoc.GetDrawLayer(); - if (!pModel) - return; - - for( SCTAB nObjTab = 0, nTabCount = rDoc.GetTableCount(); nObjTab < nTabCount; ++nObjTab ) - { - rDoc.InitializeNoteCaptions( nObjTab ); - SdrPage* pPage = pModel->GetPage( static_cast< sal_uInt16 >( nObjTab ) ); - OSL_ENSURE( pPage, "Page ?" ); - if( pPage ) - { - SdrObjListIter aIter( *pPage, IM_FLAT ); - for( SdrObject* pObject = aIter.Next(); pObject; pObject = aIter.Next() ) - { - if ( ScDrawObjData* pData = ScDrawLayer::GetNoteCaptionData( pObject, nObjTab ) ) - { - ScPostIt* pNote = rDoc.GetNote( pData->maStart ); - // caption should exist, we iterate over drawing objects... - OSL_ENSURE( pNote && (pNote->GetCaption() == pObject), "ScDetectiveFunc::UpdateAllComments - invalid cell note" ); - if( pNote ) - { - ScCommentData aData( rDoc, pModel ); - SfxItemSet aAttrColorSet = pObject->GetMergedItemSet(); - aAttrColorSet.Put( XFillColorItem( String(), GetCommentColor() ) ); - aData.UpdateCaptionSet( aAttrColorSet ); - pObject->SetMergedItemSetAndBroadcast( aData.GetCaptionSet() ); - if( SdrCaptionObj* pCaption = dynamic_cast< SdrCaptionObj* >( pObject ) ) - { - pCaption->SetSpecialTextBoxShadow(); - pCaption->SetFixedTail(); - } - } - } - } - } - } -} - -void ScDetectiveFunc::UpdateAllArrowColors() -{ - // no undo actions necessary - - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - if (!pModel) - return; - - for( SCTAB nObjTab = 0, nTabCount = pDoc->GetTableCount(); nObjTab < nTabCount; ++nObjTab ) - { - SdrPage* pPage = pModel->GetPage( static_cast< sal_uInt16 >( nObjTab ) ); - OSL_ENSURE( pPage, "Page ?" ); - if( pPage ) - { - SdrObjListIter aIter( *pPage, IM_FLAT ); - for( SdrObject* pObject = aIter.Next(); pObject; pObject = aIter.Next() ) - { - if ( pObject->GetLayer() == SC_LAYER_INTERN ) - { - sal_Bool bArrow = false; - sal_Bool bError = false; - - ScAddress aPos; - ScRange aSource; - sal_Bool bDummy; - ScDetectiveObjType eType = GetDetectiveObjectType( pObject, nObjTab, aPos, aSource, bDummy ); - if ( eType == SC_DETOBJ_ARROW || eType == SC_DETOBJ_TOOTHERTAB ) - { - // source is valid, determine error flag from source range - - ScAddress aErrPos; - if ( HasError( aSource, aErrPos ) ) - bError = sal_True; - else - bArrow = sal_True; - } - else if ( eType == SC_DETOBJ_FROMOTHERTAB ) - { - // source range is no longer known, take error flag from formula itself - // (this means, if the formula has an error, all references to other tables - // are marked red) - - ScAddress aErrPos; - if ( HasError( ScRange( aPos), aErrPos ) ) - bError = sal_True; - else - bArrow = sal_True; - } - else if ( eType == SC_DETOBJ_CIRCLE ) - { - // circles (error marks) are always red - - bError = sal_True; - } - else if ( eType == SC_DETOBJ_NONE ) - { - // frame for area reference has no ObjType, always gets arrow color - - if ( pObject->ISA( SdrRectObj ) && !pObject->ISA( SdrCaptionObj ) ) - { - bArrow = sal_True; - } - } - - if ( bArrow || bError ) - { - ColorData nColorData = ( bError ? GetErrorColor() : GetArrowColor() ); - pObject->SetMergedItem( XLineColorItem( String(), Color( nColorData ) ) ); - - // repaint only - pObject->ActionChanged(); - } - } - } - } - } -} - -sal_Bool ScDetectiveFunc::FindFrameForObject( SdrObject* pObject, ScRange& rRange ) -{ - // find the rectangle for an arrow (always the object directly before the arrow) - // rRange must be initialized to the source cell of the arrow (start of area) - - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - if (!pModel) return false; - - SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); - OSL_ENSURE(pPage,"Page ?"); - if (!pPage) return false; - - // test if the object is a direct page member - if( pObject && pObject->GetPage() && (pObject->GetPage() == pObject->GetObjList()) ) - { - // Is there a previous object? - const sal_uInt32 nOrdNum(pObject->GetOrdNum()); - - if(nOrdNum > 0) - { - SdrObject* pPrevObj = pPage->GetObj(nOrdNum - 1); - - if ( pPrevObj && pPrevObj->GetLayer() == SC_LAYER_INTERN && pPrevObj->ISA(SdrRectObj) ) - { - ScDrawObjData* pPrevData = ScDrawLayer::GetObjDataTab( pPrevObj, rRange.aStart.Tab() ); - if ( pPrevData && pPrevData->maStart.IsValid() && pPrevData->maEnd.IsValid() && (pPrevData->maStart == rRange.aStart) ) - { - rRange.aEnd = pPrevData->maEnd; - return sal_True; - } - } - } - } - return false; -} - -ScDetectiveObjType ScDetectiveFunc::GetDetectiveObjectType( SdrObject* pObject, SCTAB nObjTab, - ScAddress& rPosition, ScRange& rSource, sal_Bool& rRedLine ) -{ - rRedLine = false; - ScDetectiveObjType eType = SC_DETOBJ_NONE; - - if ( pObject && pObject->GetLayer() == SC_LAYER_INTERN ) - { - if ( ScDrawObjData* pData = ScDrawLayer::GetObjDataTab( pObject, nObjTab ) ) - { - bool bValidStart = pData->maStart.IsValid(); - bool bValidEnd = pData->maEnd.IsValid(); - - if ( pObject->IsPolyObj() && pObject->GetPointCount() == 2 ) - { - // line object -> arrow - - if ( bValidStart ) - eType = bValidEnd ? SC_DETOBJ_ARROW : SC_DETOBJ_TOOTHERTAB; - else if ( bValidEnd ) - eType = SC_DETOBJ_FROMOTHERTAB; - - if ( bValidStart ) - rSource = pData->maStart; - if ( bValidEnd ) - rPosition = pData->maEnd; - - if ( bValidStart && lcl_HasThickLine( *pObject ) ) - { - // thick line -> look for frame before this object - - FindFrameForObject( pObject, rSource ); // modifies rSource - } - - ColorData nObjColor = ((const XLineColorItem&)pObject->GetMergedItem(XATTR_LINECOLOR)).GetColorValue().GetColor(); - if ( nObjColor == GetErrorColor() && nObjColor != GetArrowColor() ) - rRedLine = sal_True; - } - else if ( pObject->ISA(SdrCircObj) ) - { - if ( bValidStart ) - { - // cell position is returned in rPosition - - rPosition = pData->maStart; - eType = SC_DETOBJ_CIRCLE; - } - } - } - } - - return eType; -} - -void ScDetectiveFunc::InsertObject( ScDetectiveObjType eType, - const ScAddress& rPosition, const ScRange& rSource, - sal_Bool bRedLine ) -{ - ScDrawLayer* pModel = pDoc->GetDrawLayer(); - if (!pModel) return; - ScDetectiveData aData( pModel ); - - switch (eType) - { - case SC_DETOBJ_ARROW: - case SC_DETOBJ_FROMOTHERTAB: - InsertArrow( rPosition.Col(), rPosition.Row(), - rSource.aStart.Col(), rSource.aStart.Row(), - rSource.aEnd.Col(), rSource.aEnd.Row(), - (eType == SC_DETOBJ_FROMOTHERTAB), bRedLine, aData ); - break; - case SC_DETOBJ_TOOTHERTAB: - InsertToOtherTab( rSource.aStart.Col(), rSource.aStart.Row(), - rSource.aEnd.Col(), rSource.aEnd.Row(), - bRedLine, aData ); - break; - case SC_DETOBJ_CIRCLE: - DrawCircle( rPosition.Col(), rPosition.Row(), aData ); - break; - default: - { - // added to avoid warnings - } - } -} - -ColorData ScDetectiveFunc::GetArrowColor() -{ - if (!bColorsInitialized) - InitializeColors(); - return nArrowColor; -} - -ColorData ScDetectiveFunc::GetErrorColor() -{ - if (!bColorsInitialized) - InitializeColors(); - return nErrorColor; -} - -ColorData ScDetectiveFunc::GetCommentColor() -{ - if (!bColorsInitialized) - InitializeColors(); - return nCommentColor; -} - -void ScDetectiveFunc::InitializeColors() -{ - // may be called several times to update colors from configuration - - const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig(); - nArrowColor = rColorCfg.GetColorValue(svtools::CALCDETECTIVE).nColor; - nErrorColor = rColorCfg.GetColorValue(svtools::CALCDETECTIVEERROR).nColor; - nCommentColor = rColorCfg.GetColorValue(svtools::CALCNOTESBACKGROUND).nColor; - - bColorsInitialized = sal_True; -} - -sal_Bool ScDetectiveFunc::IsColorsInitialized() -{ - return bColorsInitialized; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |