merge the formfield patch from ooo-build
[ooovba.git] / sc / source / core / data / drwlayer.cxx
blob03c48f53893f03f090abda164ccce86860831304
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: drwlayer.cxx,v $
10 * $Revision: 1.55.128.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
33 #include <com/sun/star/uno/Reference.hxx>
34 #include <com/sun/star/embed/XEmbeddedObject.hpp>
35 #include <com/sun/star/embed/XVisualObject.hpp>
36 #include <com/sun/star/embed/XClassifiedObject.hpp>
37 #include <com/sun/star/embed/XComponentSupplier.hpp>
38 #include <com/sun/star/embed/EmbedStates.hpp>
39 #include <com/sun/star/embed/ElementModes.hpp>
40 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
41 #include <com/sun/star/datatransfer/XTransferable.hpp>
43 // INCLUDE ---------------------------------------------------------------
45 #include "scitems.hxx"
46 #include <svx/eeitem.hxx>
47 #include <svx/frmdiritem.hxx>
48 #include <sot/exchange.hxx>
49 #include <svx/objfac3d.hxx>
50 #include <svx/xtable.hxx>
51 #include <svx/svdoutl.hxx>
52 #include <svx/svditer.hxx>
53 #include <svx/svdocapt.hxx>
54 #include <svx/svdocirc.hxx>
55 #include <svx/svdoedge.hxx>
56 #include <svx/svdograf.hxx>
57 #include <svx/svdoole2.hxx>
58 #include <svx/svdundo.hxx>
59 #include <svx/unolingu.hxx>
60 #include <svx/drawitem.hxx>
61 #include <svx/fhgtitem.hxx>
62 #include <svx/scriptspaceitem.hxx>
63 #include <svx/shapepropertynotifier.hxx>
64 #include <sfx2/viewsh.hxx>
65 #include <sfx2/docfile.hxx>
66 #include <sot/storage.hxx>
67 #include <svtools/pathoptions.hxx>
68 #include <svtools/itempool.hxx>
69 #include <vcl/virdev.hxx>
70 #include <vcl/svapp.hxx>
71 #include <unotools/ucbstreamhelper.hxx>
73 #include "drwlayer.hxx"
74 #include "drawpage.hxx"
75 #include "global.hxx"
76 #include "document.hxx"
77 #include "rechead.hxx"
78 #include "userdat.hxx"
79 #include "markdata.hxx"
80 #include "globstr.hrc"
81 #include "scmod.hxx"
82 #include "chartarr.hxx"
83 #include "postit.hxx"
84 #include "attrib.hxx"
86 #ifndef _SV_FIELD_HXX //autogen
87 #include <vcl/field.hxx>
88 #endif
90 #define DET_ARROW_OFFSET 1000
92 // Abstand zur naechsten Zelle beim Loeschen (bShrink), damit der Anker
93 // immer an der richtigen Zelle angezeigt wird
94 //#define SHRINK_DIST 3
95 // und noch etwas mehr, damit das Objekt auch sichtbar in der Zelle liegt
96 #define SHRINK_DIST 25
98 #define SHRINK_DIST_TWIPS 15
100 using namespace ::com::sun::star;
102 // STATIC DATA -----------------------------------------------------------
104 TYPEINIT1(ScTabDeletedHint, SfxHint);
105 TYPEINIT1(ScTabSizeChangedHint, SfxHint);
107 static ScDrawObjFactory* pFac = NULL;
108 static E3dObjFactory* pF3d = NULL;
109 static USHORT nInst = 0;
111 SfxObjectShell* ScDrawLayer::pGlobalDrawPersist = NULL;
112 //REMOVE SvPersist* ScDrawLayer::pGlobalDrawPersist = NULL;
114 BOOL bDrawIsInUndo = FALSE; //! Member
116 // -----------------------------------------------------------------------
118 ScUndoObjData::ScUndoObjData( SdrObject* pObjP, const ScAddress& rOS, const ScAddress& rOE,
119 const ScAddress& rNS, const ScAddress& rNE ) :
120 SdrUndoObj( *pObjP ),
121 aOldStt( rOS ),
122 aOldEnd( rOE ),
123 aNewStt( rNS ),
124 aNewEnd( rNE )
128 __EXPORT ScUndoObjData::~ScUndoObjData()
132 void ScUndoObjData::Undo()
134 ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj );
135 DBG_ASSERT(pData,"ScUndoObjData: Daten nicht da");
136 if (pData)
138 pData->maStart = aOldStt;
139 pData->maEnd = aOldEnd;
143 void __EXPORT ScUndoObjData::Redo()
145 ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj );
146 DBG_ASSERT(pData,"ScUndoObjData: Daten nicht da");
147 if (pData)
149 pData->maStart = aNewStt;
150 pData->maEnd = aNewEnd;
154 // -----------------------------------------------------------------------
156 ScTabDeletedHint::ScTabDeletedHint( SCTAB nTabNo ) :
157 nTab( nTabNo )
161 __EXPORT ScTabDeletedHint::~ScTabDeletedHint()
165 ScTabSizeChangedHint::ScTabSizeChangedHint( SCTAB nTabNo ) :
166 nTab( nTabNo )
170 __EXPORT ScTabSizeChangedHint::~ScTabSizeChangedHint()
174 // -----------------------------------------------------------------------
176 #define MAXMM 10000000
178 inline long TwipsToHmm (long nVal)
180 return static_cast< long >( MetricField::ConvertDoubleValue (static_cast<sal_Int64>(nVal), 0, 0,
181 FUNIT_TWIP, FUNIT_100TH_MM) );
184 inline long HmmToTwips (long nVal)
186 return static_cast< long > ( MetricField::ConvertDoubleValue (static_cast<sal_Int64>(nVal), 0, 0,
187 FUNIT_100TH_MM, FUNIT_TWIP) );
190 inline void TwipsToMM( long& nVal )
192 nVal = TwipsToHmm (nVal);
195 inline void ReverseTwipsToMM( long& nVal )
197 nVal = HmmToTwips (nVal);
200 void lcl_TwipsToMM( Point& rPoint )
202 TwipsToMM( rPoint.X() );
203 TwipsToMM( rPoint.Y() );
206 void lcl_ReverseTwipsToMM( Point& rPoint )
208 ReverseTwipsToMM( rPoint.X() );
209 ReverseTwipsToMM( rPoint.Y() );
212 void lcl_ReverseTwipsToMM( Rectangle& rRect )
214 ReverseTwipsToMM( rRect.Left() );
215 ReverseTwipsToMM( rRect.Right() );
216 ReverseTwipsToMM( rRect.Top() );
217 ReverseTwipsToMM( rRect.Bottom() );
220 // -----------------------------------------------------------------------
223 ScDrawLayer::ScDrawLayer( ScDocument* pDocument, const String& rName ) :
224 FmFormModel( SvtPathOptions().GetPalettePath(),
225 NULL, // SfxItemPool* Pool
226 pGlobalDrawPersist ?
227 pGlobalDrawPersist :
228 ( pDocument ? pDocument->GetDocumentShell() : NULL ),
229 TRUE ), // bUseExtColorTable (is set below)
230 aName( rName ),
231 pDoc( pDocument ),
232 pUndoGroup( NULL ),
233 bRecording( FALSE ),
234 bAdjustEnabled( TRUE ),
235 bHyphenatorSet( FALSE )
237 pGlobalDrawPersist = NULL; // nur einmal benutzen
239 SfxObjectShell* pObjSh = pDocument ? pDocument->GetDocumentShell() : NULL;
240 if ( pObjSh )
242 SetObjectShell( pObjSh );
244 // set color table
245 SvxColorTableItem* pColItem = (SvxColorTableItem*) pObjSh->GetItem( SID_COLOR_TABLE );
246 XColorTable* pXCol = pColItem ? pColItem->GetColorTable() : XColorTable::GetStdColorTable();
247 SetColorTable( pXCol );
249 else
250 SetColorTable( XColorTable::GetStdColorTable() );
252 SetSwapGraphics(TRUE);
253 // SetSwapAsynchron(TRUE); // an der View
255 SetScaleUnit(MAP_100TH_MM);
256 SfxItemPool& rPool = GetItemPool();
257 rPool.SetDefaultMetric(SFX_MAPUNIT_100TH_MM);
258 SvxFrameDirectionItem aModeItem( FRMDIR_ENVIRONMENT, EE_PARA_WRITINGDIR );
259 rPool.SetPoolDefaultItem( aModeItem );
261 // #i33700#
262 // Set shadow distance defaults as PoolDefaultItems. Details see bug.
263 rPool.SetPoolDefaultItem(SdrShadowXDistItem(300));
264 rPool.SetPoolDefaultItem(SdrShadowYDistItem(300));
266 // #111216# default for script spacing depends on locale, see SdDrawDocument ctor in sd
267 LanguageType eOfficeLanguage = Application::GetSettings().GetLanguage();
268 if ( eOfficeLanguage == LANGUAGE_KOREAN || eOfficeLanguage == LANGUAGE_KOREAN_JOHAB ||
269 eOfficeLanguage == LANGUAGE_JAPANESE )
271 // secondary is edit engine pool
272 rPool.GetSecondaryPool()->SetPoolDefaultItem( SvxScriptSpaceItem( FALSE, EE_PARA_ASIANCJKSPACING ) );
275 rPool.FreezeIdRanges(); // the pool is also used directly
277 SdrLayerAdmin& rAdmin = GetLayerAdmin();
278 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("vorne")), SC_LAYER_FRONT);
279 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("hinten")), SC_LAYER_BACK);
280 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("intern")), SC_LAYER_INTERN);
281 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Controls")), SC_LAYER_CONTROLS);
282 rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("hidden")), SC_LAYER_HIDDEN);
283 // "Controls" is new - must also be created when loading
285 // Link fuer URL-Fields setzen
286 ScModule* pScMod = SC_MOD();
287 Outliner& rOutliner = GetDrawOutliner();
288 rOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) );
290 Outliner& rHitOutliner = GetHitTestOutliner();
291 rHitOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) );
293 // #95129# SJ: set FontHeight pool defaults without changing static SdrEngineDefaults
294 SfxItemPool* pOutlinerPool = rOutliner.GetEditTextObjectPool();
295 if ( pOutlinerPool )
296 pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt
297 SfxItemPool* pHitOutlinerPool = rHitOutliner.GetEditTextObjectPool();
298 if ( pHitOutlinerPool )
299 pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt
301 // URL-Buttons haben keinen Handler mehr, machen alles selber
303 if( !nInst++ )
305 pFac = new ScDrawObjFactory;
306 pF3d = new E3dObjFactory;
310 __EXPORT ScDrawLayer::~ScDrawLayer()
312 Broadcast(SdrHint(HINT_MODELCLEARED));
314 // #116168#
315 //Clear();
316 ClearModel(sal_True);
318 delete pUndoGroup;
319 if( !--nInst )
321 delete pFac, pFac = NULL;
322 delete pF3d, pF3d = NULL;
326 void ScDrawLayer::UseHyphenator()
328 if (!bHyphenatorSet)
330 com::sun::star::uno::Reference< com::sun::star::linguistic2::XHyphenator >
331 xHyphenator = LinguMgr::GetHyphenator();
333 GetDrawOutliner().SetHyphenator( xHyphenator );
334 GetHitTestOutliner().SetHyphenator( xHyphenator );
336 bHyphenatorSet = TRUE;
340 SdrPage* __EXPORT ScDrawLayer::AllocPage(FASTBOOL bMasterPage)
342 // don't create basic until it is needed
343 StarBASIC* pBasic = NULL;
344 ScDrawPage* pPage = new ScDrawPage( *this, pBasic, sal::static_int_cast<BOOL>(bMasterPage) );
345 return pPage;
348 BOOL ScDrawLayer::HasObjects() const
350 BOOL bFound = FALSE;
352 USHORT nCount = GetPageCount();
353 for (USHORT i=0; i<nCount && !bFound; i++)
354 if (GetPage(i)->GetObjCount())
355 bFound = TRUE;
357 return bFound;
360 void ScDrawLayer::UpdateBasic()
362 // don't create basic until it is needed
363 //! remove this method?
366 SdrModel* __EXPORT ScDrawLayer::AllocModel() const
368 // #103849# Allocated model (for clipboard etc) must not have a pointer
369 // to the original model's document, pass NULL as document:
371 return new ScDrawLayer( NULL, aName );
374 Window* __EXPORT ScDrawLayer::GetCurDocViewWin()
376 DBG_ASSERT( pDoc, "ScDrawLayer::GetCurDocViewWin without document" );
377 if ( !pDoc )
378 return NULL;
380 SfxViewShell* pViewSh = SfxViewShell::Current();
381 SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
383 if (pViewSh && pViewSh->GetObjectShell() == pObjSh)
384 return pViewSh->GetWindow();
386 return NULL;
389 BOOL ScDrawLayer::ScAddPage( SCTAB nTab )
391 if (bDrawIsInUndo)
392 return FALSE; // not inserted
394 ScDrawPage* pPage = (ScDrawPage*)AllocPage( FALSE );
395 InsertPage(pPage, static_cast<sal_uInt16>(nTab));
396 if (bRecording)
397 AddCalcUndo(new SdrUndoNewPage(*pPage));
399 return TRUE; // inserted
402 void ScDrawLayer::ScRemovePage( SCTAB nTab )
404 if (bDrawIsInUndo)
405 return;
407 Broadcast( ScTabDeletedHint( nTab ) );
408 if (bRecording)
410 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
411 AddCalcUndo(new SdrUndoDelPage(*pPage)); // Undo-Action wird Owner der Page
412 RemovePage( static_cast<sal_uInt16>(nTab) ); // nur austragen, nicht loeschen
414 else
415 DeletePage( static_cast<sal_uInt16>(nTab) ); // einfach weg damit
418 void ScDrawLayer::ScRenamePage( SCTAB nTab, const String& rNewName )
420 ScDrawPage* pPage = (ScDrawPage*) GetPage(static_cast<sal_uInt16>(nTab));
421 if (pPage)
422 pPage->SetName(rNewName);
425 void ScDrawLayer::ScMovePage( USHORT nOldPos, USHORT nNewPos )
427 MovePage( nOldPos, nNewPos );
430 void ScDrawLayer::ScCopyPage( USHORT nOldPos, USHORT nNewPos, BOOL bAlloc )
432 //! remove argument bAlloc (always FALSE)
434 if (bDrawIsInUndo)
435 return;
437 SdrPage* pOldPage = GetPage(nOldPos);
438 SdrPage* pNewPage = bAlloc ? AllocPage(FALSE) : GetPage(nNewPos);
440 // kopieren
442 if (pOldPage && pNewPage)
444 SdrObjListIter aIter( *pOldPage, IM_FLAT );
445 SdrObject* pOldObject = aIter.Next();
446 while (pOldObject)
448 // #116235#
449 SdrObject* pNewObject = pOldObject->Clone();
450 //SdrObject* pNewObject = pOldObject->Clone( pNewPage, this );
451 pNewObject->SetModel(this);
452 pNewObject->SetPage(pNewPage);
454 pNewObject->NbcMove(Size(0,0));
455 pNewPage->InsertObject( pNewObject );
456 if (bRecording)
457 AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) );
459 pOldObject = aIter.Next();
463 if (bAlloc)
464 InsertPage(pNewPage, nNewPos);
467 inline BOOL IsInBlock( const ScAddress& rPos, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2 )
469 return rPos.Col() >= nCol1 && rPos.Col() <= nCol2 &&
470 rPos.Row() >= nRow1 && rPos.Row() <= nRow2;
473 void ScDrawLayer::MoveCells( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2,
474 SCsCOL nDx,SCsROW nDy )
476 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
477 DBG_ASSERT(pPage,"Page nicht gefunden");
478 if (!pPage)
479 return;
481 BOOL bNegativePage = pDoc && pDoc->IsNegativePage( nTab );
483 ULONG nCount = pPage->GetObjCount();
484 for ( ULONG i = 0; i < nCount; i++ )
486 SdrObject* pObj = pPage->GetObj( i );
487 ScDrawObjData* pData = GetObjDataTab( pObj, nTab );
488 if( pData )
490 const ScAddress aOldStt = pData->maStart;
491 const ScAddress aOldEnd = pData->maEnd;
492 BOOL bChange = FALSE;
493 if ( aOldStt.IsValid() && IsInBlock( aOldStt, nCol1,nRow1, nCol2,nRow2 ) )
495 pData->maStart.IncCol( nDx );
496 pData->maStart.IncRow( nDy );
497 bChange = TRUE;
499 if ( aOldEnd.IsValid() && IsInBlock( aOldEnd, nCol1,nRow1, nCol2,nRow2 ) )
501 pData->maEnd.IncCol( nDx );
502 pData->maEnd.IncRow( nDy );
503 bChange = TRUE;
505 if (bChange)
507 if ( pObj->ISA( SdrRectObj ) && pData->maStart.IsValid() && pData->maEnd.IsValid() )
508 pData->maStart.PutInOrder( pData->maEnd );
509 AddCalcUndo( new ScUndoObjData( pObj, aOldStt, aOldEnd, pData->maStart, pData->maEnd ) );
510 RecalcPos( pObj, *pData, bNegativePage );
516 void ScDrawLayer::SetPageSize( USHORT nPageNo, const Size& rSize )
518 SdrPage* pPage = GetPage(nPageNo);
519 if (pPage)
521 if ( rSize != pPage->GetSize() )
523 pPage->SetSize( rSize );
524 Broadcast( ScTabSizeChangedHint( static_cast<SCTAB>(nPageNo) ) ); // SetWorkArea() an den Views
527 // Detektivlinien umsetzen (an neue Hoehen/Breiten anpassen)
528 // auch wenn Groesse gleich geblieben ist
529 // (einzelne Zeilen/Spalten koennen geaendert sein)
531 BOOL bNegativePage = pDoc && pDoc->IsNegativePage( static_cast<SCTAB>(nPageNo) );
533 ULONG nCount = pPage->GetObjCount();
534 for ( ULONG i = 0; i < nCount; i++ )
536 SdrObject* pObj = pPage->GetObj( i );
537 ScDrawObjData* pData = GetObjDataTab( pObj, static_cast<SCTAB>(nPageNo) );
538 if( pData )
539 RecalcPos( pObj, *pData, bNegativePage );
544 void ScDrawLayer::RecalcPos( SdrObject* pObj, const ScDrawObjData& rData, bool bNegativePage )
546 DBG_ASSERT( pDoc, "ScDrawLayer::RecalcPos - missing document" );
547 if( !pDoc )
548 return;
550 /* TODO CleanUp: Updating note position works just by chance currently...
551 When inserting rows/columns, this function is called after the
552 insertion, and the note is located at the new position contained in the
553 passed ScDrawObjData already. But when deleting rows/columns, this
554 function is called *before* the deletion, so the note is still at the
555 old cell position, and ScDocument::GetNote() will fail to get the note
556 or will get another note. But after the rows/columns are deleted, a
557 call to ScDrawLayer::SetPageSize() will call this function again, and
558 now the note is at the expected position in the document. */
559 if( rData.mbNote )
561 DBG_ASSERT( rData.maStart.IsValid(), "ScDrawLayer::RecalcPos - invalid position for cell note" );
562 /* When inside an undo action, there may be pending note captions
563 where cell note is already deleted. The caption will be deleted
564 later with drawing undo. */
565 if( ScPostIt* pNote = pDoc->GetNote( rData.maStart ) )
566 pNote->UpdateCaptionPos( rData.maStart );
567 return;
570 bool bValid1 = rData.maStart.IsValid();
571 SCCOL nCol1 = rData.maStart.Col();
572 SCROW nRow1 = rData.maStart.Row();
573 SCTAB nTab1 = rData.maStart.Tab();
574 bool bValid2 = rData.maEnd.IsValid();
575 SCCOL nCol2 = rData.maEnd.Col();
576 SCROW nRow2 = rData.maEnd.Row();
577 SCTAB nTab2 = rData.maEnd.Tab();
579 // validation circle
580 bool bCircle = pObj->ISA( SdrCircObj );
581 // detective arrow
582 bool bArrow = pObj->IsPolyObj() && (pObj->GetPointCount() == 2);
584 if( bCircle )
586 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
587 TwipsToMM( aPos.X() );
588 TwipsToMM( aPos.Y() );
590 // Berechnung und Werte wie in detfunc.cxx
592 Size aSize( (long)( TwipsToHmm( pDoc->GetColWidth( nCol1, nTab1) ) ),
593 (long)( TwipsToHmm( pDoc->GetRowHeight( nRow1, nTab1) ) ) );
594 Rectangle aRect( aPos, aSize );
595 aRect.Left() -= 250;
596 aRect.Right() += 250;
597 aRect.Top() -= 70;
598 aRect.Bottom() += 70;
599 if ( bNegativePage )
600 MirrorRectRTL( aRect );
602 if ( pObj->GetLogicRect() != aRect )
604 if (bRecording)
605 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
606 pObj->SetLogicRect(aRect);
609 else if( bArrow )
611 //! nicht mehrere Undos fuer ein Objekt erzeugen (hinteres kann dann weggelassen werden)
613 SCCOL nLastCol;
614 SCROW nLastRow;
615 if( bValid1 )
617 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
618 if (!pDoc->ColHidden(nCol1, nTab1, nLastCol))
619 aPos.X() += pDoc->GetColWidth( nCol1, nTab1 ) / 4;
620 if (!pDoc->RowHidden(nRow1, nTab1, nLastRow))
621 aPos.Y() += pDoc->GetRowHeight( nRow1, nTab1 ) / 2;
622 TwipsToMM( aPos.X() );
623 TwipsToMM( aPos.Y() );
624 Point aStartPos = aPos;
625 if ( bNegativePage )
626 aStartPos.X() = -aStartPos.X(); // don't modify aPos - used below
627 if ( pObj->GetPoint( 0 ) != aStartPos )
629 if (bRecording)
630 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
631 pObj->SetPoint( aStartPos, 0 );
634 if( !bValid2 )
636 Point aEndPos( aPos.X() + DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
637 if (aEndPos.Y() < 0)
638 aEndPos.Y() += (2 * DET_ARROW_OFFSET);
639 if ( bNegativePage )
640 aEndPos.X() = -aEndPos.X();
641 if ( pObj->GetPoint( 1 ) != aEndPos )
643 if (bRecording)
644 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
645 pObj->SetPoint( aEndPos, 1 );
649 if( bValid2 )
651 Point aPos( pDoc->GetColOffset( nCol2, nTab2 ), pDoc->GetRowOffset( nRow2, nTab2 ) );
652 if (!pDoc->ColHidden(nCol2, nTab2, nLastCol))
653 aPos.X() += pDoc->GetColWidth( nCol2, nTab2 ) / 4;
654 if (!pDoc->RowHidden(nRow2, nTab2, nLastRow))
655 aPos.Y() += pDoc->GetRowHeight( nRow2, nTab2 ) / 2;
656 TwipsToMM( aPos.X() );
657 TwipsToMM( aPos.Y() );
658 Point aEndPos = aPos;
659 if ( bNegativePage )
660 aEndPos.X() = -aEndPos.X(); // don't modify aPos - used below
661 if ( pObj->GetPoint( 1 ) != aEndPos )
663 if (bRecording)
664 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
665 pObj->SetPoint( aEndPos, 1 );
668 if( !bValid1 )
670 Point aStartPos( aPos.X() - DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
671 if (aStartPos.X() < 0)
672 aStartPos.X() += (2 * DET_ARROW_OFFSET);
673 if (aStartPos.Y() < 0)
674 aStartPos.Y() += (2 * DET_ARROW_OFFSET);
675 if ( bNegativePage )
676 aStartPos.X() = -aStartPos.X();
677 if ( pObj->GetPoint( 0 ) != aStartPos )
679 if (bRecording)
680 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
681 pObj->SetPoint( aStartPos, 0 );
686 else // Referenz-Rahmen
688 DBG_ASSERT( bValid1, "ScDrawLayer::RecalcPos - invalid start position" );
689 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
690 TwipsToMM( aPos.X() );
691 TwipsToMM( aPos.Y() );
693 if( bValid2 )
695 Point aEnd( pDoc->GetColOffset( nCol2 + 1, nTab2 ), pDoc->GetRowOffset( nRow2 + 1, nTab2 ) );
696 TwipsToMM( aEnd.X() );
697 TwipsToMM( aEnd.Y() );
699 Rectangle aNew( aPos, aEnd );
700 if ( bNegativePage )
701 MirrorRectRTL( aNew );
702 if ( pObj->GetLogicRect() != aNew )
704 if (bRecording)
705 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
706 pObj->SetLogicRect(aNew);
709 else
711 if ( bNegativePage )
712 aPos.X() = -aPos.X();
713 if ( pObj->GetRelativePos() != aPos )
715 if (bRecording)
716 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
717 pObj->SetRelativePos( aPos );
723 BOOL ScDrawLayer::GetPrintArea( ScRange& rRange, BOOL bSetHor, BOOL bSetVer ) const
725 DBG_ASSERT( pDoc, "ScDrawLayer::GetPrintArea without document" );
726 if ( !pDoc )
727 return FALSE;
729 SCTAB nTab = rRange.aStart.Tab();
730 DBG_ASSERT( rRange.aEnd.Tab() == nTab, "GetPrintArea: Tab unterschiedlich" );
732 BOOL bNegativePage = pDoc->IsNegativePage( nTab );
734 BOOL bAny = FALSE;
735 long nEndX = 0;
736 long nEndY = 0;
737 long nStartX = LONG_MAX;
738 long nStartY = LONG_MAX;
740 // Grenzen ausrechnen
742 if (!bSetHor)
744 nStartX = 0;
745 SCCOL nStartCol = rRange.aStart.Col();
746 SCCOL i;
747 for (i=0; i<nStartCol; i++)
748 nStartX +=pDoc->GetColWidth(i,nTab);
749 nEndX = nStartX;
750 SCCOL nEndCol = rRange.aEnd.Col();
751 for (i=nStartCol; i<=nEndCol; i++)
752 nEndX += pDoc->GetColWidth(i,nTab);
753 nStartX = TwipsToHmm( nStartX );
754 nEndX = TwipsToHmm( nEndX );
756 if (!bSetVer)
758 nStartY = pDoc->FastGetRowHeight( 0, rRange.aStart.Row()-1, nTab);
759 nEndY = nStartY + pDoc->FastGetRowHeight( rRange.aStart.Row(),
760 rRange.aEnd.Row(), nTab);
761 nStartY = TwipsToHmm( nStartY );
762 nEndY = TwipsToHmm( nEndY );
765 if ( bNegativePage )
767 nStartX = -nStartX; // positions are negative, swap start/end so the same comparisons work
768 nEndX = -nEndX;
769 ::std::swap( nStartX, nEndX );
772 const SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
773 DBG_ASSERT(pPage,"Page nicht gefunden");
774 if (pPage)
776 SdrObjListIter aIter( *pPage, IM_FLAT );
777 SdrObject* pObject = aIter.Next();
778 while (pObject)
780 //! Flags (ausgeblendet?) testen
782 Rectangle aObjRect = pObject->GetCurrentBoundRect();
783 BOOL bFit = TRUE;
784 if ( !bSetHor && ( aObjRect.Right() < nStartX || aObjRect.Left() > nEndX ) )
785 bFit = FALSE;
786 if ( !bSetVer && ( aObjRect.Bottom() < nStartY || aObjRect.Top() > nEndY ) )
787 bFit = FALSE;
788 if ( bFit )
790 if (bSetHor)
792 if (aObjRect.Left() < nStartX) nStartX = aObjRect.Left();
793 if (aObjRect.Right() > nEndX) nEndX = aObjRect.Right();
795 if (bSetVer)
797 if (aObjRect.Top() < nStartY) nStartY = aObjRect.Top();
798 if (aObjRect.Bottom() > nEndY) nEndY = aObjRect.Bottom();
800 bAny = TRUE;
803 pObject = aIter.Next();
807 if ( bNegativePage )
809 nStartX = -nStartX; // reverse transformation, so the same cell address calculation works
810 nEndX = -nEndX;
811 ::std::swap( nStartX, nEndX );
814 if (bAny)
816 DBG_ASSERT( nStartX<=nEndX && nStartY<=nEndY, "Start/End falsch in ScDrawLayer::GetPrintArea" );
818 if (bSetHor)
820 nStartX = HmmToTwips( nStartX );
821 nEndX = HmmToTwips( nEndX );
822 long nWidth;
823 SCCOL i;
825 nWidth = 0;
826 for (i=0; i<=MAXCOL && nWidth<=nStartX; i++)
827 nWidth += pDoc->GetColWidth(i,nTab);
828 rRange.aStart.SetCol( i>0 ? (i-1) : 0 );
830 nWidth = 0;
831 for (i=0; i<=MAXCOL && nWidth<=nEndX; i++) //! bei Start anfangen
832 nWidth += pDoc->GetColWidth(i,nTab);
833 rRange.aEnd.SetCol( i>0 ? (i-1) : 0 );
836 if (bSetVer)
838 nStartY = HmmToTwips( nStartY );
839 nEndY = HmmToTwips( nEndY );
840 SCROW nRow = pDoc->FastGetRowForHeight( nTab, nStartY);
841 rRange.aStart.SetRow( nRow>0 ? (nRow-1) : 0);
842 nRow = pDoc->FastGetRowForHeight( nTab, nEndY);
843 rRange.aEnd.SetRow( nRow == MAXROW ? MAXROW :
844 (nRow>0 ? (nRow-1) : 0));
847 else
849 if (bSetHor)
851 rRange.aStart.SetCol(0);
852 rRange.aEnd.SetCol(0);
854 if (bSetVer)
856 rRange.aStart.SetRow(0);
857 rRange.aEnd.SetRow(0);
860 return bAny;
863 void ScDrawLayer::AddCalcUndo( SdrUndoAction* pUndo )
865 if (bRecording)
867 if (!pUndoGroup)
868 pUndoGroup = new SdrUndoGroup(*this);
870 pUndoGroup->AddAction( pUndo );
872 else
873 delete pUndo;
876 void ScDrawLayer::BeginCalcUndo()
878 //! DBG_ASSERT( !bRecording, "BeginCalcUndo ohne GetCalcUndo" );
880 DELETEZ(pUndoGroup);
881 bRecording = TRUE;
884 SdrUndoGroup* ScDrawLayer::GetCalcUndo()
886 //! DBG_ASSERT( bRecording, "GetCalcUndo ohne BeginCalcUndo" );
888 SdrUndoGroup* pRet = pUndoGroup;
889 pUndoGroup = NULL;
890 bRecording = FALSE;
891 return pRet;
894 // MoveAreaTwips: all measures are kept in twips
895 void ScDrawLayer::MoveAreaTwips( SCTAB nTab, const Rectangle& rArea,
896 const Point& rMove, const Point& rTopLeft )
898 if (!rMove.X() && !rMove.Y())
899 return; // nix
901 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
902 DBG_ASSERT(pPage,"Page nicht gefunden");
903 if (!pPage)
904 return;
906 BOOL bNegativePage = pDoc && pDoc->IsNegativePage( nTab );
908 // fuer Shrinking!
909 Rectangle aNew( rArea );
910 BOOL bShrink = FALSE;
911 if ( rMove.X() < 0 || rMove.Y() < 0 ) // verkleinern
913 if ( rTopLeft != rArea.TopLeft() ) // sind gleich beim Verschieben von Zellen
915 bShrink = TRUE;
916 aNew.Left() = rTopLeft.X();
917 aNew.Top() = rTopLeft.Y();
920 SdrObjListIter aIter( *pPage, IM_FLAT );
921 SdrObject* pObject = aIter.Next();
922 while (pObject)
924 if( GetAnchor( pObject ) == SCA_CELL )
926 if ( GetObjData( pObject ) ) // Detektiv-Pfeil ?
928 // hier nichts
930 else if ( pObject->ISA( SdrEdgeObj ) ) // Verbinder?
932 // hier auch nichts
933 //! nicht verbundene Enden wie bei Linien (s.u.) behandeln?
935 else if ( pObject->IsPolyObj() && pObject->GetPointCount()==2 )
937 for (USHORT i=0; i<2; i++)
939 BOOL bMoved = FALSE;
940 Point aPoint = pObject->GetPoint(i);
941 lcl_ReverseTwipsToMM( aPoint );
942 if (rArea.IsInside(aPoint))
944 aPoint += rMove; bMoved = TRUE;
946 else if (bShrink && aNew.IsInside(aPoint))
948 // Punkt ist in betroffener Zelle - Test auf geloeschten Bereich
949 if ( rMove.X() && aPoint.X() >= rArea.Left() + rMove.X() )
951 aPoint.X() = rArea.Left() + rMove.X() - SHRINK_DIST_TWIPS;
952 if ( aPoint.X() < 0 ) aPoint.X() = 0;
953 bMoved = TRUE;
955 if ( rMove.Y() && aPoint.Y() >= rArea.Top() + rMove.Y() )
957 aPoint.Y() = rArea.Top() + rMove.Y() - SHRINK_DIST_TWIPS;
958 if ( aPoint.Y() < 0 ) aPoint.Y() = 0;
959 bMoved = TRUE;
962 if( bMoved )
964 AddCalcUndo( new SdrUndoGeoObj( *pObject ) );
965 lcl_TwipsToMM( aPoint );
966 pObject->SetPoint( aPoint, i );
970 else
972 Rectangle aObjRect = pObject->GetLogicRect();
973 // aOldMMPos: not converted, millimeters
974 Point aOldMMPos = bNegativePage ? aObjRect.TopRight() : aObjRect.TopLeft();
975 lcl_ReverseTwipsToMM( aObjRect );
976 Point aTopLeft = bNegativePage ? aObjRect.TopRight() : aObjRect.TopLeft(); // logical left
977 Size aMoveSize;
978 BOOL bDoMove = FALSE;
979 if (rArea.IsInside(aTopLeft))
981 aMoveSize = Size(rMove.X(),rMove.Y());
982 bDoMove = TRUE;
984 else if (bShrink && aNew.IsInside(aTopLeft))
986 // Position ist in betroffener Zelle - Test auf geloeschten Bereich
987 if ( rMove.X() && aTopLeft.X() >= rArea.Left() + rMove.X() )
989 aMoveSize.Width() = rArea.Left() + rMove.X() - SHRINK_DIST - aTopLeft.X();
990 bDoMove = TRUE;
992 if ( rMove.Y() && aTopLeft.Y() >= rArea.Top() + rMove.Y() )
994 aMoveSize.Height() = rArea.Top() + rMove.Y() - SHRINK_DIST - aTopLeft.Y();
995 bDoMove = TRUE;
998 if ( bDoMove )
1000 if ( bNegativePage )
1002 if ( aTopLeft.X() + aMoveSize.Width() > 0 )
1003 aMoveSize.Width() = -aTopLeft.X();
1005 else
1007 if ( aTopLeft.X() + aMoveSize.Width() < 0 )
1008 aMoveSize.Width() = -aTopLeft.X();
1010 if ( aTopLeft.Y() + aMoveSize.Height() < 0 )
1011 aMoveSize.Height() = -aTopLeft.Y();
1013 // get corresponding move size in millimeters:
1014 Point aNewPos( aTopLeft.X() + aMoveSize.Width(), aTopLeft.Y() + aMoveSize.Height() );
1015 lcl_TwipsToMM( aNewPos );
1016 aMoveSize = Size( aNewPos.X() - aOldMMPos.X(), aNewPos.Y() - aOldMMPos.Y() ); // millimeters
1018 AddCalcUndo( new SdrUndoMoveObj( *pObject, aMoveSize ) );
1019 pObject->Move( aMoveSize );
1021 else if ( rArea.IsInside( bNegativePage ? aObjRect.BottomLeft() : aObjRect.BottomRight() ) &&
1022 !pObject->IsResizeProtect() )
1024 // geschuetzte Groessen werden nicht veraendert
1025 // (Positionen schon, weil sie ja an der Zelle "verankert" sind)
1026 AddCalcUndo( new SdrUndoGeoObj( *pObject ) );
1027 long nOldSizeX = aObjRect.Right() - aObjRect.Left() + 1;
1028 long nOldSizeY = aObjRect.Bottom() - aObjRect.Top() + 1;
1029 long nLogMoveX = rMove.X() * ( bNegativePage ? -1 : 1 ); // logical direction
1030 pObject->Resize( aOldMMPos, Fraction( nOldSizeX+nLogMoveX, nOldSizeX ),
1031 Fraction( nOldSizeY+rMove.Y(), nOldSizeY ) );
1035 pObject = aIter.Next();
1039 void ScDrawLayer::MoveArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2,
1040 SCsCOL nDx,SCsROW nDy, BOOL bInsDel )
1042 DBG_ASSERT( pDoc, "ScDrawLayer::MoveArea without document" );
1043 if ( !pDoc )
1044 return;
1046 if (!bAdjustEnabled)
1047 return;
1049 BOOL bNegativePage = pDoc->IsNegativePage( nTab );
1051 Rectangle aRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
1052 lcl_ReverseTwipsToMM( aRect );
1053 //! use twips directly?
1055 Point aMove;
1057 if (nDx > 0)
1058 for (SCsCOL s=0; s<nDx; s++)
1059 aMove.X() += pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab);
1060 else
1061 for (SCsCOL s=-1; s>=nDx; s--)
1062 aMove.X() -= pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab);
1063 if (nDy > 0)
1064 aMove.Y() += pDoc->FastGetRowHeight( nRow1, nRow1+nDy-1, nTab);
1065 else
1066 aMove.Y() -= pDoc->FastGetRowHeight( nRow1+nDy, nRow1-1, nTab);
1068 if ( bNegativePage )
1069 aMove.X() = -aMove.X();
1071 Point aTopLeft = aRect.TopLeft(); // Anfang beim Verkleinern
1072 if (bInsDel)
1074 if ( aMove.X() != 0 && nDx < 0 ) // nDx counts cells, sign is independent of RTL
1075 aTopLeft.X() += aMove.X();
1076 if ( aMove.Y() < 0 )
1077 aTopLeft.Y() += aMove.Y();
1080 // drawing objects are now directly included in cut&paste
1081 // -> only update references when inserting/deleting (or changing widths or heights)
1082 if ( bInsDel )
1083 MoveAreaTwips( nTab, aRect, aMove, aTopLeft );
1086 // Detektiv-Pfeile: Zellpositionen anpassen
1089 MoveCells( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy );
1092 void ScDrawLayer::WidthChanged( SCTAB nTab, SCCOL nCol, long nDifTwips )
1094 DBG_ASSERT( pDoc, "ScDrawLayer::WidthChanged without document" );
1095 if ( !pDoc )
1096 return;
1098 if (!bAdjustEnabled)
1099 return;
1101 Rectangle aRect;
1102 Point aTopLeft;
1104 for (SCCOL i=0; i<nCol; i++)
1105 aRect.Left() += pDoc->GetColWidth(i,nTab);
1106 aTopLeft.X() = aRect.Left();
1107 aRect.Left() += pDoc->GetColWidth(nCol,nTab);
1109 aRect.Right() = MAXMM;
1110 aRect.Top() = 0;
1111 aRect.Bottom() = MAXMM;
1113 //! aTopLeft ist falsch, wenn mehrere Spalten auf einmal ausgeblendet werden
1115 BOOL bNegativePage = pDoc->IsNegativePage( nTab );
1116 if ( bNegativePage )
1118 MirrorRectRTL( aRect );
1119 aTopLeft.X() = -aTopLeft.X();
1120 nDifTwips = -nDifTwips;
1123 MoveAreaTwips( nTab, aRect, Point( nDifTwips,0 ), aTopLeft );
1126 void ScDrawLayer::HeightChanged( SCTAB nTab, SCROW nRow, long nDifTwips )
1128 DBG_ASSERT( pDoc, "ScDrawLayer::HeightChanged without document" );
1129 if ( !pDoc )
1130 return;
1132 if (!bAdjustEnabled)
1133 return;
1135 Rectangle aRect;
1136 Point aTopLeft;
1138 aRect.Top() += pDoc->FastGetRowHeight( 0, nRow-1, nTab);
1139 aTopLeft.Y() = aRect.Top();
1140 aRect.Top() += pDoc->FastGetRowHeight(nRow,nTab);
1142 aRect.Bottom() = MAXMM;
1143 aRect.Left() = 0;
1144 aRect.Right() = MAXMM;
1146 //! aTopLeft ist falsch, wenn mehrere Zeilen auf einmal ausgeblendet werden
1148 BOOL bNegativePage = pDoc->IsNegativePage( nTab );
1149 if ( bNegativePage )
1151 MirrorRectRTL( aRect );
1152 aTopLeft.X() = -aTopLeft.X();
1155 MoveAreaTwips( nTab, aRect, Point( 0,nDifTwips ), aTopLeft );
1158 BOOL ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow )
1160 DBG_ASSERT( pDoc, "ScDrawLayer::HasObjectsInRows without document" );
1161 if ( !pDoc )
1162 return FALSE;
1164 Rectangle aTestRect;
1166 aTestRect.Top() += pDoc->FastGetRowHeight( 0, nStartRow-1, nTab);
1168 if (nEndRow==MAXROW)
1169 aTestRect.Bottom() = MAXMM;
1170 else
1172 aTestRect.Bottom() = aTestRect.Top();
1173 aTestRect.Bottom() += pDoc->FastGetRowHeight( nStartRow, nEndRow, nTab);
1174 TwipsToMM( aTestRect.Bottom() );
1177 TwipsToMM( aTestRect.Top() );
1179 aTestRect.Left() = 0;
1180 aTestRect.Right() = MAXMM;
1182 BOOL bNegativePage = pDoc->IsNegativePage( nTab );
1183 if ( bNegativePage )
1184 MirrorRectRTL( aTestRect );
1186 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1187 DBG_ASSERT(pPage,"Page nicht gefunden");
1188 if (!pPage)
1189 return FALSE;
1191 BOOL bFound = FALSE;
1193 Rectangle aObjRect;
1194 SdrObjListIter aIter( *pPage );
1195 SdrObject* pObject = aIter.Next();
1196 while ( pObject && !bFound )
1198 aObjRect = pObject->GetSnapRect(); //! GetLogicRect ?
1199 if (aTestRect.IsInside(aObjRect.TopLeft()) || aTestRect.IsInside(aObjRect.BottomLeft()))
1200 bFound = TRUE;
1202 pObject = aIter.Next();
1205 return bFound;
1208 #if 0
1209 void ScDrawLayer::DeleteObjects( SCTAB nTab )
1211 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1212 DBG_ASSERT(pPage,"Page ?");
1213 if (!pPage)
1214 return;
1216 pPage->RecalcObjOrdNums();
1218 long nDelCount = 0;
1219 ULONG nObjCount = pPage->GetObjCount();
1220 if (nObjCount)
1222 SdrObject** ppObj = new SdrObject*[nObjCount];
1224 SdrObjListIter aIter( *pPage, IM_FLAT );
1225 SdrObject* pObject = aIter.Next();
1226 while (pObject)
1228 // alle loeschen
1229 ppObj[nDelCount++] = pObject;
1230 pObject = aIter.Next();
1233 long i;
1234 if (bRecording)
1235 for (i=1; i<=nDelCount; i++)
1236 AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
1238 for (i=1; i<=nDelCount; i++)
1239 pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1241 delete[] ppObj;
1244 #endif
1246 void ScDrawLayer::DeleteObjectsInArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1,
1247 SCCOL nCol2,SCROW nRow2 )
1249 DBG_ASSERT( pDoc, "ScDrawLayer::DeleteObjectsInArea without document" );
1250 if ( !pDoc )
1251 return;
1253 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1254 DBG_ASSERT(pPage,"Page ?");
1255 if (!pPage)
1256 return;
1258 pPage->RecalcObjOrdNums();
1260 long nDelCount = 0;
1261 ULONG nObjCount = pPage->GetObjCount();
1262 if (nObjCount)
1264 Rectangle aDelRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
1266 SdrObject** ppObj = new SdrObject*[nObjCount];
1268 SdrObjListIter aIter( *pPage, IM_FLAT );
1269 SdrObject* pObject = aIter.Next();
1270 while (pObject)
1272 // do not delete note caption, they are always handled by the cell note
1273 // TODO: detective objects are still deleted, is this desired?
1274 if (!IsNoteCaption( pObject ))
1276 Rectangle aObjRect = pObject->GetCurrentBoundRect();
1277 if ( aDelRect.IsInside( aObjRect ) )
1278 ppObj[nDelCount++] = pObject;
1281 pObject = aIter.Next();
1284 long i;
1285 if (bRecording)
1286 for (i=1; i<=nDelCount; i++)
1287 AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
1289 for (i=1; i<=nDelCount; i++)
1290 pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1292 delete[] ppObj;
1296 void ScDrawLayer::DeleteObjectsInSelection( const ScMarkData& rMark )
1298 DBG_ASSERT( pDoc, "ScDrawLayer::DeleteObjectsInSelection without document" );
1299 if ( !pDoc )
1300 return;
1302 if ( !rMark.IsMultiMarked() )
1303 return;
1305 ScRange aMarkRange;
1306 rMark.GetMultiMarkArea( aMarkRange );
1308 SCTAB nTabCount = pDoc->GetTableCount();
1309 for (SCTAB nTab=0; nTab<=nTabCount; nTab++)
1310 if ( rMark.GetTableSelect( nTab ) )
1312 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1313 if (pPage)
1315 pPage->RecalcObjOrdNums();
1316 long nDelCount = 0;
1317 ULONG nObjCount = pPage->GetObjCount();
1318 if (nObjCount)
1320 // Rechteck um die ganze Selektion
1321 Rectangle aMarkBound = pDoc->GetMMRect(
1322 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
1323 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab );
1325 SdrObject** ppObj = new SdrObject*[nObjCount];
1327 SdrObjListIter aIter( *pPage, IM_FLAT );
1328 SdrObject* pObject = aIter.Next();
1329 while (pObject)
1331 // do not delete note caption, they are always handled by the cell note
1332 // TODO: detective objects are still deleted, is this desired?
1333 if (!IsNoteCaption( pObject ))
1335 Rectangle aObjRect = pObject->GetCurrentBoundRect();
1336 if ( aMarkBound.IsInside( aObjRect ) )
1338 ScRange aRange = pDoc->GetRange( nTab, aObjRect );
1339 if (rMark.IsAllMarked(aRange))
1340 ppObj[nDelCount++] = pObject;
1344 pObject = aIter.Next();
1347 // Objekte loeschen (rueckwaerts)
1349 long i;
1350 if (bRecording)
1351 for (i=1; i<=nDelCount; i++)
1352 AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
1354 for (i=1; i<=nDelCount; i++)
1355 pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1357 delete[] ppObj;
1360 else
1362 DBG_ERROR("pPage?");
1367 void ScDrawLayer::CopyToClip( ScDocument* pClipDoc, SCTAB nTab, const Rectangle& rRange )
1369 // copy everything in the specified range into the same page (sheet) in the clipboard doc
1371 SdrPage* pSrcPage = GetPage(static_cast<sal_uInt16>(nTab));
1372 if (pSrcPage)
1374 ScDrawLayer* pDestModel = NULL;
1375 SdrPage* pDestPage = NULL;
1377 SdrObjListIter aIter( *pSrcPage, IM_FLAT );
1378 SdrObject* pOldObject = aIter.Next();
1379 while (pOldObject)
1381 Rectangle aObjRect = pOldObject->GetCurrentBoundRect();
1382 // do not copy internal objects (detective) and note captions
1383 if ( rRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) )
1385 if ( !pDestModel )
1387 pDestModel = pClipDoc->GetDrawLayer(); // does the document already have a drawing layer?
1388 if ( !pDestModel )
1390 // allocate drawing layer in clipboard document only if there are objects to copy
1392 pClipDoc->InitDrawLayer(); //! create contiguous pages
1393 pDestModel = pClipDoc->GetDrawLayer();
1395 if (pDestModel)
1396 pDestPage = pDestModel->GetPage( static_cast<sal_uInt16>(nTab) );
1399 DBG_ASSERT( pDestPage, "no page" );
1400 if (pDestPage)
1402 // #116235#
1403 SdrObject* pNewObject = pOldObject->Clone();
1404 //SdrObject* pNewObject = pOldObject->Clone( pDestPage, pDestModel );
1405 pNewObject->SetModel(pDestModel);
1406 pNewObject->SetPage(pDestPage);
1408 pNewObject->NbcMove(Size(0,0));
1409 pDestPage->InsertObject( pNewObject );
1411 // no undo needed in clipboard document
1412 // charts are not updated
1416 pOldObject = aIter.Next();
1421 BOOL lcl_IsAllInRange( const ScRangeList& rRanges, const ScRange& rClipRange )
1423 // check if every range of rRanges is completely in rClipRange
1425 ULONG nCount = rRanges.Count();
1426 for (ULONG i=0; i<nCount; i++)
1428 ScRange aRange = *rRanges.GetObject(i);
1429 if ( !rClipRange.In( aRange ) )
1431 return FALSE; // at least one range is not valid
1435 return TRUE; // everything is fine
1438 BOOL lcl_MoveRanges( ScRangeList& rRanges, const ScRange& rSourceRange, const ScAddress& rDestPos )
1440 BOOL bChanged = FALSE;
1442 ULONG nCount = rRanges.Count();
1443 for (ULONG i=0; i<nCount; i++)
1445 ScRange* pRange = rRanges.GetObject(i);
1446 if ( rSourceRange.In( *pRange ) )
1448 SCsCOL nDiffX = rDestPos.Col() - (SCsCOL)rSourceRange.aStart.Col();
1449 SCsROW nDiffY = rDestPos.Row() - (SCsROW)rSourceRange.aStart.Row();
1450 SCsTAB nDiffZ = rDestPos.Tab() - (SCsTAB)rSourceRange.aStart.Tab();
1451 pRange->Move( nDiffX, nDiffY, nDiffZ );
1452 bChanged = TRUE;
1456 return bChanged;
1459 void ScDrawLayer::CopyFromClip( ScDrawLayer* pClipModel, SCTAB nSourceTab, const Rectangle& rSourceRange,
1460 const ScAddress& rDestPos, const Rectangle& rDestRange )
1462 DBG_ASSERT( pDoc, "ScDrawLayer::CopyFromClip without document" );
1463 if ( !pDoc )
1464 return;
1466 if (!pClipModel)
1467 return;
1469 if (bDrawIsInUndo) //! can this happen?
1471 DBG_ERROR("CopyFromClip, bDrawIsInUndo");
1472 return;
1475 BOOL bMirrorObj = ( rSourceRange.Left() < 0 && rSourceRange.Right() < 0 &&
1476 rDestRange.Left() > 0 && rDestRange.Right() > 0 ) ||
1477 ( rSourceRange.Left() > 0 && rSourceRange.Right() > 0 &&
1478 rDestRange.Left() < 0 && rDestRange.Right() < 0 );
1479 Rectangle aMirroredSource = rSourceRange;
1480 if ( bMirrorObj )
1481 MirrorRectRTL( aMirroredSource );
1483 SCTAB nDestTab = rDestPos.Tab();
1485 SdrPage* pSrcPage = pClipModel->GetPage(static_cast<sal_uInt16>(nSourceTab));
1486 SdrPage* pDestPage = GetPage(static_cast<sal_uInt16>(nDestTab));
1487 DBG_ASSERT( pSrcPage && pDestPage, "draw page missing" );
1488 if ( !pSrcPage || !pDestPage )
1489 return;
1491 // first mirror, then move
1492 Size aMove( rDestRange.Left() - aMirroredSource.Left(), rDestRange.Top() - aMirroredSource.Top() );
1494 long nDestWidth = rDestRange.GetWidth();
1495 long nDestHeight = rDestRange.GetHeight();
1496 long nSourceWidth = rSourceRange.GetWidth();
1497 long nSourceHeight = rSourceRange.GetHeight();
1499 long nWidthDiff = nDestWidth - nSourceWidth;
1500 long nHeightDiff = nDestHeight - nSourceHeight;
1502 Fraction aHorFract(1,1);
1503 Fraction aVerFract(1,1);
1504 BOOL bResize = FALSE;
1505 // sizes can differ by 1 from twips->1/100mm conversion for equal cell sizes,
1506 // don't resize to empty size when pasting into hidden columns or rows
1507 if ( Abs(nWidthDiff) > 1 && nDestWidth > 1 && nSourceWidth > 1 )
1509 aHorFract = Fraction( nDestWidth, nSourceWidth );
1510 bResize = TRUE;
1512 if ( Abs(nHeightDiff) > 1 && nDestHeight > 1 && nSourceHeight > 1 )
1514 aVerFract = Fraction( nDestHeight, nSourceHeight );
1515 bResize = TRUE;
1517 Point aRefPos = rDestRange.TopLeft(); // for resizing (after moving)
1519 SdrObjListIter aIter( *pSrcPage, IM_FLAT );
1520 SdrObject* pOldObject = aIter.Next();
1521 while (pOldObject)
1523 Rectangle aObjRect = pOldObject->GetCurrentBoundRect();
1524 // do not copy internal objects (detective) and note captions
1525 if ( rSourceRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) )
1527 // #116235#
1528 SdrObject* pNewObject = pOldObject->Clone();
1529 //SdrObject* pNewObject = pOldObject->Clone( pDestPage, this );
1530 pNewObject->SetModel(this);
1531 pNewObject->SetPage(pDestPage);
1533 if ( bMirrorObj )
1534 MirrorRTL( pNewObject ); // first mirror, then move
1536 pNewObject->NbcMove( aMove );
1537 if ( bResize )
1538 pNewObject->NbcResize( aRefPos, aHorFract, aVerFract );
1540 pDestPage->InsertObject( pNewObject );
1541 if (bRecording)
1542 AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) );
1544 // handle chart data references (after InsertObject)
1546 if ( pNewObject->GetObjIdentifier() == OBJ_OLE2 )
1548 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pNewObject)->GetObjRef();
1549 uno::Reference< embed::XClassifiedObject > xClassified( xIPObj, uno::UNO_QUERY );
1550 SvGlobalName aObjectClassName;
1551 if ( xClassified.is() )
1553 try {
1554 aObjectClassName = SvGlobalName( xClassified->getClassID() );
1555 } catch( uno::Exception& )
1557 // TODO: handle error?
1561 if ( xIPObj.is() && SotExchange::IsChart( aObjectClassName ) )
1563 String aNewName = ((SdrOle2Obj*)pNewObject)->GetPersistName();
1565 //! need to set new DataProvider, or does Chart handle this itself?
1567 ScRangeListRef xRanges( new ScRangeList );
1568 BOOL bColHeaders = FALSE;
1569 BOOL bRowHeaders = FALSE;
1570 pDoc->GetOldChartParameters( aNewName, *xRanges, bColHeaders, bRowHeaders );
1572 if ( xRanges->Count() > 0 )
1574 ScDocument* pClipDoc = pClipModel->GetDocument();
1576 // a clipboard document and its source share the same document item pool,
1577 // so the pointers can be compared to see if this is copy&paste within
1578 // the same document
1579 BOOL bSameDoc = pDoc && pClipDoc && pDoc->GetPool() == pClipDoc->GetPool();
1581 BOOL bDestClip = pDoc && pDoc->IsClipboard();
1583 BOOL bInSourceRange = FALSE;
1584 ScRange aClipRange;
1585 if ( pClipDoc )
1587 SCCOL nClipStartX;
1588 SCROW nClipStartY;
1589 SCCOL nClipEndX;
1590 SCROW nClipEndY;
1591 pClipDoc->GetClipStart( nClipStartX, nClipStartY );
1592 pClipDoc->GetClipArea( nClipEndX, nClipEndY, TRUE );
1593 nClipEndX = nClipEndX + nClipStartX;
1594 nClipEndY += nClipStartY; // GetClipArea returns the difference
1596 aClipRange = ScRange( nClipStartX, nClipStartY, nSourceTab,
1597 nClipEndX, nClipEndY, nSourceTab );
1599 bInSourceRange = lcl_IsAllInRange( *xRanges, aClipRange );
1602 // always lose references when pasting into a clipboard document (transpose)
1603 if ( ( bInSourceRange || bSameDoc ) && !bDestClip )
1605 if ( bInSourceRange )
1607 if ( rDestPos != aClipRange.aStart )
1609 // update the data ranges to the new (copied) position
1610 ScRangeListRef xNewRanges = new ScRangeList( *xRanges );
1611 if ( lcl_MoveRanges( *xNewRanges, aClipRange, rDestPos ) )
1613 pDoc->UpdateChartArea( aNewName, xNewRanges, bColHeaders, bRowHeaders, FALSE );
1617 else
1619 // leave the ranges unchanged
1622 else
1624 // pasting into a new document without the complete source data
1625 // -> break connection to source data
1627 // (see ScDocument::UpdateChartListenerCollection, PastingDrawFromOtherDoc)
1629 //! need chart interface to switch to own data
1636 pOldObject = aIter.Next();
1640 void ScDrawLayer::MirrorRTL( SdrObject* pObj )
1642 UINT16 nIdent = pObj->GetObjIdentifier();
1644 // don't mirror OLE or graphics, otherwise ask the object
1645 // if it can be mirrored
1646 BOOL bCanMirror = ( nIdent != OBJ_GRAF && nIdent != OBJ_OLE2 );
1647 if (bCanMirror)
1649 SdrObjTransformInfoRec aInfo;
1650 pObj->TakeObjInfo( aInfo );
1651 bCanMirror = aInfo.bMirror90Allowed;
1654 if (bCanMirror)
1656 Point aRef1( 0, 0 );
1657 Point aRef2( 0, 1 );
1658 if (bRecording)
1659 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
1660 pObj->Mirror( aRef1, aRef2 );
1662 else
1664 // Move instead of mirroring:
1665 // New start position is negative of old end position
1666 // -> move by sum of start and end position
1667 Rectangle aObjRect = pObj->GetLogicRect();
1668 Size aMoveSize( -(aObjRect.Left() + aObjRect.Right()), 0 );
1669 if (bRecording)
1670 AddCalcUndo( new SdrUndoMoveObj( *pObj, aMoveSize ) );
1671 pObj->Move( aMoveSize );
1675 // static
1676 void ScDrawLayer::MirrorRectRTL( Rectangle& rRect )
1678 // mirror and swap left/right
1679 long nTemp = rRect.Left();
1680 rRect.Left() = -rRect.Right();
1681 rRect.Right() = -nTemp;
1684 Rectangle ScDrawLayer::GetCellRect( ScDocument& rDoc, const ScAddress& rPos, bool bMergedCell )
1686 Rectangle aCellRect;
1687 DBG_ASSERT( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ), "ScDrawLayer::GetCellRect - invalid cell address" );
1688 if( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ) )
1690 // find top left position of passed cell address
1691 Point aTopLeft;
1692 for( SCCOL nCol = 0; nCol < rPos.Col(); ++nCol )
1693 aTopLeft.X() += rDoc.GetColWidth( nCol, rPos.Tab() );
1694 if( rPos.Row() > 0 )
1695 aTopLeft.Y() += rDoc.FastGetRowHeight( 0, rPos.Row() - 1, rPos.Tab() );
1697 // find bottom-right position of passed cell address
1698 ScAddress aEndPos = rPos;
1699 if( bMergedCell )
1701 const ScMergeAttr* pMerge = static_cast< const ScMergeAttr* >( rDoc.GetAttr( rPos.Col(), rPos.Row(), rPos.Tab(), ATTR_MERGE ) );
1702 if( pMerge->GetColMerge() > 1 )
1703 aEndPos.IncCol( pMerge->GetColMerge() - 1 );
1704 if( pMerge->GetRowMerge() > 1 )
1705 aEndPos.IncRow( pMerge->GetRowMerge() - 1 );
1707 Point aBotRight = aTopLeft;
1708 for( SCCOL nCol = rPos.Col(); nCol <= aEndPos.Col(); ++nCol )
1709 aBotRight.X() += rDoc.GetColWidth( nCol, rPos.Tab() );
1710 aBotRight.Y() += rDoc.FastGetRowHeight( rPos.Row(), aEndPos.Row(), rPos.Tab() );
1712 // twips -> 1/100 mm
1713 aTopLeft.X() = static_cast< long >( aTopLeft.X() * HMM_PER_TWIPS );
1714 aTopLeft.Y() = static_cast< long >( aTopLeft.Y() * HMM_PER_TWIPS );
1715 aBotRight.X() = static_cast< long >( aBotRight.X() * HMM_PER_TWIPS );
1716 aBotRight.Y() = static_cast< long >( aBotRight.Y() * HMM_PER_TWIPS );
1718 aCellRect = Rectangle( aTopLeft, aBotRight );
1719 if( rDoc.IsNegativePage( rPos.Tab() ) )
1720 MirrorRectRTL( aCellRect );
1722 return aCellRect;
1725 // static
1726 String ScDrawLayer::GetVisibleName( SdrObject* pObj )
1728 String aName = pObj->GetName();
1729 if ( pObj->GetObjIdentifier() == OBJ_OLE2 )
1731 // #95575# For OLE, the user defined name (GetName) is used
1732 // if it's not empty (accepting possibly duplicate names),
1733 // otherwise the persist name is used so every object appears
1734 // in the Navigator at all.
1736 if ( !aName.Len() )
1737 aName = static_cast<SdrOle2Obj*>(pObj)->GetPersistName();
1739 return aName;
1742 inline sal_Bool IsNamedObject( SdrObject* pObj, const String& rName )
1744 // TRUE if rName is the object's Name or PersistName
1745 // (used to find a named object)
1747 return ( pObj->GetName() == rName ||
1748 ( pObj->GetObjIdentifier() == OBJ_OLE2 &&
1749 static_cast<SdrOle2Obj*>(pObj)->GetPersistName() == rName ) );
1752 SdrObject* ScDrawLayer::GetNamedObject( const String& rName, USHORT nId, SCTAB& rFoundTab ) const
1754 sal_uInt16 nTabCount = GetPageCount();
1755 for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++)
1757 const SdrPage* pPage = GetPage(nTab);
1758 DBG_ASSERT(pPage,"Page ?");
1759 if (pPage)
1761 SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
1762 SdrObject* pObject = aIter.Next();
1763 while (pObject)
1765 if ( nId == 0 || pObject->GetObjIdentifier() == nId )
1766 if ( IsNamedObject( pObject, rName ) )
1768 rFoundTab = static_cast<SCTAB>(nTab);
1769 return pObject;
1772 pObject = aIter.Next();
1777 return NULL;
1780 String ScDrawLayer::GetNewGraphicName( long* pnCounter ) const
1782 String aBase = ScGlobal::GetRscString(STR_GRAPHICNAME);
1783 aBase += ' ';
1785 BOOL bThere = TRUE;
1786 String aGraphicName;
1787 SCTAB nDummy;
1788 long nId = pnCounter ? *pnCounter : 0;
1789 while (bThere)
1791 ++nId;
1792 aGraphicName = aBase;
1793 aGraphicName += String::CreateFromInt32( nId );
1794 bThere = ( GetNamedObject( aGraphicName, 0, nDummy ) != NULL );
1797 if ( pnCounter )
1798 *pnCounter = nId;
1800 return aGraphicName;
1803 void ScDrawLayer::EnsureGraphicNames()
1805 // make sure all graphic objects have names (after Excel import etc.)
1807 sal_uInt16 nTabCount = GetPageCount();
1808 for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++)
1810 SdrPage* pPage = GetPage(nTab);
1811 DBG_ASSERT(pPage,"Page ?");
1812 if (pPage)
1814 SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
1815 SdrObject* pObject = aIter.Next();
1817 /* #101799# The index passed to GetNewGraphicName() will be set to
1818 the used index in each call. This prevents the repeated search
1819 for all names from 1 to current index. */
1820 long nCounter = 0;
1822 while (pObject)
1824 if ( pObject->GetObjIdentifier() == OBJ_GRAF && pObject->GetName().Len() == 0 )
1825 pObject->SetName( GetNewGraphicName( &nCounter ) );
1827 pObject = aIter.Next();
1833 void ScDrawLayer::SetAnchor( SdrObject* pObj, ScAnchorType eType )
1835 ScAnchorType eOldAnchorType = GetAnchor( pObj );
1837 // Ein an der Seite verankertes Objekt zeichnet sich durch eine Anker-Pos
1838 // von (0,1) aus. Das ist ein shabby Trick, der aber funktioniert!
1839 Point aAnchor( 0, eType == SCA_PAGE ? 1 : 0 );
1840 pObj->SetAnchorPos( aAnchor );
1842 if ( eOldAnchorType != eType )
1843 pObj->notifyShapePropertyChange( ::svx::eSpreadsheetAnchor );
1846 ScAnchorType ScDrawLayer::GetAnchor( const SdrObject* pObj )
1848 Point aAnchor( pObj->GetAnchorPos() );
1849 return ( aAnchor.Y() != 0 ) ? SCA_PAGE : SCA_CELL;
1852 ScDrawObjData* ScDrawLayer::GetObjData( SdrObject* pObj, BOOL bCreate ) // static
1854 USHORT nCount = pObj ? pObj->GetUserDataCount() : 0;
1855 for( USHORT i = 0; i < nCount; i++ )
1857 SdrObjUserData* pData = pObj->GetUserData( i );
1858 if( pData && pData->GetInventor() == SC_DRAWLAYER
1859 && pData->GetId() == SC_UD_OBJDATA )
1860 return (ScDrawObjData*) pData;
1862 if( pObj && bCreate )
1864 ScDrawObjData* pData = new ScDrawObjData;
1865 pObj->InsertUserData( pData, 0 );
1866 return pData;
1868 return 0;
1871 ScDrawObjData* ScDrawLayer::GetObjDataTab( SdrObject* pObj, SCTAB nTab ) // static
1873 ScDrawObjData* pData = GetObjData( pObj );
1874 if ( pData )
1876 if ( pData->maStart.IsValid() )
1877 pData->maStart.SetTab( nTab );
1878 if ( pData->maEnd.IsValid() )
1879 pData->maEnd.SetTab( nTab );
1881 return pData;
1884 bool ScDrawLayer::IsNoteCaption( SdrObject* pObj )
1886 ScDrawObjData* pData = pObj ? GetObjData( pObj ) : 0;
1887 return pData && pData->mbNote;
1890 ScDrawObjData* ScDrawLayer::GetNoteCaptionData( SdrObject* pObj, SCTAB nTab )
1892 ScDrawObjData* pData = pObj ? GetObjDataTab( pObj, nTab ) : 0;
1893 return (pData && pData->mbNote) ? pData : 0;
1896 ScIMapInfo* ScDrawLayer::GetIMapInfo( SdrObject* pObj ) // static
1898 USHORT nCount = pObj->GetUserDataCount();
1899 for( USHORT i = 0; i < nCount; i++ )
1901 SdrObjUserData* pData = pObj->GetUserData( i );
1902 if( pData && pData->GetInventor() == SC_DRAWLAYER
1903 && pData->GetId() == SC_UD_IMAPDATA )
1904 return (ScIMapInfo*) pData;
1906 return NULL;
1909 // static:
1910 IMapObject* ScDrawLayer::GetHitIMapObject( SdrObject* pObj,
1911 const Point& rWinPoint, const Window& rCmpWnd )
1913 const MapMode aMap100( MAP_100TH_MM );
1914 MapMode aWndMode = rCmpWnd.GetMapMode();
1915 Point aRelPoint( rCmpWnd.LogicToLogic( rWinPoint, &aWndMode, &aMap100 ) );
1916 Rectangle aLogRect = rCmpWnd.LogicToLogic( pObj->GetLogicRect(), &aWndMode, &aMap100 );
1917 ScIMapInfo* pIMapInfo = GetIMapInfo( pObj );
1918 IMapObject* pIMapObj = NULL;
1920 if ( pIMapInfo )
1922 Size aGraphSize;
1923 ImageMap& rImageMap = (ImageMap&) pIMapInfo->GetImageMap();
1924 Graphic aGraphic;
1925 BOOL bObjSupported = FALSE;
1927 if ( pObj->ISA( SdrGrafObj ) ) // einfaches Grafik-Objekt
1929 const SdrGrafObj* pGrafObj = (const SdrGrafObj*) pObj;
1930 const GeoStat& rGeo = pGrafObj->GetGeoStat();
1931 const Graphic& rGraphic = pGrafObj->GetGraphic();
1933 // Drehung rueckgaengig
1934 if ( rGeo.nDrehWink )
1935 RotatePoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nSin, rGeo.nCos );
1937 // Spiegelung rueckgaengig
1938 if ( ( (const SdrGrafObjGeoData*) pGrafObj->GetGeoData() )->bMirrored )
1939 aRelPoint.X() = aLogRect.Right() + aLogRect.Left() - aRelPoint.X();
1941 // ggf. Unshear:
1942 if ( rGeo.nShearWink )
1943 ShearPoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nTan );
1946 if ( rGraphic.GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
1947 aGraphSize = rCmpWnd.PixelToLogic( rGraphic.GetPrefSize(),
1948 aMap100 );
1949 else
1950 aGraphSize = OutputDevice::LogicToLogic( rGraphic.GetPrefSize(),
1951 rGraphic.GetPrefMapMode(),
1952 aMap100 );
1954 bObjSupported = TRUE;
1956 else if ( pObj->ISA( SdrOle2Obj ) ) // OLE-Objekt
1958 // TODO/LEAN: working with visual area needs running state
1959 aGraphSize = ((SdrOle2Obj*)pObj)->GetOrigObjSize();
1960 bObjSupported = TRUE;
1963 // hat alles geklappt, dann HitTest ausfuehren
1964 if ( bObjSupported )
1966 // relativen Mauspunkt berechnen
1967 aRelPoint -= aLogRect.TopLeft();
1968 pIMapObj = rImageMap.GetHitIMapObject( aGraphSize, aLogRect.GetSize(), aRelPoint );
1972 return pIMapObj;
1975 ScMacroInfo* ScDrawLayer::GetMacroInfo( SdrObject* pObj, BOOL bCreate ) // static
1977 USHORT nCount = pObj->GetUserDataCount();
1978 for( USHORT i = 0; i < nCount; i++ )
1980 SdrObjUserData* pData = pObj->GetUserData( i );
1981 if( pData && pData->GetInventor() == SC_DRAWLAYER
1982 && pData->GetId() == SC_UD_MACRODATA )
1983 return (ScMacroInfo*) pData;
1985 if ( bCreate )
1987 ScMacroInfo* pData = new ScMacroInfo;
1988 pObj->InsertUserData( pData, 0 );
1989 return pData;
1991 return 0;
1994 void ScDrawLayer::SetGlobalDrawPersist(SfxObjectShell* pPersist) // static
1996 DBG_ASSERT(!pGlobalDrawPersist,"SetGlobalDrawPersist mehrfach");
1997 pGlobalDrawPersist = pPersist;
2000 void __EXPORT ScDrawLayer::SetChanged( sal_Bool bFlg /* = sal_True */ )
2002 if ( bFlg && pDoc )
2003 pDoc->SetChartListenerCollectionNeedsUpdate( TRUE );
2004 FmFormModel::SetChanged( bFlg );
2007 SvStream* __EXPORT ScDrawLayer::GetDocumentStream(SdrDocumentStreamInfo& rStreamInfo) const
2009 DBG_ASSERT( pDoc, "ScDrawLayer::GetDocumentStream without document" );
2010 if ( !pDoc )
2011 return NULL;
2013 uno::Reference< embed::XStorage > xStorage = pDoc->GetDocumentShell() ?
2014 pDoc->GetDocumentShell()->GetStorage() :
2015 NULL;
2016 SvStream* pRet = NULL;
2018 if( xStorage.is() )
2020 if( rStreamInfo.maUserData.Len() &&
2021 ( rStreamInfo.maUserData.GetToken( 0, ':' ) ==
2022 String( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package" ) ) ) )
2024 const String aPicturePath( rStreamInfo.maUserData.GetToken( 1, ':' ) );
2026 // graphic from picture stream in picture storage in XML package
2027 if( aPicturePath.GetTokenCount( '/' ) == 2 )
2029 const String aPictureStreamName( aPicturePath.GetToken( 1, '/' ) );
2030 const String aPictureStorageName( aPicturePath.GetToken( 0, '/' ) );
2032 try {
2033 if ( xStorage->isStorageElement( aPictureStorageName ) )
2035 uno::Reference< embed::XStorage > xPictureStorage =
2036 xStorage->openStorageElement( aPictureStorageName, embed::ElementModes::READ );
2038 if( xPictureStorage.is() &&
2039 xPictureStorage->isStreamElement( aPictureStreamName ) )
2041 uno::Reference< io::XStream > xStream =
2042 xPictureStorage->openStreamElement( aPictureStreamName, embed::ElementModes::READ );
2043 if ( xStream.is() )
2044 pRet = ::utl::UcbStreamHelper::CreateStream( xStream );
2048 catch( uno::Exception& )
2050 // TODO: error handling
2054 // the following code seems to be related to binary format
2055 //REMOVE else
2056 //REMOVE {
2057 //REMOVE pRet = pStor->OpenStream( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_SCSTREAM)),
2058 //REMOVE STREAM_READ | STREAM_WRITE | STREAM_TRUNC );
2059 //REMOVE
2060 //REMOVE if( pRet )
2061 //REMOVE {
2062 //REMOVE pRet->SetVersion( pStor->GetVersion() );
2063 //REMOVE pRet->SetKey( pStor->GetKey() );
2064 //REMOVE }
2065 //REMOVE }
2067 rStreamInfo.mbDeleteAfterUse = ( pRet != NULL );
2070 return pRet;
2073 //REMOVE void ScDrawLayer::ReleasePictureStorage()
2074 //REMOVE {
2075 //REMOVE xPictureStorage.Clear();
2076 //REMOVE }
2078 SdrLayerID __EXPORT ScDrawLayer::GetControlExportLayerId( const SdrObject & ) const
2080 // Layer fuer Export von Form-Controls in Versionen vor 5.0 - immer SC_LAYER_FRONT
2081 return SC_LAYER_FRONT;
2084 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ScDrawLayer::createUnoModel()
2086 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xRet;
2087 if( pDoc && pDoc->GetDocumentShell() )
2088 xRet = pDoc->GetDocumentShell()->GetModel();
2090 return xRet;