update dev300-m57
[ooovba.git] / sc / source / core / data / drwlayer.cxx
blob94708e1c7fac5eb9c83c392e524459253ff9e611
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 if( bValid1 )
615 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
616 if( (pDoc->GetColFlags( nCol1, nTab1 ) & CR_HIDDEN) == 0 )
617 aPos.X() += pDoc->GetColWidth( nCol1, nTab1 ) / 4;
618 if( (pDoc->GetRowFlags( nRow1, nTab1 ) & CR_HIDDEN) == 0 )
619 aPos.Y() += pDoc->GetRowHeight( nRow1, nTab1 ) / 2;
620 TwipsToMM( aPos.X() );
621 TwipsToMM( aPos.Y() );
622 Point aStartPos = aPos;
623 if ( bNegativePage )
624 aStartPos.X() = -aStartPos.X(); // don't modify aPos - used below
625 if ( pObj->GetPoint( 0 ) != aStartPos )
627 if (bRecording)
628 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
629 pObj->SetPoint( aStartPos, 0 );
632 if( !bValid2 )
634 Point aEndPos( aPos.X() + DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
635 if (aEndPos.Y() < 0)
636 aEndPos.Y() += (2 * DET_ARROW_OFFSET);
637 if ( bNegativePage )
638 aEndPos.X() = -aEndPos.X();
639 if ( pObj->GetPoint( 1 ) != aEndPos )
641 if (bRecording)
642 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
643 pObj->SetPoint( aEndPos, 1 );
647 if( bValid2 )
649 Point aPos( pDoc->GetColOffset( nCol2, nTab2 ), pDoc->GetRowOffset( nRow2, nTab2 ) );
650 if( (pDoc->GetColFlags( nCol2, nTab2 ) & CR_HIDDEN) == 0 )
651 aPos.X() += pDoc->GetColWidth( nCol2, nTab2 ) / 4;
652 if( (pDoc->GetRowFlags( nRow2, nTab2 ) & CR_HIDDEN) == 0 )
653 aPos.Y() += pDoc->GetRowHeight( nRow2, nTab2 ) / 2;
654 TwipsToMM( aPos.X() );
655 TwipsToMM( aPos.Y() );
656 Point aEndPos = aPos;
657 if ( bNegativePage )
658 aEndPos.X() = -aEndPos.X(); // don't modify aPos - used below
659 if ( pObj->GetPoint( 1 ) != aEndPos )
661 if (bRecording)
662 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
663 pObj->SetPoint( aEndPos, 1 );
666 if( !bValid1 )
668 Point aStartPos( aPos.X() - DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
669 if (aStartPos.X() < 0)
670 aStartPos.X() += (2 * DET_ARROW_OFFSET);
671 if (aStartPos.Y() < 0)
672 aStartPos.Y() += (2 * DET_ARROW_OFFSET);
673 if ( bNegativePage )
674 aStartPos.X() = -aStartPos.X();
675 if ( pObj->GetPoint( 0 ) != aStartPos )
677 if (bRecording)
678 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
679 pObj->SetPoint( aStartPos, 0 );
684 else // Referenz-Rahmen
686 DBG_ASSERT( bValid1, "ScDrawLayer::RecalcPos - invalid start position" );
687 Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
688 TwipsToMM( aPos.X() );
689 TwipsToMM( aPos.Y() );
691 if( bValid2 )
693 Point aEnd( pDoc->GetColOffset( nCol2 + 1, nTab2 ), pDoc->GetRowOffset( nRow2 + 1, nTab2 ) );
694 TwipsToMM( aEnd.X() );
695 TwipsToMM( aEnd.Y() );
697 Rectangle aNew( aPos, aEnd );
698 if ( bNegativePage )
699 MirrorRectRTL( aNew );
700 if ( pObj->GetLogicRect() != aNew )
702 if (bRecording)
703 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
704 pObj->SetLogicRect(aNew);
707 else
709 if ( bNegativePage )
710 aPos.X() = -aPos.X();
711 if ( pObj->GetRelativePos() != aPos )
713 if (bRecording)
714 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
715 pObj->SetRelativePos( aPos );
721 BOOL ScDrawLayer::GetPrintArea( ScRange& rRange, BOOL bSetHor, BOOL bSetVer ) const
723 DBG_ASSERT( pDoc, "ScDrawLayer::GetPrintArea without document" );
724 if ( !pDoc )
725 return FALSE;
727 SCTAB nTab = rRange.aStart.Tab();
728 DBG_ASSERT( rRange.aEnd.Tab() == nTab, "GetPrintArea: Tab unterschiedlich" );
730 BOOL bNegativePage = pDoc->IsNegativePage( nTab );
732 BOOL bAny = FALSE;
733 long nEndX = 0;
734 long nEndY = 0;
735 long nStartX = LONG_MAX;
736 long nStartY = LONG_MAX;
738 // Grenzen ausrechnen
740 if (!bSetHor)
742 nStartX = 0;
743 SCCOL nStartCol = rRange.aStart.Col();
744 SCCOL i;
745 for (i=0; i<nStartCol; i++)
746 nStartX +=pDoc->GetColWidth(i,nTab);
747 nEndX = nStartX;
748 SCCOL nEndCol = rRange.aEnd.Col();
749 for (i=nStartCol; i<=nEndCol; i++)
750 nEndX += pDoc->GetColWidth(i,nTab);
751 nStartX = TwipsToHmm( nStartX );
752 nEndX = TwipsToHmm( nEndX );
754 if (!bSetVer)
756 nStartY = pDoc->FastGetRowHeight( 0, rRange.aStart.Row()-1, nTab);
757 nEndY = nStartY + pDoc->FastGetRowHeight( rRange.aStart.Row(),
758 rRange.aEnd.Row(), nTab);
759 nStartY = TwipsToHmm( nStartY );
760 nEndY = TwipsToHmm( nEndY );
763 if ( bNegativePage )
765 nStartX = -nStartX; // positions are negative, swap start/end so the same comparisons work
766 nEndX = -nEndX;
767 ::std::swap( nStartX, nEndX );
770 const SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
771 DBG_ASSERT(pPage,"Page nicht gefunden");
772 if (pPage)
774 SdrObjListIter aIter( *pPage, IM_FLAT );
775 SdrObject* pObject = aIter.Next();
776 while (pObject)
778 //! Flags (ausgeblendet?) testen
780 Rectangle aObjRect = pObject->GetCurrentBoundRect();
781 BOOL bFit = TRUE;
782 if ( !bSetHor && ( aObjRect.Right() < nStartX || aObjRect.Left() > nEndX ) )
783 bFit = FALSE;
784 if ( !bSetVer && ( aObjRect.Bottom() < nStartY || aObjRect.Top() > nEndY ) )
785 bFit = FALSE;
786 if ( bFit )
788 if (bSetHor)
790 if (aObjRect.Left() < nStartX) nStartX = aObjRect.Left();
791 if (aObjRect.Right() > nEndX) nEndX = aObjRect.Right();
793 if (bSetVer)
795 if (aObjRect.Top() < nStartY) nStartY = aObjRect.Top();
796 if (aObjRect.Bottom() > nEndY) nEndY = aObjRect.Bottom();
798 bAny = TRUE;
801 pObject = aIter.Next();
805 if ( bNegativePage )
807 nStartX = -nStartX; // reverse transformation, so the same cell address calculation works
808 nEndX = -nEndX;
809 ::std::swap( nStartX, nEndX );
812 if (bAny)
814 DBG_ASSERT( nStartX<=nEndX && nStartY<=nEndY, "Start/End falsch in ScDrawLayer::GetPrintArea" );
816 if (bSetHor)
818 nStartX = HmmToTwips( nStartX );
819 nEndX = HmmToTwips( nEndX );
820 long nWidth;
821 SCCOL i;
823 nWidth = 0;
824 for (i=0; i<=MAXCOL && nWidth<=nStartX; i++)
825 nWidth += pDoc->GetColWidth(i,nTab);
826 rRange.aStart.SetCol( i>0 ? (i-1) : 0 );
828 nWidth = 0;
829 for (i=0; i<=MAXCOL && nWidth<=nEndX; i++) //! bei Start anfangen
830 nWidth += pDoc->GetColWidth(i,nTab);
831 rRange.aEnd.SetCol( i>0 ? (i-1) : 0 );
834 if (bSetVer)
836 nStartY = HmmToTwips( nStartY );
837 nEndY = HmmToTwips( nEndY );
838 SCROW nRow = pDoc->FastGetRowForHeight( nTab, nStartY);
839 rRange.aStart.SetRow( nRow>0 ? (nRow-1) : 0);
840 nRow = pDoc->FastGetRowForHeight( nTab, nEndY);
841 rRange.aEnd.SetRow( nRow == MAXROW ? MAXROW :
842 (nRow>0 ? (nRow-1) : 0));
845 else
847 if (bSetHor)
849 rRange.aStart.SetCol(0);
850 rRange.aEnd.SetCol(0);
852 if (bSetVer)
854 rRange.aStart.SetRow(0);
855 rRange.aEnd.SetRow(0);
858 return bAny;
861 void ScDrawLayer::AddCalcUndo( SdrUndoAction* pUndo )
863 if (bRecording)
865 if (!pUndoGroup)
866 pUndoGroup = new SdrUndoGroup(*this);
868 pUndoGroup->AddAction( pUndo );
870 else
871 delete pUndo;
874 void ScDrawLayer::BeginCalcUndo()
876 //! DBG_ASSERT( !bRecording, "BeginCalcUndo ohne GetCalcUndo" );
878 DELETEZ(pUndoGroup);
879 bRecording = TRUE;
882 SdrUndoGroup* ScDrawLayer::GetCalcUndo()
884 //! DBG_ASSERT( bRecording, "GetCalcUndo ohne BeginCalcUndo" );
886 SdrUndoGroup* pRet = pUndoGroup;
887 pUndoGroup = NULL;
888 bRecording = FALSE;
889 return pRet;
892 // MoveAreaTwips: all measures are kept in twips
893 void ScDrawLayer::MoveAreaTwips( SCTAB nTab, const Rectangle& rArea,
894 const Point& rMove, const Point& rTopLeft )
896 if (!rMove.X() && !rMove.Y())
897 return; // nix
899 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
900 DBG_ASSERT(pPage,"Page nicht gefunden");
901 if (!pPage)
902 return;
904 BOOL bNegativePage = pDoc && pDoc->IsNegativePage( nTab );
906 // fuer Shrinking!
907 Rectangle aNew( rArea );
908 BOOL bShrink = FALSE;
909 if ( rMove.X() < 0 || rMove.Y() < 0 ) // verkleinern
911 if ( rTopLeft != rArea.TopLeft() ) // sind gleich beim Verschieben von Zellen
913 bShrink = TRUE;
914 aNew.Left() = rTopLeft.X();
915 aNew.Top() = rTopLeft.Y();
918 SdrObjListIter aIter( *pPage, IM_FLAT );
919 SdrObject* pObject = aIter.Next();
920 while (pObject)
922 if( GetAnchor( pObject ) == SCA_CELL )
924 if ( GetObjData( pObject ) ) // Detektiv-Pfeil ?
926 // hier nichts
928 else if ( pObject->ISA( SdrEdgeObj ) ) // Verbinder?
930 // hier auch nichts
931 //! nicht verbundene Enden wie bei Linien (s.u.) behandeln?
933 else if ( pObject->IsPolyObj() && pObject->GetPointCount()==2 )
935 for (USHORT i=0; i<2; i++)
937 BOOL bMoved = FALSE;
938 Point aPoint = pObject->GetPoint(i);
939 lcl_ReverseTwipsToMM( aPoint );
940 if (rArea.IsInside(aPoint))
942 aPoint += rMove; bMoved = TRUE;
944 else if (bShrink && aNew.IsInside(aPoint))
946 // Punkt ist in betroffener Zelle - Test auf geloeschten Bereich
947 if ( rMove.X() && aPoint.X() >= rArea.Left() + rMove.X() )
949 aPoint.X() = rArea.Left() + rMove.X() - SHRINK_DIST_TWIPS;
950 if ( aPoint.X() < 0 ) aPoint.X() = 0;
951 bMoved = TRUE;
953 if ( rMove.Y() && aPoint.Y() >= rArea.Top() + rMove.Y() )
955 aPoint.Y() = rArea.Top() + rMove.Y() - SHRINK_DIST_TWIPS;
956 if ( aPoint.Y() < 0 ) aPoint.Y() = 0;
957 bMoved = TRUE;
960 if( bMoved )
962 AddCalcUndo( new SdrUndoGeoObj( *pObject ) );
963 lcl_TwipsToMM( aPoint );
964 pObject->SetPoint( aPoint, i );
968 else
970 Rectangle aObjRect = pObject->GetLogicRect();
971 // aOldMMPos: not converted, millimeters
972 Point aOldMMPos = bNegativePage ? aObjRect.TopRight() : aObjRect.TopLeft();
973 lcl_ReverseTwipsToMM( aObjRect );
974 Point aTopLeft = bNegativePage ? aObjRect.TopRight() : aObjRect.TopLeft(); // logical left
975 Size aMoveSize;
976 BOOL bDoMove = FALSE;
977 if (rArea.IsInside(aTopLeft))
979 aMoveSize = Size(rMove.X(),rMove.Y());
980 bDoMove = TRUE;
982 else if (bShrink && aNew.IsInside(aTopLeft))
984 // Position ist in betroffener Zelle - Test auf geloeschten Bereich
985 if ( rMove.X() && aTopLeft.X() >= rArea.Left() + rMove.X() )
987 aMoveSize.Width() = rArea.Left() + rMove.X() - SHRINK_DIST - aTopLeft.X();
988 bDoMove = TRUE;
990 if ( rMove.Y() && aTopLeft.Y() >= rArea.Top() + rMove.Y() )
992 aMoveSize.Height() = rArea.Top() + rMove.Y() - SHRINK_DIST - aTopLeft.Y();
993 bDoMove = TRUE;
996 if ( bDoMove )
998 if ( bNegativePage )
1000 if ( aTopLeft.X() + aMoveSize.Width() > 0 )
1001 aMoveSize.Width() = -aTopLeft.X();
1003 else
1005 if ( aTopLeft.X() + aMoveSize.Width() < 0 )
1006 aMoveSize.Width() = -aTopLeft.X();
1008 if ( aTopLeft.Y() + aMoveSize.Height() < 0 )
1009 aMoveSize.Height() = -aTopLeft.Y();
1011 // get corresponding move size in millimeters:
1012 Point aNewPos( aTopLeft.X() + aMoveSize.Width(), aTopLeft.Y() + aMoveSize.Height() );
1013 lcl_TwipsToMM( aNewPos );
1014 aMoveSize = Size( aNewPos.X() - aOldMMPos.X(), aNewPos.Y() - aOldMMPos.Y() ); // millimeters
1016 AddCalcUndo( new SdrUndoMoveObj( *pObject, aMoveSize ) );
1017 pObject->Move( aMoveSize );
1019 else if ( rArea.IsInside( bNegativePage ? aObjRect.BottomLeft() : aObjRect.BottomRight() ) &&
1020 !pObject->IsResizeProtect() )
1022 // geschuetzte Groessen werden nicht veraendert
1023 // (Positionen schon, weil sie ja an der Zelle "verankert" sind)
1024 AddCalcUndo( new SdrUndoGeoObj( *pObject ) );
1025 long nOldSizeX = aObjRect.Right() - aObjRect.Left() + 1;
1026 long nOldSizeY = aObjRect.Bottom() - aObjRect.Top() + 1;
1027 long nLogMoveX = rMove.X() * ( bNegativePage ? -1 : 1 ); // logical direction
1028 pObject->Resize( aOldMMPos, Fraction( nOldSizeX+nLogMoveX, nOldSizeX ),
1029 Fraction( nOldSizeY+rMove.Y(), nOldSizeY ) );
1033 pObject = aIter.Next();
1037 void ScDrawLayer::MoveArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2,
1038 SCsCOL nDx,SCsROW nDy, BOOL bInsDel )
1040 DBG_ASSERT( pDoc, "ScDrawLayer::MoveArea without document" );
1041 if ( !pDoc )
1042 return;
1044 if (!bAdjustEnabled)
1045 return;
1047 BOOL bNegativePage = pDoc->IsNegativePage( nTab );
1049 Rectangle aRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
1050 lcl_ReverseTwipsToMM( aRect );
1051 //! use twips directly?
1053 Point aMove;
1055 if (nDx > 0)
1056 for (SCsCOL s=0; s<nDx; s++)
1057 aMove.X() += pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab);
1058 else
1059 for (SCsCOL s=-1; s>=nDx; s--)
1060 aMove.X() -= pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab);
1061 if (nDy > 0)
1062 aMove.Y() += pDoc->FastGetRowHeight( nRow1, nRow1+nDy-1, nTab);
1063 else
1064 aMove.Y() -= pDoc->FastGetRowHeight( nRow1+nDy, nRow1-1, nTab);
1066 if ( bNegativePage )
1067 aMove.X() = -aMove.X();
1069 Point aTopLeft = aRect.TopLeft(); // Anfang beim Verkleinern
1070 if (bInsDel)
1072 if ( aMove.X() != 0 && nDx < 0 ) // nDx counts cells, sign is independent of RTL
1073 aTopLeft.X() += aMove.X();
1074 if ( aMove.Y() < 0 )
1075 aTopLeft.Y() += aMove.Y();
1078 // drawing objects are now directly included in cut&paste
1079 // -> only update references when inserting/deleting (or changing widths or heights)
1080 if ( bInsDel )
1081 MoveAreaTwips( nTab, aRect, aMove, aTopLeft );
1084 // Detektiv-Pfeile: Zellpositionen anpassen
1087 MoveCells( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy );
1090 void ScDrawLayer::WidthChanged( SCTAB nTab, SCCOL nCol, long nDifTwips )
1092 DBG_ASSERT( pDoc, "ScDrawLayer::WidthChanged without document" );
1093 if ( !pDoc )
1094 return;
1096 if (!bAdjustEnabled)
1097 return;
1099 Rectangle aRect;
1100 Point aTopLeft;
1102 for (SCCOL i=0; i<nCol; i++)
1103 aRect.Left() += pDoc->GetColWidth(i,nTab);
1104 aTopLeft.X() = aRect.Left();
1105 aRect.Left() += pDoc->GetColWidth(nCol,nTab);
1107 aRect.Right() = MAXMM;
1108 aRect.Top() = 0;
1109 aRect.Bottom() = MAXMM;
1111 //! aTopLeft ist falsch, wenn mehrere Spalten auf einmal ausgeblendet werden
1113 BOOL bNegativePage = pDoc->IsNegativePage( nTab );
1114 if ( bNegativePage )
1116 MirrorRectRTL( aRect );
1117 aTopLeft.X() = -aTopLeft.X();
1118 nDifTwips = -nDifTwips;
1121 MoveAreaTwips( nTab, aRect, Point( nDifTwips,0 ), aTopLeft );
1124 void ScDrawLayer::HeightChanged( SCTAB nTab, SCROW nRow, long nDifTwips )
1126 DBG_ASSERT( pDoc, "ScDrawLayer::HeightChanged without document" );
1127 if ( !pDoc )
1128 return;
1130 if (!bAdjustEnabled)
1131 return;
1133 Rectangle aRect;
1134 Point aTopLeft;
1136 aRect.Top() += pDoc->FastGetRowHeight( 0, nRow-1, nTab);
1137 aTopLeft.Y() = aRect.Top();
1138 aRect.Top() += pDoc->FastGetRowHeight(nRow,nTab);
1140 aRect.Bottom() = MAXMM;
1141 aRect.Left() = 0;
1142 aRect.Right() = MAXMM;
1144 //! aTopLeft ist falsch, wenn mehrere Zeilen auf einmal ausgeblendet werden
1146 BOOL bNegativePage = pDoc->IsNegativePage( nTab );
1147 if ( bNegativePage )
1149 MirrorRectRTL( aRect );
1150 aTopLeft.X() = -aTopLeft.X();
1153 MoveAreaTwips( nTab, aRect, Point( 0,nDifTwips ), aTopLeft );
1156 BOOL ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow )
1158 DBG_ASSERT( pDoc, "ScDrawLayer::HasObjectsInRows without document" );
1159 if ( !pDoc )
1160 return FALSE;
1162 Rectangle aTestRect;
1164 aTestRect.Top() += pDoc->FastGetRowHeight( 0, nStartRow-1, nTab);
1166 if (nEndRow==MAXROW)
1167 aTestRect.Bottom() = MAXMM;
1168 else
1170 aTestRect.Bottom() = aTestRect.Top();
1171 aTestRect.Bottom() += pDoc->FastGetRowHeight( nStartRow, nEndRow, nTab);
1172 TwipsToMM( aTestRect.Bottom() );
1175 TwipsToMM( aTestRect.Top() );
1177 aTestRect.Left() = 0;
1178 aTestRect.Right() = MAXMM;
1180 BOOL bNegativePage = pDoc->IsNegativePage( nTab );
1181 if ( bNegativePage )
1182 MirrorRectRTL( aTestRect );
1184 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1185 DBG_ASSERT(pPage,"Page nicht gefunden");
1186 if (!pPage)
1187 return FALSE;
1189 BOOL bFound = FALSE;
1191 Rectangle aObjRect;
1192 SdrObjListIter aIter( *pPage );
1193 SdrObject* pObject = aIter.Next();
1194 while ( pObject && !bFound )
1196 aObjRect = pObject->GetSnapRect(); //! GetLogicRect ?
1197 if (aTestRect.IsInside(aObjRect.TopLeft()) || aTestRect.IsInside(aObjRect.BottomLeft()))
1198 bFound = TRUE;
1200 pObject = aIter.Next();
1203 return bFound;
1206 #if 0
1207 void ScDrawLayer::DeleteObjects( SCTAB nTab )
1209 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1210 DBG_ASSERT(pPage,"Page ?");
1211 if (!pPage)
1212 return;
1214 pPage->RecalcObjOrdNums();
1216 long nDelCount = 0;
1217 ULONG nObjCount = pPage->GetObjCount();
1218 if (nObjCount)
1220 SdrObject** ppObj = new SdrObject*[nObjCount];
1222 SdrObjListIter aIter( *pPage, IM_FLAT );
1223 SdrObject* pObject = aIter.Next();
1224 while (pObject)
1226 // alle loeschen
1227 ppObj[nDelCount++] = pObject;
1228 pObject = aIter.Next();
1231 long i;
1232 if (bRecording)
1233 for (i=1; i<=nDelCount; i++)
1234 AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
1236 for (i=1; i<=nDelCount; i++)
1237 pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1239 delete[] ppObj;
1242 #endif
1244 void ScDrawLayer::DeleteObjectsInArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1,
1245 SCCOL nCol2,SCROW nRow2 )
1247 DBG_ASSERT( pDoc, "ScDrawLayer::DeleteObjectsInArea without document" );
1248 if ( !pDoc )
1249 return;
1251 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1252 DBG_ASSERT(pPage,"Page ?");
1253 if (!pPage)
1254 return;
1256 pPage->RecalcObjOrdNums();
1258 long nDelCount = 0;
1259 ULONG nObjCount = pPage->GetObjCount();
1260 if (nObjCount)
1262 Rectangle aDelRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
1264 SdrObject** ppObj = new SdrObject*[nObjCount];
1266 SdrObjListIter aIter( *pPage, IM_FLAT );
1267 SdrObject* pObject = aIter.Next();
1268 while (pObject)
1270 // do not delete note caption, they are always handled by the cell note
1271 // TODO: detective objects are still deleted, is this desired?
1272 if (!IsNoteCaption( pObject ))
1274 Rectangle aObjRect = pObject->GetCurrentBoundRect();
1275 if ( aDelRect.IsInside( aObjRect ) )
1276 ppObj[nDelCount++] = pObject;
1279 pObject = aIter.Next();
1282 long i;
1283 if (bRecording)
1284 for (i=1; i<=nDelCount; i++)
1285 AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
1287 for (i=1; i<=nDelCount; i++)
1288 pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1290 delete[] ppObj;
1294 void ScDrawLayer::DeleteObjectsInSelection( const ScMarkData& rMark )
1296 DBG_ASSERT( pDoc, "ScDrawLayer::DeleteObjectsInSelection without document" );
1297 if ( !pDoc )
1298 return;
1300 if ( !rMark.IsMultiMarked() )
1301 return;
1303 ScRange aMarkRange;
1304 rMark.GetMultiMarkArea( aMarkRange );
1306 SCTAB nTabCount = pDoc->GetTableCount();
1307 for (SCTAB nTab=0; nTab<=nTabCount; nTab++)
1308 if ( rMark.GetTableSelect( nTab ) )
1310 SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1311 if (pPage)
1313 pPage->RecalcObjOrdNums();
1314 long nDelCount = 0;
1315 ULONG nObjCount = pPage->GetObjCount();
1316 if (nObjCount)
1318 // Rechteck um die ganze Selektion
1319 Rectangle aMarkBound = pDoc->GetMMRect(
1320 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
1321 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab );
1323 SdrObject** ppObj = new SdrObject*[nObjCount];
1325 SdrObjListIter aIter( *pPage, IM_FLAT );
1326 SdrObject* pObject = aIter.Next();
1327 while (pObject)
1329 // do not delete note caption, they are always handled by the cell note
1330 // TODO: detective objects are still deleted, is this desired?
1331 if (!IsNoteCaption( pObject ))
1333 Rectangle aObjRect = pObject->GetCurrentBoundRect();
1334 if ( aMarkBound.IsInside( aObjRect ) )
1336 ScRange aRange = pDoc->GetRange( nTab, aObjRect );
1337 if (rMark.IsAllMarked(aRange))
1338 ppObj[nDelCount++] = pObject;
1342 pObject = aIter.Next();
1345 // Objekte loeschen (rueckwaerts)
1347 long i;
1348 if (bRecording)
1349 for (i=1; i<=nDelCount; i++)
1350 AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
1352 for (i=1; i<=nDelCount; i++)
1353 pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1355 delete[] ppObj;
1358 else
1360 DBG_ERROR("pPage?");
1365 void ScDrawLayer::CopyToClip( ScDocument* pClipDoc, SCTAB nTab, const Rectangle& rRange )
1367 // copy everything in the specified range into the same page (sheet) in the clipboard doc
1369 SdrPage* pSrcPage = GetPage(static_cast<sal_uInt16>(nTab));
1370 if (pSrcPage)
1372 ScDrawLayer* pDestModel = NULL;
1373 SdrPage* pDestPage = NULL;
1375 SdrObjListIter aIter( *pSrcPage, IM_FLAT );
1376 SdrObject* pOldObject = aIter.Next();
1377 while (pOldObject)
1379 Rectangle aObjRect = pOldObject->GetCurrentBoundRect();
1380 // do not copy internal objects (detective) and note captions
1381 if ( rRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) )
1383 if ( !pDestModel )
1385 pDestModel = pClipDoc->GetDrawLayer(); // does the document already have a drawing layer?
1386 if ( !pDestModel )
1388 // allocate drawing layer in clipboard document only if there are objects to copy
1390 pClipDoc->InitDrawLayer(); //! create contiguous pages
1391 pDestModel = pClipDoc->GetDrawLayer();
1393 if (pDestModel)
1394 pDestPage = pDestModel->GetPage( static_cast<sal_uInt16>(nTab) );
1397 DBG_ASSERT( pDestPage, "no page" );
1398 if (pDestPage)
1400 // #116235#
1401 SdrObject* pNewObject = pOldObject->Clone();
1402 //SdrObject* pNewObject = pOldObject->Clone( pDestPage, pDestModel );
1403 pNewObject->SetModel(pDestModel);
1404 pNewObject->SetPage(pDestPage);
1406 pNewObject->NbcMove(Size(0,0));
1407 pDestPage->InsertObject( pNewObject );
1409 // no undo needed in clipboard document
1410 // charts are not updated
1414 pOldObject = aIter.Next();
1419 BOOL lcl_IsAllInRange( const ScRangeList& rRanges, const ScRange& rClipRange )
1421 // check if every range of rRanges is completely in rClipRange
1423 ULONG nCount = rRanges.Count();
1424 for (ULONG i=0; i<nCount; i++)
1426 ScRange aRange = *rRanges.GetObject(i);
1427 if ( !rClipRange.In( aRange ) )
1429 return FALSE; // at least one range is not valid
1433 return TRUE; // everything is fine
1436 BOOL lcl_MoveRanges( ScRangeList& rRanges, const ScRange& rSourceRange, const ScAddress& rDestPos )
1438 BOOL bChanged = FALSE;
1440 ULONG nCount = rRanges.Count();
1441 for (ULONG i=0; i<nCount; i++)
1443 ScRange* pRange = rRanges.GetObject(i);
1444 if ( rSourceRange.In( *pRange ) )
1446 SCsCOL nDiffX = rDestPos.Col() - (SCsCOL)rSourceRange.aStart.Col();
1447 SCsROW nDiffY = rDestPos.Row() - (SCsROW)rSourceRange.aStart.Row();
1448 SCsTAB nDiffZ = rDestPos.Tab() - (SCsTAB)rSourceRange.aStart.Tab();
1449 pRange->Move( nDiffX, nDiffY, nDiffZ );
1450 bChanged = TRUE;
1454 return bChanged;
1457 void ScDrawLayer::CopyFromClip( ScDrawLayer* pClipModel, SCTAB nSourceTab, const Rectangle& rSourceRange,
1458 const ScAddress& rDestPos, const Rectangle& rDestRange )
1460 DBG_ASSERT( pDoc, "ScDrawLayer::CopyFromClip without document" );
1461 if ( !pDoc )
1462 return;
1464 if (!pClipModel)
1465 return;
1467 if (bDrawIsInUndo) //! can this happen?
1469 DBG_ERROR("CopyFromClip, bDrawIsInUndo");
1470 return;
1473 BOOL bMirrorObj = ( rSourceRange.Left() < 0 && rSourceRange.Right() < 0 &&
1474 rDestRange.Left() > 0 && rDestRange.Right() > 0 ) ||
1475 ( rSourceRange.Left() > 0 && rSourceRange.Right() > 0 &&
1476 rDestRange.Left() < 0 && rDestRange.Right() < 0 );
1477 Rectangle aMirroredSource = rSourceRange;
1478 if ( bMirrorObj )
1479 MirrorRectRTL( aMirroredSource );
1481 SCTAB nDestTab = rDestPos.Tab();
1483 SdrPage* pSrcPage = pClipModel->GetPage(static_cast<sal_uInt16>(nSourceTab));
1484 SdrPage* pDestPage = GetPage(static_cast<sal_uInt16>(nDestTab));
1485 DBG_ASSERT( pSrcPage && pDestPage, "draw page missing" );
1486 if ( !pSrcPage || !pDestPage )
1487 return;
1489 // first mirror, then move
1490 Size aMove( rDestRange.Left() - aMirroredSource.Left(), rDestRange.Top() - aMirroredSource.Top() );
1492 long nDestWidth = rDestRange.GetWidth();
1493 long nDestHeight = rDestRange.GetHeight();
1494 long nSourceWidth = rSourceRange.GetWidth();
1495 long nSourceHeight = rSourceRange.GetHeight();
1497 long nWidthDiff = nDestWidth - nSourceWidth;
1498 long nHeightDiff = nDestHeight - nSourceHeight;
1500 Fraction aHorFract(1,1);
1501 Fraction aVerFract(1,1);
1502 BOOL bResize = FALSE;
1503 // sizes can differ by 1 from twips->1/100mm conversion for equal cell sizes,
1504 // don't resize to empty size when pasting into hidden columns or rows
1505 if ( Abs(nWidthDiff) > 1 && nDestWidth > 1 && nSourceWidth > 1 )
1507 aHorFract = Fraction( nDestWidth, nSourceWidth );
1508 bResize = TRUE;
1510 if ( Abs(nHeightDiff) > 1 && nDestHeight > 1 && nSourceHeight > 1 )
1512 aVerFract = Fraction( nDestHeight, nSourceHeight );
1513 bResize = TRUE;
1515 Point aRefPos = rDestRange.TopLeft(); // for resizing (after moving)
1517 SdrObjListIter aIter( *pSrcPage, IM_FLAT );
1518 SdrObject* pOldObject = aIter.Next();
1519 while (pOldObject)
1521 Rectangle aObjRect = pOldObject->GetCurrentBoundRect();
1522 // do not copy internal objects (detective) and note captions
1523 if ( rSourceRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) )
1525 // #116235#
1526 SdrObject* pNewObject = pOldObject->Clone();
1527 //SdrObject* pNewObject = pOldObject->Clone( pDestPage, this );
1528 pNewObject->SetModel(this);
1529 pNewObject->SetPage(pDestPage);
1531 if ( bMirrorObj )
1532 MirrorRTL( pNewObject ); // first mirror, then move
1534 pNewObject->NbcMove( aMove );
1535 if ( bResize )
1536 pNewObject->NbcResize( aRefPos, aHorFract, aVerFract );
1538 pDestPage->InsertObject( pNewObject );
1539 if (bRecording)
1540 AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) );
1542 // handle chart data references (after InsertObject)
1544 if ( pNewObject->GetObjIdentifier() == OBJ_OLE2 )
1546 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pNewObject)->GetObjRef();
1547 uno::Reference< embed::XClassifiedObject > xClassified( xIPObj, uno::UNO_QUERY );
1548 SvGlobalName aObjectClassName;
1549 if ( xClassified.is() )
1551 try {
1552 aObjectClassName = SvGlobalName( xClassified->getClassID() );
1553 } catch( uno::Exception& )
1555 // TODO: handle error?
1559 if ( xIPObj.is() && SotExchange::IsChart( aObjectClassName ) )
1561 String aNewName = ((SdrOle2Obj*)pNewObject)->GetPersistName();
1563 //! need to set new DataProvider, or does Chart handle this itself?
1565 ScRangeListRef xRanges( new ScRangeList );
1566 BOOL bColHeaders = FALSE;
1567 BOOL bRowHeaders = FALSE;
1568 pDoc->GetOldChartParameters( aNewName, *xRanges, bColHeaders, bRowHeaders );
1570 if ( xRanges->Count() > 0 )
1572 ScDocument* pClipDoc = pClipModel->GetDocument();
1574 // a clipboard document and its source share the same document item pool,
1575 // so the pointers can be compared to see if this is copy&paste within
1576 // the same document
1577 BOOL bSameDoc = pDoc && pClipDoc && pDoc->GetPool() == pClipDoc->GetPool();
1579 BOOL bDestClip = pDoc && pDoc->IsClipboard();
1581 BOOL bInSourceRange = FALSE;
1582 ScRange aClipRange;
1583 if ( pClipDoc )
1585 SCCOL nClipStartX;
1586 SCROW nClipStartY;
1587 SCCOL nClipEndX;
1588 SCROW nClipEndY;
1589 pClipDoc->GetClipStart( nClipStartX, nClipStartY );
1590 pClipDoc->GetClipArea( nClipEndX, nClipEndY, TRUE );
1591 nClipEndX = nClipEndX + nClipStartX;
1592 nClipEndY += nClipStartY; // GetClipArea returns the difference
1594 aClipRange = ScRange( nClipStartX, nClipStartY, nSourceTab,
1595 nClipEndX, nClipEndY, nSourceTab );
1597 bInSourceRange = lcl_IsAllInRange( *xRanges, aClipRange );
1600 // always lose references when pasting into a clipboard document (transpose)
1601 if ( ( bInSourceRange || bSameDoc ) && !bDestClip )
1603 if ( bInSourceRange )
1605 if ( rDestPos != aClipRange.aStart )
1607 // update the data ranges to the new (copied) position
1608 ScRangeListRef xNewRanges = new ScRangeList( *xRanges );
1609 if ( lcl_MoveRanges( *xNewRanges, aClipRange, rDestPos ) )
1611 pDoc->UpdateChartArea( aNewName, xNewRanges, bColHeaders, bRowHeaders, FALSE );
1615 else
1617 // leave the ranges unchanged
1620 else
1622 // pasting into a new document without the complete source data
1623 // -> break connection to source data
1625 // (see ScDocument::UpdateChartListenerCollection, PastingDrawFromOtherDoc)
1627 //! need chart interface to switch to own data
1634 pOldObject = aIter.Next();
1638 void ScDrawLayer::MirrorRTL( SdrObject* pObj )
1640 UINT16 nIdent = pObj->GetObjIdentifier();
1642 // don't mirror OLE or graphics, otherwise ask the object
1643 // if it can be mirrored
1644 BOOL bCanMirror = ( nIdent != OBJ_GRAF && nIdent != OBJ_OLE2 );
1645 if (bCanMirror)
1647 SdrObjTransformInfoRec aInfo;
1648 pObj->TakeObjInfo( aInfo );
1649 bCanMirror = aInfo.bMirror90Allowed;
1652 if (bCanMirror)
1654 Point aRef1( 0, 0 );
1655 Point aRef2( 0, 1 );
1656 if (bRecording)
1657 AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
1658 pObj->Mirror( aRef1, aRef2 );
1660 else
1662 // Move instead of mirroring:
1663 // New start position is negative of old end position
1664 // -> move by sum of start and end position
1665 Rectangle aObjRect = pObj->GetLogicRect();
1666 Size aMoveSize( -(aObjRect.Left() + aObjRect.Right()), 0 );
1667 if (bRecording)
1668 AddCalcUndo( new SdrUndoMoveObj( *pObj, aMoveSize ) );
1669 pObj->Move( aMoveSize );
1673 // static
1674 void ScDrawLayer::MirrorRectRTL( Rectangle& rRect )
1676 // mirror and swap left/right
1677 long nTemp = rRect.Left();
1678 rRect.Left() = -rRect.Right();
1679 rRect.Right() = -nTemp;
1682 Rectangle ScDrawLayer::GetCellRect( ScDocument& rDoc, const ScAddress& rPos, bool bMergedCell )
1684 Rectangle aCellRect;
1685 DBG_ASSERT( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ), "ScDrawLayer::GetCellRect - invalid cell address" );
1686 if( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ) )
1688 // find top left position of passed cell address
1689 Point aTopLeft;
1690 for( SCCOL nCol = 0; nCol < rPos.Col(); ++nCol )
1691 aTopLeft.X() += rDoc.GetColWidth( nCol, rPos.Tab() );
1692 if( rPos.Row() > 0 )
1693 aTopLeft.Y() += rDoc.FastGetRowHeight( 0, rPos.Row() - 1, rPos.Tab() );
1695 // find bottom-right position of passed cell address
1696 ScAddress aEndPos = rPos;
1697 if( bMergedCell )
1699 const ScMergeAttr* pMerge = static_cast< const ScMergeAttr* >( rDoc.GetAttr( rPos.Col(), rPos.Row(), rPos.Tab(), ATTR_MERGE ) );
1700 if( pMerge->GetColMerge() > 1 )
1701 aEndPos.IncCol( pMerge->GetColMerge() - 1 );
1702 if( pMerge->GetRowMerge() > 1 )
1703 aEndPos.IncRow( pMerge->GetRowMerge() - 1 );
1705 Point aBotRight = aTopLeft;
1706 for( SCCOL nCol = rPos.Col(); nCol <= aEndPos.Col(); ++nCol )
1707 aBotRight.X() += rDoc.GetColWidth( nCol, rPos.Tab() );
1708 aBotRight.Y() += rDoc.FastGetRowHeight( rPos.Row(), aEndPos.Row(), rPos.Tab() );
1710 // twips -> 1/100 mm
1711 aTopLeft.X() = static_cast< long >( aTopLeft.X() * HMM_PER_TWIPS );
1712 aTopLeft.Y() = static_cast< long >( aTopLeft.Y() * HMM_PER_TWIPS );
1713 aBotRight.X() = static_cast< long >( aBotRight.X() * HMM_PER_TWIPS );
1714 aBotRight.Y() = static_cast< long >( aBotRight.Y() * HMM_PER_TWIPS );
1716 aCellRect = Rectangle( aTopLeft, aBotRight );
1717 if( rDoc.IsNegativePage( rPos.Tab() ) )
1718 MirrorRectRTL( aCellRect );
1720 return aCellRect;
1723 // static
1724 String ScDrawLayer::GetVisibleName( SdrObject* pObj )
1726 String aName = pObj->GetName();
1727 if ( pObj->GetObjIdentifier() == OBJ_OLE2 )
1729 // #95575# For OLE, the user defined name (GetName) is used
1730 // if it's not empty (accepting possibly duplicate names),
1731 // otherwise the persist name is used so every object appears
1732 // in the Navigator at all.
1734 if ( !aName.Len() )
1735 aName = static_cast<SdrOle2Obj*>(pObj)->GetPersistName();
1737 return aName;
1740 inline sal_Bool IsNamedObject( SdrObject* pObj, const String& rName )
1742 // TRUE if rName is the object's Name or PersistName
1743 // (used to find a named object)
1745 return ( pObj->GetName() == rName ||
1746 ( pObj->GetObjIdentifier() == OBJ_OLE2 &&
1747 static_cast<SdrOle2Obj*>(pObj)->GetPersistName() == rName ) );
1750 SdrObject* ScDrawLayer::GetNamedObject( const String& rName, USHORT nId, SCTAB& rFoundTab ) const
1752 sal_uInt16 nTabCount = GetPageCount();
1753 for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++)
1755 const SdrPage* pPage = GetPage(nTab);
1756 DBG_ASSERT(pPage,"Page ?");
1757 if (pPage)
1759 SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
1760 SdrObject* pObject = aIter.Next();
1761 while (pObject)
1763 if ( nId == 0 || pObject->GetObjIdentifier() == nId )
1764 if ( IsNamedObject( pObject, rName ) )
1766 rFoundTab = static_cast<SCTAB>(nTab);
1767 return pObject;
1770 pObject = aIter.Next();
1775 return NULL;
1778 String ScDrawLayer::GetNewGraphicName( long* pnCounter ) const
1780 String aBase = ScGlobal::GetRscString(STR_GRAPHICNAME);
1781 aBase += ' ';
1783 BOOL bThere = TRUE;
1784 String aGraphicName;
1785 SCTAB nDummy;
1786 long nId = pnCounter ? *pnCounter : 0;
1787 while (bThere)
1789 ++nId;
1790 aGraphicName = aBase;
1791 aGraphicName += String::CreateFromInt32( nId );
1792 bThere = ( GetNamedObject( aGraphicName, 0, nDummy ) != NULL );
1795 if ( pnCounter )
1796 *pnCounter = nId;
1798 return aGraphicName;
1801 void ScDrawLayer::EnsureGraphicNames()
1803 // make sure all graphic objects have names (after Excel import etc.)
1805 sal_uInt16 nTabCount = GetPageCount();
1806 for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++)
1808 SdrPage* pPage = GetPage(nTab);
1809 DBG_ASSERT(pPage,"Page ?");
1810 if (pPage)
1812 SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
1813 SdrObject* pObject = aIter.Next();
1815 /* #101799# The index passed to GetNewGraphicName() will be set to
1816 the used index in each call. This prevents the repeated search
1817 for all names from 1 to current index. */
1818 long nCounter = 0;
1820 while (pObject)
1822 if ( pObject->GetObjIdentifier() == OBJ_GRAF && pObject->GetName().Len() == 0 )
1823 pObject->SetName( GetNewGraphicName( &nCounter ) );
1825 pObject = aIter.Next();
1831 void ScDrawLayer::SetAnchor( SdrObject* pObj, ScAnchorType eType )
1833 ScAnchorType eOldAnchorType = GetAnchor( pObj );
1835 // Ein an der Seite verankertes Objekt zeichnet sich durch eine Anker-Pos
1836 // von (0,1) aus. Das ist ein shabby Trick, der aber funktioniert!
1837 Point aAnchor( 0, eType == SCA_PAGE ? 1 : 0 );
1838 pObj->SetAnchorPos( aAnchor );
1840 if ( eOldAnchorType != eType )
1841 pObj->notifyShapePropertyChange( ::svx::eSpreadsheetAnchor );
1844 ScAnchorType ScDrawLayer::GetAnchor( const SdrObject* pObj )
1846 Point aAnchor( pObj->GetAnchorPos() );
1847 return ( aAnchor.Y() != 0 ) ? SCA_PAGE : SCA_CELL;
1850 ScDrawObjData* ScDrawLayer::GetObjData( SdrObject* pObj, BOOL bCreate ) // static
1852 USHORT nCount = pObj ? pObj->GetUserDataCount() : 0;
1853 for( USHORT i = 0; i < nCount; i++ )
1855 SdrObjUserData* pData = pObj->GetUserData( i );
1856 if( pData && pData->GetInventor() == SC_DRAWLAYER
1857 && pData->GetId() == SC_UD_OBJDATA )
1858 return (ScDrawObjData*) pData;
1860 if( pObj && bCreate )
1862 ScDrawObjData* pData = new ScDrawObjData;
1863 pObj->InsertUserData( pData, 0 );
1864 return pData;
1866 return 0;
1869 ScDrawObjData* ScDrawLayer::GetObjDataTab( SdrObject* pObj, SCTAB nTab ) // static
1871 ScDrawObjData* pData = GetObjData( pObj );
1872 if ( pData )
1874 if ( pData->maStart.IsValid() )
1875 pData->maStart.SetTab( nTab );
1876 if ( pData->maEnd.IsValid() )
1877 pData->maEnd.SetTab( nTab );
1879 return pData;
1882 bool ScDrawLayer::IsNoteCaption( SdrObject* pObj )
1884 ScDrawObjData* pData = pObj ? GetObjData( pObj ) : 0;
1885 return pData && pData->mbNote;
1888 ScDrawObjData* ScDrawLayer::GetNoteCaptionData( SdrObject* pObj, SCTAB nTab )
1890 ScDrawObjData* pData = pObj ? GetObjDataTab( pObj, nTab ) : 0;
1891 return (pData && pData->mbNote) ? pData : 0;
1894 ScIMapInfo* ScDrawLayer::GetIMapInfo( SdrObject* pObj ) // static
1896 USHORT nCount = pObj->GetUserDataCount();
1897 for( USHORT i = 0; i < nCount; i++ )
1899 SdrObjUserData* pData = pObj->GetUserData( i );
1900 if( pData && pData->GetInventor() == SC_DRAWLAYER
1901 && pData->GetId() == SC_UD_IMAPDATA )
1902 return (ScIMapInfo*) pData;
1904 return NULL;
1907 // static:
1908 IMapObject* ScDrawLayer::GetHitIMapObject( SdrObject* pObj,
1909 const Point& rWinPoint, const Window& rCmpWnd )
1911 const MapMode aMap100( MAP_100TH_MM );
1912 MapMode aWndMode = rCmpWnd.GetMapMode();
1913 Point aRelPoint( rCmpWnd.LogicToLogic( rWinPoint, &aWndMode, &aMap100 ) );
1914 Rectangle aLogRect = rCmpWnd.LogicToLogic( pObj->GetLogicRect(), &aWndMode, &aMap100 );
1915 ScIMapInfo* pIMapInfo = GetIMapInfo( pObj );
1916 IMapObject* pIMapObj = NULL;
1918 if ( pIMapInfo )
1920 Size aGraphSize;
1921 ImageMap& rImageMap = (ImageMap&) pIMapInfo->GetImageMap();
1922 Graphic aGraphic;
1923 BOOL bObjSupported = FALSE;
1925 if ( pObj->ISA( SdrGrafObj ) ) // einfaches Grafik-Objekt
1927 const SdrGrafObj* pGrafObj = (const SdrGrafObj*) pObj;
1928 const GeoStat& rGeo = pGrafObj->GetGeoStat();
1929 const Graphic& rGraphic = pGrafObj->GetGraphic();
1931 // Drehung rueckgaengig
1932 if ( rGeo.nDrehWink )
1933 RotatePoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nSin, rGeo.nCos );
1935 // Spiegelung rueckgaengig
1936 if ( ( (const SdrGrafObjGeoData*) pGrafObj->GetGeoData() )->bMirrored )
1937 aRelPoint.X() = aLogRect.Right() + aLogRect.Left() - aRelPoint.X();
1939 // ggf. Unshear:
1940 if ( rGeo.nShearWink )
1941 ShearPoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nTan );
1944 if ( rGraphic.GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
1945 aGraphSize = rCmpWnd.PixelToLogic( rGraphic.GetPrefSize(),
1946 aMap100 );
1947 else
1948 aGraphSize = OutputDevice::LogicToLogic( rGraphic.GetPrefSize(),
1949 rGraphic.GetPrefMapMode(),
1950 aMap100 );
1952 bObjSupported = TRUE;
1954 else if ( pObj->ISA( SdrOle2Obj ) ) // OLE-Objekt
1956 // TODO/LEAN: working with visual area needs running state
1957 aGraphSize = ((SdrOle2Obj*)pObj)->GetOrigObjSize();
1958 bObjSupported = TRUE;
1961 // hat alles geklappt, dann HitTest ausfuehren
1962 if ( bObjSupported )
1964 // relativen Mauspunkt berechnen
1965 aRelPoint -= aLogRect.TopLeft();
1966 pIMapObj = rImageMap.GetHitIMapObject( aGraphSize, aLogRect.GetSize(), aRelPoint );
1970 return pIMapObj;
1973 ScMacroInfo* ScDrawLayer::GetMacroInfo( SdrObject* pObj, BOOL bCreate ) // static
1975 USHORT nCount = pObj->GetUserDataCount();
1976 for( USHORT i = 0; i < nCount; i++ )
1978 SdrObjUserData* pData = pObj->GetUserData( i );
1979 if( pData && pData->GetInventor() == SC_DRAWLAYER
1980 && pData->GetId() == SC_UD_MACRODATA )
1981 return (ScMacroInfo*) pData;
1983 if ( bCreate )
1985 ScMacroInfo* pData = new ScMacroInfo;
1986 pObj->InsertUserData( pData, 0 );
1987 return pData;
1989 return 0;
1992 void ScDrawLayer::SetGlobalDrawPersist(SfxObjectShell* pPersist) // static
1994 DBG_ASSERT(!pGlobalDrawPersist,"SetGlobalDrawPersist mehrfach");
1995 pGlobalDrawPersist = pPersist;
1998 void __EXPORT ScDrawLayer::SetChanged( sal_Bool bFlg /* = sal_True */ )
2000 if ( bFlg && pDoc )
2001 pDoc->SetChartListenerCollectionNeedsUpdate( TRUE );
2002 FmFormModel::SetChanged( bFlg );
2005 SvStream* __EXPORT ScDrawLayer::GetDocumentStream(SdrDocumentStreamInfo& rStreamInfo) const
2007 DBG_ASSERT( pDoc, "ScDrawLayer::GetDocumentStream without document" );
2008 if ( !pDoc )
2009 return NULL;
2011 uno::Reference< embed::XStorage > xStorage = pDoc->GetDocumentShell() ?
2012 pDoc->GetDocumentShell()->GetStorage() :
2013 NULL;
2014 SvStream* pRet = NULL;
2016 if( xStorage.is() )
2018 if( rStreamInfo.maUserData.Len() &&
2019 ( rStreamInfo.maUserData.GetToken( 0, ':' ) ==
2020 String( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package" ) ) ) )
2022 const String aPicturePath( rStreamInfo.maUserData.GetToken( 1, ':' ) );
2024 // graphic from picture stream in picture storage in XML package
2025 if( aPicturePath.GetTokenCount( '/' ) == 2 )
2027 const String aPictureStreamName( aPicturePath.GetToken( 1, '/' ) );
2028 const String aPictureStorageName( aPicturePath.GetToken( 0, '/' ) );
2030 try {
2031 if ( xStorage->isStorageElement( aPictureStorageName ) )
2033 uno::Reference< embed::XStorage > xPictureStorage =
2034 xStorage->openStorageElement( aPictureStorageName, embed::ElementModes::READ );
2036 if( xPictureStorage.is() &&
2037 xPictureStorage->isStreamElement( aPictureStreamName ) )
2039 uno::Reference< io::XStream > xStream =
2040 xPictureStorage->openStreamElement( aPictureStreamName, embed::ElementModes::READ );
2041 if ( xStream.is() )
2042 pRet = ::utl::UcbStreamHelper::CreateStream( xStream );
2046 catch( uno::Exception& )
2048 // TODO: error handling
2052 // the following code seems to be related to binary format
2053 //REMOVE else
2054 //REMOVE {
2055 //REMOVE pRet = pStor->OpenStream( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_SCSTREAM)),
2056 //REMOVE STREAM_READ | STREAM_WRITE | STREAM_TRUNC );
2057 //REMOVE
2058 //REMOVE if( pRet )
2059 //REMOVE {
2060 //REMOVE pRet->SetVersion( pStor->GetVersion() );
2061 //REMOVE pRet->SetKey( pStor->GetKey() );
2062 //REMOVE }
2063 //REMOVE }
2065 rStreamInfo.mbDeleteAfterUse = ( pRet != NULL );
2068 return pRet;
2071 //REMOVE void ScDrawLayer::ReleasePictureStorage()
2072 //REMOVE {
2073 //REMOVE xPictureStorage.Clear();
2074 //REMOVE }
2076 SdrLayerID __EXPORT ScDrawLayer::GetControlExportLayerId( const SdrObject & ) const
2078 // Layer fuer Export von Form-Controls in Versionen vor 5.0 - immer SC_LAYER_FRONT
2079 return SC_LAYER_FRONT;
2082 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ScDrawLayer::createUnoModel()
2084 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xRet;
2085 if( pDoc && pDoc->GetDocumentShell() )
2086 xRet = pDoc->GetDocumentShell()->GetModel();
2088 return xRet;