diff options
Diffstat (limited to 'sc/source/core/data/drwlayer.cxx')
-rw-r--r-- | sc/source/core/data/drwlayer.cxx | 2075 |
1 files changed, 2075 insertions, 0 deletions
diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx new file mode 100644 index 000000000000..cb82ede30dca --- /dev/null +++ b/sc/source/core/data/drwlayer.cxx @@ -0,0 +1,2075 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: drwlayer.cxx,v $ + * $Revision: 1.55.128.8 $ + * + * 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 <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/embed/XEmbeddedObject.hpp> +#include <com/sun/star/embed/XVisualObject.hpp> +#include <com/sun/star/embed/XClassifiedObject.hpp> +#include <com/sun/star/embed/XComponentSupplier.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/NoVisualAreaSizeException.hpp> +#include <com/sun/star/datatransfer/XTransferable.hpp> + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <svx/eeitem.hxx> +#include <svx/frmdiritem.hxx> +#include <sot/exchange.hxx> +#include <svx/objfac3d.hxx> +#include <svx/xtable.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svditer.hxx> +#include <svx/svdocapt.hxx> +#include <svx/svdocirc.hxx> +#include <svx/svdoedge.hxx> +#include <svx/svdograf.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdundo.hxx> +#include <svx/unolingu.hxx> +#include <svx/drawitem.hxx> +#include <svx/fhgtitem.hxx> +#include <svx/scriptspaceitem.hxx> +#include <svx/shapepropertynotifier.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/docfile.hxx> +#include <sot/storage.hxx> +#include <unotools/pathoptions.hxx> +#include <svl/itempool.hxx> +#include <vcl/virdev.hxx> +#include <vcl/svapp.hxx> +#include <unotools/ucbstreamhelper.hxx> + +#include "drwlayer.hxx" +#include "drawpage.hxx" +#include "global.hxx" +#include "document.hxx" +#include "rechead.hxx" +#include "userdat.hxx" +#include "markdata.hxx" +#include "globstr.hrc" +#include "scmod.hxx" +#include "chartarr.hxx" +#include "postit.hxx" +#include "attrib.hxx" + +#define DET_ARROW_OFFSET 1000 + +// Abstand zur naechsten Zelle beim Loeschen (bShrink), damit der Anker +// immer an der richtigen Zelle angezeigt wird +//#define SHRINK_DIST 3 +// und noch etwas mehr, damit das Objekt auch sichtbar in der Zelle liegt +#define SHRINK_DIST 25 + +#define SHRINK_DIST_TWIPS 15 + +using namespace ::com::sun::star; + +// STATIC DATA ----------------------------------------------------------- + +TYPEINIT1(ScTabDeletedHint, SfxHint); +TYPEINIT1(ScTabSizeChangedHint, SfxHint); + +static ScDrawObjFactory* pFac = NULL; +static E3dObjFactory* pF3d = NULL; +static USHORT nInst = 0; + +SfxObjectShell* ScDrawLayer::pGlobalDrawPersist = NULL; +//REMOVE SvPersist* ScDrawLayer::pGlobalDrawPersist = NULL; + +BOOL bDrawIsInUndo = FALSE; //! Member + +// ----------------------------------------------------------------------- + +ScUndoObjData::ScUndoObjData( SdrObject* pObjP, const ScAddress& rOS, const ScAddress& rOE, + const ScAddress& rNS, const ScAddress& rNE ) : + SdrUndoObj( *pObjP ), + aOldStt( rOS ), + aOldEnd( rOE ), + aNewStt( rNS ), + aNewEnd( rNE ) +{ +} + +__EXPORT ScUndoObjData::~ScUndoObjData() +{ +} + +void ScUndoObjData::Undo() +{ + ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj ); + DBG_ASSERT(pData,"ScUndoObjData: Daten nicht da"); + if (pData) + { + pData->maStart = aOldStt; + pData->maEnd = aOldEnd; + } +} + +void __EXPORT ScUndoObjData::Redo() +{ + ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj ); + DBG_ASSERT(pData,"ScUndoObjData: Daten nicht da"); + if (pData) + { + pData->maStart = aNewStt; + pData->maEnd = aNewEnd; + } +} + +// ----------------------------------------------------------------------- + +ScTabDeletedHint::ScTabDeletedHint( SCTAB nTabNo ) : + nTab( nTabNo ) +{ +} + +__EXPORT ScTabDeletedHint::~ScTabDeletedHint() +{ +} + +ScTabSizeChangedHint::ScTabSizeChangedHint( SCTAB nTabNo ) : + nTab( nTabNo ) +{ +} + +__EXPORT ScTabSizeChangedHint::~ScTabSizeChangedHint() +{ +} + +// ----------------------------------------------------------------------- + +#define MAXMM 10000000 + +inline void TwipsToMM( long& nVal ) +{ + nVal = (long) ( nVal * HMM_PER_TWIPS ); +} + +inline void ReverseTwipsToMM( long& nVal ) +{ + // reverse the effect of TwipsToMM - round up here (add 1) + + nVal = ((long) ( nVal / HMM_PER_TWIPS )) + 1; +} + +void lcl_TwipsToMM( Point& rPoint ) +{ + TwipsToMM( rPoint.X() ); + TwipsToMM( rPoint.Y() ); +} + +void lcl_ReverseTwipsToMM( Point& rPoint ) +{ + ReverseTwipsToMM( rPoint.X() ); + ReverseTwipsToMM( rPoint.Y() ); +} + +void lcl_ReverseTwipsToMM( Rectangle& rRect ) +{ + ReverseTwipsToMM( rRect.Left() ); + ReverseTwipsToMM( rRect.Right() ); + ReverseTwipsToMM( rRect.Top() ); + ReverseTwipsToMM( rRect.Bottom() ); +} + +// ----------------------------------------------------------------------- + + +ScDrawLayer::ScDrawLayer( ScDocument* pDocument, const String& rName ) : + FmFormModel( SvtPathOptions().GetPalettePath(), + NULL, // SfxItemPool* Pool + pGlobalDrawPersist ? + pGlobalDrawPersist : + ( pDocument ? pDocument->GetDocumentShell() : NULL ), + TRUE ), // bUseExtColorTable (is set below) + aName( rName ), + pDoc( pDocument ), + pUndoGroup( NULL ), + bRecording( FALSE ), + bAdjustEnabled( TRUE ), + bHyphenatorSet( FALSE ) +{ + pGlobalDrawPersist = NULL; // nur einmal benutzen + + SfxObjectShell* pObjSh = pDocument ? pDocument->GetDocumentShell() : NULL; + if ( pObjSh ) + { + SetObjectShell( pObjSh ); + + // set color table + SvxColorTableItem* pColItem = (SvxColorTableItem*) pObjSh->GetItem( SID_COLOR_TABLE ); + XColorTable* pXCol = pColItem ? pColItem->GetColorTable() : XColorTable::GetStdColorTable(); + SetColorTable( pXCol ); + } + else + SetColorTable( XColorTable::GetStdColorTable() ); + + SetSwapGraphics(TRUE); +// SetSwapAsynchron(TRUE); // an der View + + SetScaleUnit(MAP_100TH_MM); + SfxItemPool& rPool = GetItemPool(); + rPool.SetDefaultMetric(SFX_MAPUNIT_100TH_MM); + SvxFrameDirectionItem aModeItem( FRMDIR_ENVIRONMENT, EE_PARA_WRITINGDIR ); + rPool.SetPoolDefaultItem( aModeItem ); + + // #i33700# + // Set shadow distance defaults as PoolDefaultItems. Details see bug. + rPool.SetPoolDefaultItem(SdrShadowXDistItem(300)); + rPool.SetPoolDefaultItem(SdrShadowYDistItem(300)); + + // #111216# default for script spacing depends on locale, see SdDrawDocument ctor in sd + LanguageType eOfficeLanguage = Application::GetSettings().GetLanguage(); + if ( eOfficeLanguage == LANGUAGE_KOREAN || eOfficeLanguage == LANGUAGE_KOREAN_JOHAB || + eOfficeLanguage == LANGUAGE_JAPANESE ) + { + // secondary is edit engine pool + rPool.GetSecondaryPool()->SetPoolDefaultItem( SvxScriptSpaceItem( FALSE, EE_PARA_ASIANCJKSPACING ) ); + } + + rPool.FreezeIdRanges(); // the pool is also used directly + + SdrLayerAdmin& rAdmin = GetLayerAdmin(); + rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("vorne")), SC_LAYER_FRONT); + rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("hinten")), SC_LAYER_BACK); + rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("intern")), SC_LAYER_INTERN); + rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Controls")), SC_LAYER_CONTROLS); + rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("hidden")), SC_LAYER_HIDDEN); + // "Controls" is new - must also be created when loading + + // Link fuer URL-Fields setzen + ScModule* pScMod = SC_MOD(); + Outliner& rOutliner = GetDrawOutliner(); + rOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) ); + + Outliner& rHitOutliner = GetHitTestOutliner(); + rHitOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) ); + + // #95129# SJ: set FontHeight pool defaults without changing static SdrEngineDefaults + SfxItemPool* pOutlinerPool = rOutliner.GetEditTextObjectPool(); + if ( pOutlinerPool ) + pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt + SfxItemPool* pHitOutlinerPool = rHitOutliner.GetEditTextObjectPool(); + if ( pHitOutlinerPool ) + pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt + + // URL-Buttons haben keinen Handler mehr, machen alles selber + + if( !nInst++ ) + { + pFac = new ScDrawObjFactory; + pF3d = new E3dObjFactory; + } +} + +__EXPORT ScDrawLayer::~ScDrawLayer() +{ + Broadcast(SdrHint(HINT_MODELCLEARED)); + + // #116168# + //Clear(); + ClearModel(sal_True); + + delete pUndoGroup; + if( !--nInst ) + { + delete pFac, pFac = NULL; + delete pF3d, pF3d = NULL; + } +} + +void ScDrawLayer::UseHyphenator() +{ + if (!bHyphenatorSet) + { + com::sun::star::uno::Reference< com::sun::star::linguistic2::XHyphenator > + xHyphenator = LinguMgr::GetHyphenator(); + + GetDrawOutliner().SetHyphenator( xHyphenator ); + GetHitTestOutliner().SetHyphenator( xHyphenator ); + + bHyphenatorSet = TRUE; + } +} + +SdrPage* __EXPORT ScDrawLayer::AllocPage(FASTBOOL bMasterPage) +{ + // don't create basic until it is needed + StarBASIC* pBasic = NULL; + ScDrawPage* pPage = new ScDrawPage( *this, pBasic, sal::static_int_cast<BOOL>(bMasterPage) ); + return pPage; +} + +BOOL ScDrawLayer::HasObjects() const +{ + BOOL bFound = FALSE; + + USHORT nCount = GetPageCount(); + for (USHORT i=0; i<nCount && !bFound; i++) + if (GetPage(i)->GetObjCount()) + bFound = TRUE; + + return bFound; +} + +void ScDrawLayer::UpdateBasic() +{ + // don't create basic until it is needed + //! remove this method? +} + +SdrModel* __EXPORT ScDrawLayer::AllocModel() const +{ + // #103849# Allocated model (for clipboard etc) must not have a pointer + // to the original model's document, pass NULL as document: + + return new ScDrawLayer( NULL, aName ); +} + +Window* __EXPORT ScDrawLayer::GetCurDocViewWin() +{ + DBG_ASSERT( pDoc, "ScDrawLayer::GetCurDocViewWin without document" ); + if ( !pDoc ) + return NULL; + + SfxViewShell* pViewSh = SfxViewShell::Current(); + SfxObjectShell* pObjSh = pDoc->GetDocumentShell(); + + if (pViewSh && pViewSh->GetObjectShell() == pObjSh) + return pViewSh->GetWindow(); + + return NULL; +} + +BOOL ScDrawLayer::ScAddPage( SCTAB nTab ) +{ + if (bDrawIsInUndo) + return FALSE; // not inserted + + ScDrawPage* pPage = (ScDrawPage*)AllocPage( FALSE ); + InsertPage(pPage, static_cast<sal_uInt16>(nTab)); + if (bRecording) + AddCalcUndo(new SdrUndoNewPage(*pPage)); + + return TRUE; // inserted +} + +void ScDrawLayer::ScRemovePage( SCTAB nTab ) +{ + if (bDrawIsInUndo) + return; + + Broadcast( ScTabDeletedHint( nTab ) ); + if (bRecording) + { + SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); + AddCalcUndo(new SdrUndoDelPage(*pPage)); // Undo-Action wird Owner der Page + RemovePage( static_cast<sal_uInt16>(nTab) ); // nur austragen, nicht loeschen + } + else + DeletePage( static_cast<sal_uInt16>(nTab) ); // einfach weg damit +} + +void ScDrawLayer::ScRenamePage( SCTAB nTab, const String& rNewName ) +{ + ScDrawPage* pPage = (ScDrawPage*) GetPage(static_cast<sal_uInt16>(nTab)); + if (pPage) + pPage->SetName(rNewName); +} + +void ScDrawLayer::ScMovePage( USHORT nOldPos, USHORT nNewPos ) +{ + MovePage( nOldPos, nNewPos ); +} + +void ScDrawLayer::ScCopyPage( USHORT nOldPos, USHORT nNewPos, BOOL bAlloc ) +{ + //! remove argument bAlloc (always FALSE) + + if (bDrawIsInUndo) + return; + + SdrPage* pOldPage = GetPage(nOldPos); + SdrPage* pNewPage = bAlloc ? AllocPage(FALSE) : GetPage(nNewPos); + + // kopieren + + if (pOldPage && pNewPage) + { + SdrObjListIter aIter( *pOldPage, IM_FLAT ); + SdrObject* pOldObject = aIter.Next(); + while (pOldObject) + { + // #116235# + SdrObject* pNewObject = pOldObject->Clone(); + //SdrObject* pNewObject = pOldObject->Clone( pNewPage, this ); + pNewObject->SetModel(this); + pNewObject->SetPage(pNewPage); + + pNewObject->NbcMove(Size(0,0)); + pNewPage->InsertObject( pNewObject ); + if (bRecording) + AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) ); + + pOldObject = aIter.Next(); + } + } + + if (bAlloc) + InsertPage(pNewPage, nNewPos); +} + +inline BOOL IsInBlock( const ScAddress& rPos, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2 ) +{ + return rPos.Col() >= nCol1 && rPos.Col() <= nCol2 && + rPos.Row() >= nRow1 && rPos.Row() <= nRow2; +} + +void ScDrawLayer::MoveCells( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2, + SCsCOL nDx,SCsROW nDy ) +{ + SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Page nicht gefunden"); + if (!pPage) + return; + + BOOL bNegativePage = pDoc && pDoc->IsNegativePage( nTab ); + + ULONG nCount = pPage->GetObjCount(); + for ( ULONG i = 0; i < nCount; i++ ) + { + SdrObject* pObj = pPage->GetObj( i ); + ScDrawObjData* pData = GetObjDataTab( pObj, nTab ); + if( pData ) + { + const ScAddress aOldStt = pData->maStart; + const ScAddress aOldEnd = pData->maEnd; + BOOL bChange = FALSE; + if ( aOldStt.IsValid() && IsInBlock( aOldStt, nCol1,nRow1, nCol2,nRow2 ) ) + { + pData->maStart.IncCol( nDx ); + pData->maStart.IncRow( nDy ); + bChange = TRUE; + } + if ( aOldEnd.IsValid() && IsInBlock( aOldEnd, nCol1,nRow1, nCol2,nRow2 ) ) + { + pData->maEnd.IncCol( nDx ); + pData->maEnd.IncRow( nDy ); + bChange = TRUE; + } + if (bChange) + { + if ( pObj->ISA( SdrRectObj ) && pData->maStart.IsValid() && pData->maEnd.IsValid() ) + pData->maStart.PutInOrder( pData->maEnd ); + AddCalcUndo( new ScUndoObjData( pObj, aOldStt, aOldEnd, pData->maStart, pData->maEnd ) ); + RecalcPos( pObj, *pData, bNegativePage ); + } + } + } +} + +void ScDrawLayer::SetPageSize( USHORT nPageNo, const Size& rSize ) +{ + SdrPage* pPage = GetPage(nPageNo); + if (pPage) + { + if ( rSize != pPage->GetSize() ) + { + pPage->SetSize( rSize ); + Broadcast( ScTabSizeChangedHint( static_cast<SCTAB>(nPageNo) ) ); // SetWorkArea() an den Views + } + + // Detektivlinien umsetzen (an neue Hoehen/Breiten anpassen) + // auch wenn Groesse gleich geblieben ist + // (einzelne Zeilen/Spalten koennen geaendert sein) + + BOOL bNegativePage = pDoc && pDoc->IsNegativePage( static_cast<SCTAB>(nPageNo) ); + + ULONG nCount = pPage->GetObjCount(); + for ( ULONG i = 0; i < nCount; i++ ) + { + SdrObject* pObj = pPage->GetObj( i ); + ScDrawObjData* pData = GetObjDataTab( pObj, static_cast<SCTAB>(nPageNo) ); + if( pData ) + RecalcPos( pObj, *pData, bNegativePage ); + } + } +} + +void ScDrawLayer::RecalcPos( SdrObject* pObj, const ScDrawObjData& rData, bool bNegativePage ) +{ + DBG_ASSERT( pDoc, "ScDrawLayer::RecalcPos - missing document" ); + if( !pDoc ) + return; + + /* TODO CleanUp: Updating note position works just by chance currently... + When inserting rows/columns, this function is called after the + insertion, and the note is located at the new position contained in the + passed ScDrawObjData already. But when deleting rows/columns, this + function is called *before* the deletion, so the note is still at the + old cell position, and ScDocument::GetNote() will fail to get the note + or will get another note. But after the rows/columns are deleted, a + call to ScDrawLayer::SetPageSize() will call this function again, and + now the note is at the expected position in the document. */ + if( rData.mbNote ) + { + DBG_ASSERT( rData.maStart.IsValid(), "ScDrawLayer::RecalcPos - invalid position for cell note" ); + /* When inside an undo action, there may be pending note captions + where cell note is already deleted. The caption will be deleted + later with drawing undo. */ + if( ScPostIt* pNote = pDoc->GetNote( rData.maStart ) ) + pNote->UpdateCaptionPos( rData.maStart ); + return; + } + + bool bValid1 = rData.maStart.IsValid(); + SCCOL nCol1 = rData.maStart.Col(); + SCROW nRow1 = rData.maStart.Row(); + SCTAB nTab1 = rData.maStart.Tab(); + bool bValid2 = rData.maEnd.IsValid(); + SCCOL nCol2 = rData.maEnd.Col(); + SCROW nRow2 = rData.maEnd.Row(); + SCTAB nTab2 = rData.maEnd.Tab(); + + // validation circle + bool bCircle = pObj->ISA( SdrCircObj ); + // detective arrow + bool bArrow = pObj->IsPolyObj() && (pObj->GetPointCount() == 2); + + if( bCircle ) + { + Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) ); + TwipsToMM( aPos.X() ); + TwipsToMM( aPos.Y() ); + + // Berechnung und Werte wie in detfunc.cxx + + Size aSize( (long)(pDoc->GetColWidth( nCol1, nTab1 ) * HMM_PER_TWIPS), + (long)(pDoc->GetRowHeight( nRow1, nTab1 ) * HMM_PER_TWIPS) ); + Rectangle aRect( aPos, aSize ); + aRect.Left() -= 250; + aRect.Right() += 250; + aRect.Top() -= 70; + aRect.Bottom() += 70; + if ( bNegativePage ) + MirrorRectRTL( aRect ); + + if ( pObj->GetLogicRect() != aRect ) + { + if (bRecording) + AddCalcUndo( new SdrUndoGeoObj( *pObj ) ); + pObj->SetLogicRect(aRect); + } + } + else if( bArrow ) + { + //! nicht mehrere Undos fuer ein Objekt erzeugen (hinteres kann dann weggelassen werden) + + if( bValid1 ) + { + Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) ); + if( (pDoc->GetColFlags( nCol1, nTab1 ) & CR_HIDDEN) == 0 ) + aPos.X() += pDoc->GetColWidth( nCol1, nTab1 ) / 4; + if( (pDoc->GetRowFlags( nRow1, nTab1 ) & CR_HIDDEN) == 0 ) + aPos.Y() += pDoc->GetRowHeight( nRow1, nTab1 ) / 2; + TwipsToMM( aPos.X() ); + TwipsToMM( aPos.Y() ); + Point aStartPos = aPos; + if ( bNegativePage ) + aStartPos.X() = -aStartPos.X(); // don't modify aPos - used below + if ( pObj->GetPoint( 0 ) != aStartPos ) + { + if (bRecording) + AddCalcUndo( new SdrUndoGeoObj( *pObj ) ); + pObj->SetPoint( aStartPos, 0 ); + } + + if( !bValid2 ) + { + Point aEndPos( aPos.X() + DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET ); + if (aEndPos.Y() < 0) + aEndPos.Y() += (2 * DET_ARROW_OFFSET); + if ( bNegativePage ) + aEndPos.X() = -aEndPos.X(); + if ( pObj->GetPoint( 1 ) != aEndPos ) + { + if (bRecording) + AddCalcUndo( new SdrUndoGeoObj( *pObj ) ); + pObj->SetPoint( aEndPos, 1 ); + } + } + } + if( bValid2 ) + { + Point aPos( pDoc->GetColOffset( nCol2, nTab2 ), pDoc->GetRowOffset( nRow2, nTab2 ) ); + if( (pDoc->GetColFlags( nCol2, nTab2 ) & CR_HIDDEN) == 0 ) + aPos.X() += pDoc->GetColWidth( nCol2, nTab2 ) / 4; + if( (pDoc->GetRowFlags( nRow2, nTab2 ) & CR_HIDDEN) == 0 ) + aPos.Y() += pDoc->GetRowHeight( nRow2, nTab2 ) / 2; + TwipsToMM( aPos.X() ); + TwipsToMM( aPos.Y() ); + Point aEndPos = aPos; + if ( bNegativePage ) + aEndPos.X() = -aEndPos.X(); // don't modify aPos - used below + if ( pObj->GetPoint( 1 ) != aEndPos ) + { + if (bRecording) + AddCalcUndo( new SdrUndoGeoObj( *pObj ) ); + pObj->SetPoint( aEndPos, 1 ); + } + + if( !bValid1 ) + { + Point aStartPos( aPos.X() - DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET ); + if (aStartPos.X() < 0) + aStartPos.X() += (2 * DET_ARROW_OFFSET); + if (aStartPos.Y() < 0) + aStartPos.Y() += (2 * DET_ARROW_OFFSET); + if ( bNegativePage ) + aStartPos.X() = -aStartPos.X(); + if ( pObj->GetPoint( 0 ) != aStartPos ) + { + if (bRecording) + AddCalcUndo( new SdrUndoGeoObj( *pObj ) ); + pObj->SetPoint( aStartPos, 0 ); + } + } + } + } + else // Referenz-Rahmen + { + DBG_ASSERT( bValid1, "ScDrawLayer::RecalcPos - invalid start position" ); + Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) ); + TwipsToMM( aPos.X() ); + TwipsToMM( aPos.Y() ); + + if( bValid2 ) + { + Point aEnd( pDoc->GetColOffset( nCol2 + 1, nTab2 ), pDoc->GetRowOffset( nRow2 + 1, nTab2 ) ); + TwipsToMM( aEnd.X() ); + TwipsToMM( aEnd.Y() ); + + Rectangle aNew( aPos, aEnd ); + if ( bNegativePage ) + MirrorRectRTL( aNew ); + if ( pObj->GetLogicRect() != aNew ) + { + if (bRecording) + AddCalcUndo( new SdrUndoGeoObj( *pObj ) ); + pObj->SetLogicRect(aNew); + } + } + else + { + if ( bNegativePage ) + aPos.X() = -aPos.X(); + if ( pObj->GetRelativePos() != aPos ) + { + if (bRecording) + AddCalcUndo( new SdrUndoGeoObj( *pObj ) ); + pObj->SetRelativePos( aPos ); + } + } + } +} + +BOOL ScDrawLayer::GetPrintArea( ScRange& rRange, BOOL bSetHor, BOOL bSetVer ) const +{ + DBG_ASSERT( pDoc, "ScDrawLayer::GetPrintArea without document" ); + if ( !pDoc ) + return FALSE; + + SCTAB nTab = rRange.aStart.Tab(); + DBG_ASSERT( rRange.aEnd.Tab() == nTab, "GetPrintArea: Tab unterschiedlich" ); + + BOOL bNegativePage = pDoc->IsNegativePage( nTab ); + + BOOL bAny = FALSE; + long nEndX = 0; + long nEndY = 0; + long nStartX = LONG_MAX; + long nStartY = LONG_MAX; + + // Grenzen ausrechnen + + if (!bSetHor) + { + nStartX = 0; + SCCOL nStartCol = rRange.aStart.Col(); + SCCOL i; + for (i=0; i<nStartCol; i++) + nStartX +=pDoc->GetColWidth(i,nTab); + nEndX = nStartX; + SCCOL nEndCol = rRange.aEnd.Col(); + for (i=nStartCol; i<=nEndCol; i++) + nEndX += pDoc->GetColWidth(i,nTab); + nStartX = (long)(nStartX * HMM_PER_TWIPS); + nEndX = (long)(nEndX * HMM_PER_TWIPS); + } + if (!bSetVer) + { + nStartY = pDoc->FastGetRowHeight( 0, rRange.aStart.Row()-1, nTab); + nEndY = nStartY + pDoc->FastGetRowHeight( rRange.aStart.Row(), + rRange.aEnd.Row(), nTab); + nStartY = (long)(nStartY * HMM_PER_TWIPS); + nEndY = (long)(nEndY * HMM_PER_TWIPS); + } + + if ( bNegativePage ) + { + nStartX = -nStartX; // positions are negative, swap start/end so the same comparisons work + nEndX = -nEndX; + ::std::swap( nStartX, nEndX ); + } + + const SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Page nicht gefunden"); + if (pPage) + { + SdrObjListIter aIter( *pPage, IM_FLAT ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + //! Flags (ausgeblendet?) testen + + Rectangle aObjRect = pObject->GetCurrentBoundRect(); + BOOL bFit = TRUE; + if ( !bSetHor && ( aObjRect.Right() < nStartX || aObjRect.Left() > nEndX ) ) + bFit = FALSE; + if ( !bSetVer && ( aObjRect.Bottom() < nStartY || aObjRect.Top() > nEndY ) ) + bFit = FALSE; + if ( bFit ) + { + if (bSetHor) + { + if (aObjRect.Left() < nStartX) nStartX = aObjRect.Left(); + if (aObjRect.Right() > nEndX) nEndX = aObjRect.Right(); + } + if (bSetVer) + { + if (aObjRect.Top() < nStartY) nStartY = aObjRect.Top(); + if (aObjRect.Bottom() > nEndY) nEndY = aObjRect.Bottom(); + } + bAny = TRUE; + } + + pObject = aIter.Next(); + } + } + + if ( bNegativePage ) + { + nStartX = -nStartX; // reverse transformation, so the same cell address calculation works + nEndX = -nEndX; + ::std::swap( nStartX, nEndX ); + } + + if (bAny) + { + DBG_ASSERT( nStartX<=nEndX && nStartY<=nEndY, "Start/End falsch in ScDrawLayer::GetPrintArea" ); + + if (bSetHor) + { + nStartX = (long) (nStartX / HMM_PER_TWIPS); + nEndX = (long) (nEndX / HMM_PER_TWIPS); + long nWidth; + SCCOL i; + + nWidth = 0; + for (i=0; i<=MAXCOL && nWidth<=nStartX; i++) + nWidth += pDoc->GetColWidth(i,nTab); + rRange.aStart.SetCol( i>0 ? (i-1) : 0 ); + + nWidth = 0; + for (i=0; i<=MAXCOL && nWidth<=nEndX; i++) //! bei Start anfangen + nWidth += pDoc->GetColWidth(i,nTab); + rRange.aEnd.SetCol( i>0 ? (i-1) : 0 ); + } + + if (bSetVer) + { + nStartY = (long) (nStartY / HMM_PER_TWIPS); + nEndY = (long) (nEndY / HMM_PER_TWIPS); + SCROW nRow = pDoc->FastGetRowForHeight( nTab, nStartY); + rRange.aStart.SetRow( nRow>0 ? (nRow-1) : 0); + nRow = pDoc->FastGetRowForHeight( nTab, nEndY); + rRange.aEnd.SetRow( nRow == MAXROW ? MAXROW : + (nRow>0 ? (nRow-1) : 0)); + } + } + else + { + if (bSetHor) + { + rRange.aStart.SetCol(0); + rRange.aEnd.SetCol(0); + } + if (bSetVer) + { + rRange.aStart.SetRow(0); + rRange.aEnd.SetRow(0); + } + } + return bAny; +} + +void ScDrawLayer::AddCalcUndo( SdrUndoAction* pUndo ) +{ + if (bRecording) + { + if (!pUndoGroup) + pUndoGroup = new SdrUndoGroup(*this); + + pUndoGroup->AddAction( pUndo ); + } + else + delete pUndo; +} + +void ScDrawLayer::BeginCalcUndo() +{ +//! DBG_ASSERT( !bRecording, "BeginCalcUndo ohne GetCalcUndo" ); + + DELETEZ(pUndoGroup); + bRecording = TRUE; +} + +SdrUndoGroup* ScDrawLayer::GetCalcUndo() +{ +//! DBG_ASSERT( bRecording, "GetCalcUndo ohne BeginCalcUndo" ); + + SdrUndoGroup* pRet = pUndoGroup; + pUndoGroup = NULL; + bRecording = FALSE; + return pRet; +} + +// MoveAreaTwips: all measures are kept in twips +void ScDrawLayer::MoveAreaTwips( SCTAB nTab, const Rectangle& rArea, + const Point& rMove, const Point& rTopLeft ) +{ + if (!rMove.X() && !rMove.Y()) + return; // nix + + SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Page nicht gefunden"); + if (!pPage) + return; + + BOOL bNegativePage = pDoc && pDoc->IsNegativePage( nTab ); + + // fuer Shrinking! + Rectangle aNew( rArea ); + BOOL bShrink = FALSE; + if ( rMove.X() < 0 || rMove.Y() < 0 ) // verkleinern + { + if ( rTopLeft != rArea.TopLeft() ) // sind gleich beim Verschieben von Zellen + { + bShrink = TRUE; + aNew.Left() = rTopLeft.X(); + aNew.Top() = rTopLeft.Y(); + } + } + SdrObjListIter aIter( *pPage, IM_FLAT ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if( GetAnchor( pObject ) == SCA_CELL ) + { + if ( GetObjData( pObject ) ) // Detektiv-Pfeil ? + { + // hier nichts + } + else if ( pObject->ISA( SdrEdgeObj ) ) // Verbinder? + { + // hier auch nichts + //! nicht verbundene Enden wie bei Linien (s.u.) behandeln? + } + else if ( pObject->IsPolyObj() && pObject->GetPointCount()==2 ) + { + for (USHORT i=0; i<2; i++) + { + BOOL bMoved = FALSE; + Point aPoint = pObject->GetPoint(i); + lcl_ReverseTwipsToMM( aPoint ); + if (rArea.IsInside(aPoint)) + { + aPoint += rMove; bMoved = TRUE; + } + else if (bShrink && aNew.IsInside(aPoint)) + { + // Punkt ist in betroffener Zelle - Test auf geloeschten Bereich + if ( rMove.X() && aPoint.X() >= rArea.Left() + rMove.X() ) + { + aPoint.X() = rArea.Left() + rMove.X() - SHRINK_DIST_TWIPS; + if ( aPoint.X() < 0 ) aPoint.X() = 0; + bMoved = TRUE; + } + if ( rMove.Y() && aPoint.Y() >= rArea.Top() + rMove.Y() ) + { + aPoint.Y() = rArea.Top() + rMove.Y() - SHRINK_DIST_TWIPS; + if ( aPoint.Y() < 0 ) aPoint.Y() = 0; + bMoved = TRUE; + } + } + if( bMoved ) + { + AddCalcUndo( new SdrUndoGeoObj( *pObject ) ); + lcl_TwipsToMM( aPoint ); + pObject->SetPoint( aPoint, i ); + } + } + } + else + { + Rectangle aObjRect = pObject->GetLogicRect(); + // aOldMMPos: not converted, millimeters + Point aOldMMPos = bNegativePage ? aObjRect.TopRight() : aObjRect.TopLeft(); + lcl_ReverseTwipsToMM( aObjRect ); + Point aTopLeft = bNegativePage ? aObjRect.TopRight() : aObjRect.TopLeft(); // logical left + Size aMoveSize; + BOOL bDoMove = FALSE; + if (rArea.IsInside(aTopLeft)) + { + aMoveSize = Size(rMove.X(),rMove.Y()); + bDoMove = TRUE; + } + else if (bShrink && aNew.IsInside(aTopLeft)) + { + // Position ist in betroffener Zelle - Test auf geloeschten Bereich + if ( rMove.X() && aTopLeft.X() >= rArea.Left() + rMove.X() ) + { + aMoveSize.Width() = rArea.Left() + rMove.X() - SHRINK_DIST - aTopLeft.X(); + bDoMove = TRUE; + } + if ( rMove.Y() && aTopLeft.Y() >= rArea.Top() + rMove.Y() ) + { + aMoveSize.Height() = rArea.Top() + rMove.Y() - SHRINK_DIST - aTopLeft.Y(); + bDoMove = TRUE; + } + } + if ( bDoMove ) + { + if ( bNegativePage ) + { + if ( aTopLeft.X() + aMoveSize.Width() > 0 ) + aMoveSize.Width() = -aTopLeft.X(); + } + else + { + if ( aTopLeft.X() + aMoveSize.Width() < 0 ) + aMoveSize.Width() = -aTopLeft.X(); + } + if ( aTopLeft.Y() + aMoveSize.Height() < 0 ) + aMoveSize.Height() = -aTopLeft.Y(); + + // get corresponding move size in millimeters: + Point aNewPos( aTopLeft.X() + aMoveSize.Width(), aTopLeft.Y() + aMoveSize.Height() ); + lcl_TwipsToMM( aNewPos ); + aMoveSize = Size( aNewPos.X() - aOldMMPos.X(), aNewPos.Y() - aOldMMPos.Y() ); // millimeters + + AddCalcUndo( new SdrUndoMoveObj( *pObject, aMoveSize ) ); + pObject->Move( aMoveSize ); + } + else if ( rArea.IsInside( bNegativePage ? aObjRect.BottomLeft() : aObjRect.BottomRight() ) && + !pObject->IsResizeProtect() ) + { + // geschuetzte Groessen werden nicht veraendert + // (Positionen schon, weil sie ja an der Zelle "verankert" sind) + AddCalcUndo( new SdrUndoGeoObj( *pObject ) ); + long nOldSizeX = aObjRect.Right() - aObjRect.Left() + 1; + long nOldSizeY = aObjRect.Bottom() - aObjRect.Top() + 1; + long nLogMoveX = rMove.X() * ( bNegativePage ? -1 : 1 ); // logical direction + pObject->Resize( aOldMMPos, Fraction( nOldSizeX+nLogMoveX, nOldSizeX ), + Fraction( nOldSizeY+rMove.Y(), nOldSizeY ) ); + } + } + } + pObject = aIter.Next(); + } +} + +void ScDrawLayer::MoveArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2, + SCsCOL nDx,SCsROW nDy, BOOL bInsDel ) +{ + DBG_ASSERT( pDoc, "ScDrawLayer::MoveArea without document" ); + if ( !pDoc ) + return; + + if (!bAdjustEnabled) + return; + + BOOL bNegativePage = pDoc->IsNegativePage( nTab ); + + Rectangle aRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab ); + lcl_ReverseTwipsToMM( aRect ); + //! use twips directly? + + Point aMove; + + if (nDx > 0) + for (SCsCOL s=0; s<nDx; s++) + aMove.X() += pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab); + else + for (SCsCOL s=-1; s>=nDx; s--) + aMove.X() -= pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab); + if (nDy > 0) + aMove.Y() += pDoc->FastGetRowHeight( nRow1, nRow1+nDy-1, nTab); + else + aMove.Y() -= pDoc->FastGetRowHeight( nRow1+nDy, nRow1-1, nTab); + + if ( bNegativePage ) + aMove.X() = -aMove.X(); + + Point aTopLeft = aRect.TopLeft(); // Anfang beim Verkleinern + if (bInsDel) + { + if ( aMove.X() != 0 && nDx < 0 ) // nDx counts cells, sign is independent of RTL + aTopLeft.X() += aMove.X(); + if ( aMove.Y() < 0 ) + aTopLeft.Y() += aMove.Y(); + } + + // drawing objects are now directly included in cut&paste + // -> only update references when inserting/deleting (or changing widths or heights) + if ( bInsDel ) + MoveAreaTwips( nTab, aRect, aMove, aTopLeft ); + + // + // Detektiv-Pfeile: Zellpositionen anpassen + // + + MoveCells( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy ); +} + +void ScDrawLayer::WidthChanged( SCTAB nTab, SCCOL nCol, long nDifTwips ) +{ + DBG_ASSERT( pDoc, "ScDrawLayer::WidthChanged without document" ); + if ( !pDoc ) + return; + + if (!bAdjustEnabled) + return; + + Rectangle aRect; + Point aTopLeft; + + for (SCCOL i=0; i<nCol; i++) + aRect.Left() += pDoc->GetColWidth(i,nTab); + aTopLeft.X() = aRect.Left(); + aRect.Left() += pDoc->GetColWidth(nCol,nTab); + + aRect.Right() = MAXMM; + aRect.Top() = 0; + aRect.Bottom() = MAXMM; + + //! aTopLeft ist falsch, wenn mehrere Spalten auf einmal ausgeblendet werden + + BOOL bNegativePage = pDoc->IsNegativePage( nTab ); + if ( bNegativePage ) + { + MirrorRectRTL( aRect ); + aTopLeft.X() = -aTopLeft.X(); + nDifTwips = -nDifTwips; + } + + MoveAreaTwips( nTab, aRect, Point( nDifTwips,0 ), aTopLeft ); +} + +void ScDrawLayer::HeightChanged( SCTAB nTab, SCROW nRow, long nDifTwips ) +{ + DBG_ASSERT( pDoc, "ScDrawLayer::HeightChanged without document" ); + if ( !pDoc ) + return; + + if (!bAdjustEnabled) + return; + + Rectangle aRect; + Point aTopLeft; + + aRect.Top() += pDoc->FastGetRowHeight( 0, nRow-1, nTab); + aTopLeft.Y() = aRect.Top(); + aRect.Top() += pDoc->FastGetRowHeight(nRow,nTab); + + aRect.Bottom() = MAXMM; + aRect.Left() = 0; + aRect.Right() = MAXMM; + + //! aTopLeft ist falsch, wenn mehrere Zeilen auf einmal ausgeblendet werden + + BOOL bNegativePage = pDoc->IsNegativePage( nTab ); + if ( bNegativePage ) + { + MirrorRectRTL( aRect ); + aTopLeft.X() = -aTopLeft.X(); + } + + MoveAreaTwips( nTab, aRect, Point( 0,nDifTwips ), aTopLeft ); +} + +BOOL ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow ) +{ + DBG_ASSERT( pDoc, "ScDrawLayer::HasObjectsInRows without document" ); + if ( !pDoc ) + return FALSE; + + Rectangle aTestRect; + + aTestRect.Top() += pDoc->FastGetRowHeight( 0, nStartRow-1, nTab); + + if (nEndRow==MAXROW) + aTestRect.Bottom() = MAXMM; + else + { + aTestRect.Bottom() = aTestRect.Top(); + aTestRect.Bottom() += pDoc->FastGetRowHeight( nStartRow, nEndRow, nTab); + TwipsToMM( aTestRect.Bottom() ); + } + + TwipsToMM( aTestRect.Top() ); + + aTestRect.Left() = 0; + aTestRect.Right() = MAXMM; + + BOOL bNegativePage = pDoc->IsNegativePage( nTab ); + if ( bNegativePage ) + MirrorRectRTL( aTestRect ); + + SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Page nicht gefunden"); + if (!pPage) + return FALSE; + + BOOL bFound = FALSE; + + Rectangle aObjRect; + SdrObjListIter aIter( *pPage ); + SdrObject* pObject = aIter.Next(); + while ( pObject && !bFound ) + { + aObjRect = pObject->GetSnapRect(); //! GetLogicRect ? + if (aTestRect.IsInside(aObjRect.TopLeft()) || aTestRect.IsInside(aObjRect.BottomLeft())) + bFound = TRUE; + + pObject = aIter.Next(); + } + + return bFound; +} + +#if 0 +void ScDrawLayer::DeleteObjects( SCTAB nTab ) +{ + SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Page ?"); + if (!pPage) + return; + + pPage->RecalcObjOrdNums(); + + long nDelCount = 0; + ULONG nObjCount = pPage->GetObjCount(); + if (nObjCount) + { + SdrObject** ppObj = new SdrObject*[nObjCount]; + + SdrObjListIter aIter( *pPage, IM_FLAT ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + // alle loeschen + ppObj[nDelCount++] = pObject; + pObject = aIter.Next(); + } + + long i; + if (bRecording) + for (i=1; i<=nDelCount; i++) + AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) ); + + for (i=1; i<=nDelCount; i++) + pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() ); + + delete[] ppObj; + } +} +#endif + +void ScDrawLayer::DeleteObjectsInArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1, + SCCOL nCol2,SCROW nRow2 ) +{ + DBG_ASSERT( pDoc, "ScDrawLayer::DeleteObjectsInArea without document" ); + if ( !pDoc ) + return; + + SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Page ?"); + if (!pPage) + return; + + pPage->RecalcObjOrdNums(); + + long nDelCount = 0; + ULONG nObjCount = pPage->GetObjCount(); + if (nObjCount) + { + Rectangle aDelRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab ); + + SdrObject** ppObj = new SdrObject*[nObjCount]; + + SdrObjListIter aIter( *pPage, IM_FLAT ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + // do not delete note caption, they are always handled by the cell note + // TODO: detective objects are still deleted, is this desired? + if (!IsNoteCaption( pObject )) + { + Rectangle aObjRect = pObject->GetCurrentBoundRect(); + if ( aDelRect.IsInside( aObjRect ) ) + ppObj[nDelCount++] = pObject; + } + + pObject = aIter.Next(); + } + + long i; + if (bRecording) + for (i=1; i<=nDelCount; i++) + AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) ); + + for (i=1; i<=nDelCount; i++) + pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() ); + + delete[] ppObj; + } +} + +void ScDrawLayer::DeleteObjectsInSelection( const ScMarkData& rMark ) +{ + DBG_ASSERT( pDoc, "ScDrawLayer::DeleteObjectsInSelection without document" ); + if ( !pDoc ) + return; + + if ( !rMark.IsMultiMarked() ) + return; + + ScRange aMarkRange; + rMark.GetMultiMarkArea( aMarkRange ); + + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<=nTabCount; nTab++) + if ( rMark.GetTableSelect( nTab ) ) + { + SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab)); + if (pPage) + { + pPage->RecalcObjOrdNums(); + long nDelCount = 0; + ULONG nObjCount = pPage->GetObjCount(); + if (nObjCount) + { + // Rechteck um die ganze Selektion + Rectangle aMarkBound = pDoc->GetMMRect( + aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), + aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab ); + + SdrObject** ppObj = new SdrObject*[nObjCount]; + + SdrObjListIter aIter( *pPage, IM_FLAT ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + // do not delete note caption, they are always handled by the cell note + // TODO: detective objects are still deleted, is this desired? + if (!IsNoteCaption( pObject )) + { + Rectangle aObjRect = pObject->GetCurrentBoundRect(); + if ( aMarkBound.IsInside( aObjRect ) ) + { + ScRange aRange = pDoc->GetRange( nTab, aObjRect ); + if (rMark.IsAllMarked(aRange)) + ppObj[nDelCount++] = pObject; + } + } + + pObject = aIter.Next(); + } + + // Objekte loeschen (rueckwaerts) + + long i; + if (bRecording) + for (i=1; i<=nDelCount; i++) + AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) ); + + for (i=1; i<=nDelCount; i++) + pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() ); + + delete[] ppObj; + } + } + else + { + DBG_ERROR("pPage?"); + } + } +} + +void ScDrawLayer::CopyToClip( ScDocument* pClipDoc, SCTAB nTab, const Rectangle& rRange ) +{ + // copy everything in the specified range into the same page (sheet) in the clipboard doc + + SdrPage* pSrcPage = GetPage(static_cast<sal_uInt16>(nTab)); + if (pSrcPage) + { + ScDrawLayer* pDestModel = NULL; + SdrPage* pDestPage = NULL; + + SdrObjListIter aIter( *pSrcPage, IM_FLAT ); + SdrObject* pOldObject = aIter.Next(); + while (pOldObject) + { + Rectangle aObjRect = pOldObject->GetCurrentBoundRect(); + // do not copy internal objects (detective) and note captions + if ( rRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) ) + { + if ( !pDestModel ) + { + pDestModel = pClipDoc->GetDrawLayer(); // does the document already have a drawing layer? + if ( !pDestModel ) + { + // allocate drawing layer in clipboard document only if there are objects to copy + + pClipDoc->InitDrawLayer(); //! create contiguous pages + pDestModel = pClipDoc->GetDrawLayer(); + } + if (pDestModel) + pDestPage = pDestModel->GetPage( static_cast<sal_uInt16>(nTab) ); + } + + DBG_ASSERT( pDestPage, "no page" ); + if (pDestPage) + { + // #116235# + SdrObject* pNewObject = pOldObject->Clone(); + //SdrObject* pNewObject = pOldObject->Clone( pDestPage, pDestModel ); + pNewObject->SetModel(pDestModel); + pNewObject->SetPage(pDestPage); + + pNewObject->NbcMove(Size(0,0)); + pDestPage->InsertObject( pNewObject ); + + // no undo needed in clipboard document + // charts are not updated + } + } + + pOldObject = aIter.Next(); + } + } +} + +BOOL lcl_IsAllInRange( const ScRangeList& rRanges, const ScRange& rClipRange ) +{ + // check if every range of rRanges is completely in rClipRange + + ULONG nCount = rRanges.Count(); + for (ULONG i=0; i<nCount; i++) + { + ScRange aRange = *rRanges.GetObject(i); + if ( !rClipRange.In( aRange ) ) + { + return FALSE; // at least one range is not valid + } + } + + return TRUE; // everything is fine +} + +BOOL lcl_MoveRanges( ScRangeList& rRanges, const ScRange& rSourceRange, const ScAddress& rDestPos ) +{ + BOOL bChanged = FALSE; + + ULONG nCount = rRanges.Count(); + for (ULONG i=0; i<nCount; i++) + { + ScRange* pRange = rRanges.GetObject(i); + if ( rSourceRange.In( *pRange ) ) + { + SCsCOL nDiffX = rDestPos.Col() - (SCsCOL)rSourceRange.aStart.Col(); + SCsROW nDiffY = rDestPos.Row() - (SCsROW)rSourceRange.aStart.Row(); + SCsTAB nDiffZ = rDestPos.Tab() - (SCsTAB)rSourceRange.aStart.Tab(); + pRange->Move( nDiffX, nDiffY, nDiffZ ); + bChanged = TRUE; + } + } + + return bChanged; +} + +void ScDrawLayer::CopyFromClip( ScDrawLayer* pClipModel, SCTAB nSourceTab, const Rectangle& rSourceRange, + const ScAddress& rDestPos, const Rectangle& rDestRange ) +{ + DBG_ASSERT( pDoc, "ScDrawLayer::CopyFromClip without document" ); + if ( !pDoc ) + return; + + if (!pClipModel) + return; + + if (bDrawIsInUndo) //! can this happen? + { + DBG_ERROR("CopyFromClip, bDrawIsInUndo"); + return; + } + + BOOL bMirrorObj = ( rSourceRange.Left() < 0 && rSourceRange.Right() < 0 && + rDestRange.Left() > 0 && rDestRange.Right() > 0 ) || + ( rSourceRange.Left() > 0 && rSourceRange.Right() > 0 && + rDestRange.Left() < 0 && rDestRange.Right() < 0 ); + Rectangle aMirroredSource = rSourceRange; + if ( bMirrorObj ) + MirrorRectRTL( aMirroredSource ); + + SCTAB nDestTab = rDestPos.Tab(); + + SdrPage* pSrcPage = pClipModel->GetPage(static_cast<sal_uInt16>(nSourceTab)); + SdrPage* pDestPage = GetPage(static_cast<sal_uInt16>(nDestTab)); + DBG_ASSERT( pSrcPage && pDestPage, "draw page missing" ); + if ( !pSrcPage || !pDestPage ) + return; + + // first mirror, then move + Size aMove( rDestRange.Left() - aMirroredSource.Left(), rDestRange.Top() - aMirroredSource.Top() ); + + long nDestWidth = rDestRange.GetWidth(); + long nDestHeight = rDestRange.GetHeight(); + long nSourceWidth = rSourceRange.GetWidth(); + long nSourceHeight = rSourceRange.GetHeight(); + + long nWidthDiff = nDestWidth - nSourceWidth; + long nHeightDiff = nDestHeight - nSourceHeight; + + Fraction aHorFract(1,1); + Fraction aVerFract(1,1); + BOOL bResize = FALSE; + // sizes can differ by 1 from twips->1/100mm conversion for equal cell sizes, + // don't resize to empty size when pasting into hidden columns or rows + if ( Abs(nWidthDiff) > 1 && nDestWidth > 1 && nSourceWidth > 1 ) + { + aHorFract = Fraction( nDestWidth, nSourceWidth ); + bResize = TRUE; + } + if ( Abs(nHeightDiff) > 1 && nDestHeight > 1 && nSourceHeight > 1 ) + { + aVerFract = Fraction( nDestHeight, nSourceHeight ); + bResize = TRUE; + } + Point aRefPos = rDestRange.TopLeft(); // for resizing (after moving) + + SdrObjListIter aIter( *pSrcPage, IM_FLAT ); + SdrObject* pOldObject = aIter.Next(); + while (pOldObject) + { + Rectangle aObjRect = pOldObject->GetCurrentBoundRect(); + // do not copy internal objects (detective) and note captions + if ( rSourceRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) ) + { + // #116235# + SdrObject* pNewObject = pOldObject->Clone(); + //SdrObject* pNewObject = pOldObject->Clone( pDestPage, this ); + pNewObject->SetModel(this); + pNewObject->SetPage(pDestPage); + + if ( bMirrorObj ) + MirrorRTL( pNewObject ); // first mirror, then move + + pNewObject->NbcMove( aMove ); + if ( bResize ) + pNewObject->NbcResize( aRefPos, aHorFract, aVerFract ); + + pDestPage->InsertObject( pNewObject ); + if (bRecording) + AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) ); + + // handle chart data references (after InsertObject) + + if ( pNewObject->GetObjIdentifier() == OBJ_OLE2 ) + { + uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pNewObject)->GetObjRef(); + uno::Reference< embed::XClassifiedObject > xClassified( xIPObj, uno::UNO_QUERY ); + SvGlobalName aObjectClassName; + if ( xClassified.is() ) + { + try { + aObjectClassName = SvGlobalName( xClassified->getClassID() ); + } catch( uno::Exception& ) + { + // TODO: handle error? + } + } + + if ( xIPObj.is() && SotExchange::IsChart( aObjectClassName ) ) + { + String aNewName = ((SdrOle2Obj*)pNewObject)->GetPersistName(); + + //! need to set new DataProvider, or does Chart handle this itself? + + ScRangeListRef xRanges( new ScRangeList ); + BOOL bColHeaders = FALSE; + BOOL bRowHeaders = FALSE; + pDoc->GetOldChartParameters( aNewName, *xRanges, bColHeaders, bRowHeaders ); + + if ( xRanges->Count() > 0 ) + { + ScDocument* pClipDoc = pClipModel->GetDocument(); + + // a clipboard document and its source share the same document item pool, + // so the pointers can be compared to see if this is copy&paste within + // the same document + BOOL bSameDoc = pDoc && pClipDoc && pDoc->GetPool() == pClipDoc->GetPool(); + + BOOL bDestClip = pDoc && pDoc->IsClipboard(); + + BOOL bInSourceRange = FALSE; + ScRange aClipRange; + if ( pClipDoc ) + { + SCCOL nClipStartX; + SCROW nClipStartY; + SCCOL nClipEndX; + SCROW nClipEndY; + pClipDoc->GetClipStart( nClipStartX, nClipStartY ); + pClipDoc->GetClipArea( nClipEndX, nClipEndY, TRUE ); + nClipEndX = nClipEndX + nClipStartX; + nClipEndY += nClipStartY; // GetClipArea returns the difference + + aClipRange = ScRange( nClipStartX, nClipStartY, nSourceTab, + nClipEndX, nClipEndY, nSourceTab ); + + bInSourceRange = lcl_IsAllInRange( *xRanges, aClipRange ); + } + + // always lose references when pasting into a clipboard document (transpose) + if ( ( bInSourceRange || bSameDoc ) && !bDestClip ) + { + if ( bInSourceRange ) + { + if ( rDestPos != aClipRange.aStart ) + { + // update the data ranges to the new (copied) position + ScRangeListRef xNewRanges = new ScRangeList( *xRanges ); + if ( lcl_MoveRanges( *xNewRanges, aClipRange, rDestPos ) ) + { + pDoc->UpdateChartArea( aNewName, xNewRanges, bColHeaders, bRowHeaders, FALSE ); + } + } + } + else + { + // leave the ranges unchanged + } + } + else + { + // pasting into a new document without the complete source data + // -> break connection to source data + + // (see ScDocument::UpdateChartListenerCollection, PastingDrawFromOtherDoc) + + //! need chart interface to switch to own data + } + } + } + } + } + + pOldObject = aIter.Next(); + } +} + +void ScDrawLayer::MirrorRTL( SdrObject* pObj ) +{ + UINT16 nIdent = pObj->GetObjIdentifier(); + + // don't mirror OLE or graphics, otherwise ask the object + // if it can be mirrored + BOOL bCanMirror = ( nIdent != OBJ_GRAF && nIdent != OBJ_OLE2 ); + if (bCanMirror) + { + SdrObjTransformInfoRec aInfo; + pObj->TakeObjInfo( aInfo ); + bCanMirror = aInfo.bMirror90Allowed; + } + + if (bCanMirror) + { + Point aRef1( 0, 0 ); + Point aRef2( 0, 1 ); + if (bRecording) + AddCalcUndo( new SdrUndoGeoObj( *pObj ) ); + pObj->Mirror( aRef1, aRef2 ); + } + else + { + // Move instead of mirroring: + // New start position is negative of old end position + // -> move by sum of start and end position + Rectangle aObjRect = pObj->GetLogicRect(); + Size aMoveSize( -(aObjRect.Left() + aObjRect.Right()), 0 ); + if (bRecording) + AddCalcUndo( new SdrUndoMoveObj( *pObj, aMoveSize ) ); + pObj->Move( aMoveSize ); + } +} + +// static +void ScDrawLayer::MirrorRectRTL( Rectangle& rRect ) +{ + // mirror and swap left/right + long nTemp = rRect.Left(); + rRect.Left() = -rRect.Right(); + rRect.Right() = -nTemp; +} + +Rectangle ScDrawLayer::GetCellRect( ScDocument& rDoc, const ScAddress& rPos, bool bMergedCell ) +{ + Rectangle aCellRect; + DBG_ASSERT( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ), "ScDrawLayer::GetCellRect - invalid cell address" ); + if( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ) ) + { + // find top left position of passed cell address + Point aTopLeft; + for( SCCOL nCol = 0; nCol < rPos.Col(); ++nCol ) + aTopLeft.X() += rDoc.GetColWidth( nCol, rPos.Tab() ); + if( rPos.Row() > 0 ) + aTopLeft.Y() += rDoc.FastGetRowHeight( 0, rPos.Row() - 1, rPos.Tab() ); + + // find bottom-right position of passed cell address + ScAddress aEndPos = rPos; + if( bMergedCell ) + { + const ScMergeAttr* pMerge = static_cast< const ScMergeAttr* >( rDoc.GetAttr( rPos.Col(), rPos.Row(), rPos.Tab(), ATTR_MERGE ) ); + if( pMerge->GetColMerge() > 1 ) + aEndPos.IncCol( pMerge->GetColMerge() - 1 ); + if( pMerge->GetRowMerge() > 1 ) + aEndPos.IncRow( pMerge->GetRowMerge() - 1 ); + } + Point aBotRight = aTopLeft; + for( SCCOL nCol = rPos.Col(); nCol <= aEndPos.Col(); ++nCol ) + aBotRight.X() += rDoc.GetColWidth( nCol, rPos.Tab() ); + aBotRight.Y() += rDoc.FastGetRowHeight( rPos.Row(), aEndPos.Row(), rPos.Tab() ); + + // twips -> 1/100 mm + aTopLeft.X() = static_cast< long >( aTopLeft.X() * HMM_PER_TWIPS ); + aTopLeft.Y() = static_cast< long >( aTopLeft.Y() * HMM_PER_TWIPS ); + aBotRight.X() = static_cast< long >( aBotRight.X() * HMM_PER_TWIPS ); + aBotRight.Y() = static_cast< long >( aBotRight.Y() * HMM_PER_TWIPS ); + + aCellRect = Rectangle( aTopLeft, aBotRight ); + if( rDoc.IsNegativePage( rPos.Tab() ) ) + MirrorRectRTL( aCellRect ); + } + return aCellRect; +} + +// static +String ScDrawLayer::GetVisibleName( SdrObject* pObj ) +{ + String aName = pObj->GetName(); + if ( pObj->GetObjIdentifier() == OBJ_OLE2 ) + { + // #95575# For OLE, the user defined name (GetName) is used + // if it's not empty (accepting possibly duplicate names), + // otherwise the persist name is used so every object appears + // in the Navigator at all. + + if ( !aName.Len() ) + aName = static_cast<SdrOle2Obj*>(pObj)->GetPersistName(); + } + return aName; +} + +inline sal_Bool IsNamedObject( SdrObject* pObj, const String& rName ) +{ + // TRUE if rName is the object's Name or PersistName + // (used to find a named object) + + return ( pObj->GetName() == rName || + ( pObj->GetObjIdentifier() == OBJ_OLE2 && + static_cast<SdrOle2Obj*>(pObj)->GetPersistName() == rName ) ); +} + +SdrObject* ScDrawLayer::GetNamedObject( const String& rName, USHORT nId, SCTAB& rFoundTab ) const +{ + sal_uInt16 nTabCount = GetPageCount(); + for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++) + { + const SdrPage* pPage = GetPage(nTab); + DBG_ASSERT(pPage,"Page ?"); + if (pPage) + { + SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( nId == 0 || pObject->GetObjIdentifier() == nId ) + if ( IsNamedObject( pObject, rName ) ) + { + rFoundTab = static_cast<SCTAB>(nTab); + return pObject; + } + + pObject = aIter.Next(); + } + } + } + + return NULL; +} + +String ScDrawLayer::GetNewGraphicName( long* pnCounter ) const +{ + String aBase = ScGlobal::GetRscString(STR_GRAPHICNAME); + aBase += ' '; + + BOOL bThere = TRUE; + String aGraphicName; + SCTAB nDummy; + long nId = pnCounter ? *pnCounter : 0; + while (bThere) + { + ++nId; + aGraphicName = aBase; + aGraphicName += String::CreateFromInt32( nId ); + bThere = ( GetNamedObject( aGraphicName, 0, nDummy ) != NULL ); + } + + if ( pnCounter ) + *pnCounter = nId; + + return aGraphicName; +} + +void ScDrawLayer::EnsureGraphicNames() +{ + // make sure all graphic objects have names (after Excel import etc.) + + sal_uInt16 nTabCount = GetPageCount(); + for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++) + { + SdrPage* pPage = GetPage(nTab); + DBG_ASSERT(pPage,"Page ?"); + if (pPage) + { + SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS ); + SdrObject* pObject = aIter.Next(); + + /* #101799# The index passed to GetNewGraphicName() will be set to + the used index in each call. This prevents the repeated search + for all names from 1 to current index. */ + long nCounter = 0; + + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_GRAF && pObject->GetName().Len() == 0 ) + pObject->SetName( GetNewGraphicName( &nCounter ) ); + + pObject = aIter.Next(); + } + } + } +} + +void ScDrawLayer::SetAnchor( SdrObject* pObj, ScAnchorType eType ) +{ + ScAnchorType eOldAnchorType = GetAnchor( pObj ); + + // Ein an der Seite verankertes Objekt zeichnet sich durch eine Anker-Pos + // von (0,1) aus. Das ist ein shabby Trick, der aber funktioniert! + Point aAnchor( 0, eType == SCA_PAGE ? 1 : 0 ); + pObj->SetAnchorPos( aAnchor ); + + if ( eOldAnchorType != eType ) + pObj->notifyShapePropertyChange( ::svx::eSpreadsheetAnchor ); +} + +ScAnchorType ScDrawLayer::GetAnchor( const SdrObject* pObj ) +{ + Point aAnchor( pObj->GetAnchorPos() ); + return ( aAnchor.Y() != 0 ) ? SCA_PAGE : SCA_CELL; +} + +ScDrawObjData* ScDrawLayer::GetObjData( SdrObject* pObj, BOOL bCreate ) // static +{ + USHORT nCount = pObj ? pObj->GetUserDataCount() : 0; + for( USHORT i = 0; i < nCount; i++ ) + { + SdrObjUserData* pData = pObj->GetUserData( i ); + if( pData && pData->GetInventor() == SC_DRAWLAYER + && pData->GetId() == SC_UD_OBJDATA ) + return (ScDrawObjData*) pData; + } + if( pObj && bCreate ) + { + ScDrawObjData* pData = new ScDrawObjData; + pObj->InsertUserData( pData, 0 ); + return pData; + } + return 0; +} + +ScDrawObjData* ScDrawLayer::GetObjDataTab( SdrObject* pObj, SCTAB nTab ) // static +{ + ScDrawObjData* pData = GetObjData( pObj ); + if ( pData ) + { + if ( pData->maStart.IsValid() ) + pData->maStart.SetTab( nTab ); + if ( pData->maEnd.IsValid() ) + pData->maEnd.SetTab( nTab ); + } + return pData; +} + +bool ScDrawLayer::IsNoteCaption( SdrObject* pObj ) +{ + ScDrawObjData* pData = pObj ? GetObjData( pObj ) : 0; + return pData && pData->mbNote; +} + +ScDrawObjData* ScDrawLayer::GetNoteCaptionData( SdrObject* pObj, SCTAB nTab ) +{ + ScDrawObjData* pData = pObj ? GetObjDataTab( pObj, nTab ) : 0; + return (pData && pData->mbNote) ? pData : 0; +} + +ScIMapInfo* ScDrawLayer::GetIMapInfo( SdrObject* pObj ) // static +{ + USHORT nCount = pObj->GetUserDataCount(); + for( USHORT i = 0; i < nCount; i++ ) + { + SdrObjUserData* pData = pObj->GetUserData( i ); + if( pData && pData->GetInventor() == SC_DRAWLAYER + && pData->GetId() == SC_UD_IMAPDATA ) + return (ScIMapInfo*) pData; + } + return NULL; +} + +// static: +IMapObject* ScDrawLayer::GetHitIMapObject( SdrObject* pObj, + const Point& rWinPoint, const Window& rCmpWnd ) +{ + const MapMode aMap100( MAP_100TH_MM ); + MapMode aWndMode = rCmpWnd.GetMapMode(); + Point aRelPoint( rCmpWnd.LogicToLogic( rWinPoint, &aWndMode, &aMap100 ) ); + Rectangle aLogRect = rCmpWnd.LogicToLogic( pObj->GetLogicRect(), &aWndMode, &aMap100 ); + ScIMapInfo* pIMapInfo = GetIMapInfo( pObj ); + IMapObject* pIMapObj = NULL; + + if ( pIMapInfo ) + { + Size aGraphSize; + ImageMap& rImageMap = (ImageMap&) pIMapInfo->GetImageMap(); + Graphic aGraphic; + BOOL bObjSupported = FALSE; + + if ( pObj->ISA( SdrGrafObj ) ) // einfaches Grafik-Objekt + { + const SdrGrafObj* pGrafObj = (const SdrGrafObj*) pObj; + const GeoStat& rGeo = pGrafObj->GetGeoStat(); + const Graphic& rGraphic = pGrafObj->GetGraphic(); + + // Drehung rueckgaengig + if ( rGeo.nDrehWink ) + RotatePoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nSin, rGeo.nCos ); + + // Spiegelung rueckgaengig + if ( ( (const SdrGrafObjGeoData*) pGrafObj->GetGeoData() )->bMirrored ) + aRelPoint.X() = aLogRect.Right() + aLogRect.Left() - aRelPoint.X(); + + // ggf. Unshear: + if ( rGeo.nShearWink ) + ShearPoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nTan ); + + + if ( rGraphic.GetPrefMapMode().GetMapUnit() == MAP_PIXEL ) + aGraphSize = rCmpWnd.PixelToLogic( rGraphic.GetPrefSize(), + aMap100 ); + else + aGraphSize = OutputDevice::LogicToLogic( rGraphic.GetPrefSize(), + rGraphic.GetPrefMapMode(), + aMap100 ); + + bObjSupported = TRUE; + } + else if ( pObj->ISA( SdrOle2Obj ) ) // OLE-Objekt + { + // TODO/LEAN: working with visual area needs running state + aGraphSize = ((SdrOle2Obj*)pObj)->GetOrigObjSize(); + bObjSupported = TRUE; + } + + // hat alles geklappt, dann HitTest ausfuehren + if ( bObjSupported ) + { + // relativen Mauspunkt berechnen + aRelPoint -= aLogRect.TopLeft(); + pIMapObj = rImageMap.GetHitIMapObject( aGraphSize, aLogRect.GetSize(), aRelPoint ); + } + } + + return pIMapObj; +} + +ScMacroInfo* ScDrawLayer::GetMacroInfo( SdrObject* pObj, BOOL bCreate ) // static +{ + USHORT nCount = pObj->GetUserDataCount(); + for( USHORT i = 0; i < nCount; i++ ) + { + SdrObjUserData* pData = pObj->GetUserData( i ); + if( pData && pData->GetInventor() == SC_DRAWLAYER + && pData->GetId() == SC_UD_MACRODATA ) + return (ScMacroInfo*) pData; + } + if ( bCreate ) + { + ScMacroInfo* pData = new ScMacroInfo; + pObj->InsertUserData( pData, 0 ); + return pData; + } + return 0; +} + +void ScDrawLayer::SetGlobalDrawPersist(SfxObjectShell* pPersist) // static +{ + DBG_ASSERT(!pGlobalDrawPersist,"SetGlobalDrawPersist mehrfach"); + pGlobalDrawPersist = pPersist; +} + +void __EXPORT ScDrawLayer::SetChanged( sal_Bool bFlg /* = sal_True */ ) +{ + if ( bFlg && pDoc ) + pDoc->SetChartListenerCollectionNeedsUpdate( TRUE ); + FmFormModel::SetChanged( bFlg ); +} + +SvStream* __EXPORT ScDrawLayer::GetDocumentStream(SdrDocumentStreamInfo& rStreamInfo) const +{ + DBG_ASSERT( pDoc, "ScDrawLayer::GetDocumentStream without document" ); + if ( !pDoc ) + return NULL; + + uno::Reference< embed::XStorage > xStorage = pDoc->GetDocumentShell() ? + pDoc->GetDocumentShell()->GetStorage() : + NULL; + SvStream* pRet = NULL; + + if( xStorage.is() ) + { + if( rStreamInfo.maUserData.Len() && + ( rStreamInfo.maUserData.GetToken( 0, ':' ) == + String( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package" ) ) ) ) + { + const String aPicturePath( rStreamInfo.maUserData.GetToken( 1, ':' ) ); + + // graphic from picture stream in picture storage in XML package + if( aPicturePath.GetTokenCount( '/' ) == 2 ) + { + const String aPictureStreamName( aPicturePath.GetToken( 1, '/' ) ); + const String aPictureStorageName( aPicturePath.GetToken( 0, '/' ) ); + + try { + if ( xStorage->isStorageElement( aPictureStorageName ) ) + { + uno::Reference< embed::XStorage > xPictureStorage = + xStorage->openStorageElement( aPictureStorageName, embed::ElementModes::READ ); + + if( xPictureStorage.is() && + xPictureStorage->isStreamElement( aPictureStreamName ) ) + { + uno::Reference< io::XStream > xStream = + xPictureStorage->openStreamElement( aPictureStreamName, embed::ElementModes::READ ); + if ( xStream.is() ) + pRet = ::utl::UcbStreamHelper::CreateStream( xStream ); + } + } + } + catch( uno::Exception& ) + { + // TODO: error handling + } + } + } + // the following code seems to be related to binary format +//REMOVE else +//REMOVE { +//REMOVE pRet = pStor->OpenStream( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_SCSTREAM)), +//REMOVE STREAM_READ | STREAM_WRITE | STREAM_TRUNC ); +//REMOVE +//REMOVE if( pRet ) +//REMOVE { +//REMOVE pRet->SetVersion( pStor->GetVersion() ); +//REMOVE pRet->SetKey( pStor->GetKey() ); +//REMOVE } +//REMOVE } + + rStreamInfo.mbDeleteAfterUse = ( pRet != NULL ); + } + + return pRet; +} + +//REMOVE void ScDrawLayer::ReleasePictureStorage() +//REMOVE { +//REMOVE xPictureStorage.Clear(); +//REMOVE } + +SdrLayerID __EXPORT ScDrawLayer::GetControlExportLayerId( const SdrObject & ) const +{ + // Layer fuer Export von Form-Controls in Versionen vor 5.0 - immer SC_LAYER_FRONT + return SC_LAYER_FRONT; +} + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ScDrawLayer::createUnoModel() +{ + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xRet; + if( pDoc && pDoc->GetDocumentShell() ) + xRet = pDoc->GetDocumentShell()->GetModel(); + + return xRet; +} |