1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/uno/Reference.hxx>
21 #include <com/sun/star/chart/XChartDocument.hpp>
22 #include <com/sun/star/embed/XEmbeddedObject.hpp>
23 #include <com/sun/star/embed/XVisualObject.hpp>
24 #include <com/sun/star/embed/XClassifiedObject.hpp>
25 #include <com/sun/star/embed/XComponentSupplier.hpp>
26 #include <com/sun/star/embed/EmbedStates.hpp>
27 #include <com/sun/star/embed/ElementModes.hpp>
28 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
29 #include <com/sun/star/datatransfer/XTransferable.hpp>
30 #include <basegfx/matrix/b2dhommatrixtools.hxx>
32 #include "scitems.hxx"
33 #include <editeng/eeitem.hxx>
34 #include <editeng/frmdiritem.hxx>
35 #include <sot/exchange.hxx>
36 #include <svx/objfac3d.hxx>
37 #include <svx/xtable.hxx>
38 #include <svx/svdoutl.hxx>
39 #include <svx/svditer.hxx>
40 #include <svx/svdocapt.hxx>
41 #include <svx/svdocirc.hxx>
42 #include <svx/svdoedge.hxx>
43 #include <svx/svdograf.hxx>
44 #include <svx/svdoole2.hxx>
45 #include <svx/svdundo.hxx>
46 #include <i18nlangtag/mslangid.hxx>
47 #include <editeng/unolingu.hxx>
48 #include <svx/drawitem.hxx>
49 #include <editeng/fhgtitem.hxx>
50 #include <editeng/scriptspaceitem.hxx>
51 #include <svx/shapepropertynotifier.hxx>
52 #include <sfx2/viewsh.hxx>
53 #include <sfx2/docfile.hxx>
54 #include <sot/storage.hxx>
55 #include <unotools/pathoptions.hxx>
56 #include <svl/itempool.hxx>
57 #include <vcl/virdev.hxx>
58 #include <vcl/svapp.hxx>
59 #include <vcl/settings.hxx>
60 #include <unotools/ucbstreamhelper.hxx>
62 #include <basegfx/polygon/b2dpolygon.hxx>
63 #include <basegfx/polygon/b2dpolygontools.hxx>
65 #include "drwlayer.hxx"
66 #include "drawpage.hxx"
68 #include "document.hxx"
69 #include "rechead.hxx"
70 #include "userdat.hxx"
71 #include "markdata.hxx"
72 #include "globstr.hrc"
74 #include "chartarr.hxx"
77 #include "charthelper.hxx"
78 #include <basegfx/matrix/b2dhommatrix.hxx>
80 #include <vcl/field.hxx>
81 #include <boost/scoped_array.hpp>
83 #define DET_ARROW_OFFSET 1000
85 using namespace ::com::sun::star
;
87 // STATIC DATA -----------------------------------------------------------
89 static ScDrawObjFactory
* pFac
= NULL
;
90 static E3dObjFactory
* pF3d
= NULL
;
91 static sal_uInt16 nInst
= 0;
93 SfxObjectShell
* ScDrawLayer::pGlobalDrawPersist
= NULL
;
95 bool bDrawIsInUndo
= false; //TODO: Member
97 ScUndoObjData::ScUndoObjData( SdrObject
* pObjP
, const ScAddress
& rOS
, const ScAddress
& rOE
,
98 const ScAddress
& rNS
, const ScAddress
& rNE
) :
107 ScUndoObjData::~ScUndoObjData()
111 void ScUndoObjData::Undo()
113 ScDrawObjData
* pData
= ScDrawLayer::GetObjData( pObj
);
114 OSL_ENSURE(pData
,"ScUndoObjData: Data missing");
117 pData
->maStart
= aOldStt
;
118 pData
->maEnd
= aOldEnd
;
121 // Undo also an untransformed anchor
122 pData
= ScDrawLayer::GetNonRotatedObjData( pObj
);
125 pData
->maStart
= aOldStt
;
126 pData
->maEnd
= aOldEnd
;
130 void ScUndoObjData::Redo()
132 ScDrawObjData
* pData
= ScDrawLayer::GetObjData( pObj
);
133 OSL_ENSURE(pData
,"ScUndoObjData: Data missing");
136 pData
->maStart
= aNewStt
;
137 pData
->maEnd
= aNewEnd
;
140 // Redo also an untransformed anchor
141 pData
= ScDrawLayer::GetNonRotatedObjData( pObj
);
144 pData
->maStart
= aNewStt
;
145 pData
->maEnd
= aNewEnd
;
149 ScUndoAnchorData::ScUndoAnchorData( SdrObject
* pObjP
, ScDocument
* pDoc
, SCTAB nTab
) :
150 SdrUndoObj( *pObjP
),
154 mbWasCellAnchored
= ScDrawLayer::IsCellAnchored( *pObjP
);
157 ScUndoAnchorData::~ScUndoAnchorData()
161 void ScUndoAnchorData::Undo()
163 // Trigger Object Change
164 if (pObj
->IsInserted() && pObj
->GetPage() && pObj
->GetModel())
166 SdrHint
aHint(*pObj
);
167 pObj
->GetModel()->Broadcast(aHint
);
170 if (mbWasCellAnchored
)
171 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *mpDoc
, mnTab
);
173 ScDrawLayer::SetPageAnchored( *pObj
);
176 void ScUndoAnchorData::Redo()
178 if (mbWasCellAnchored
)
179 ScDrawLayer::SetPageAnchored( *pObj
);
181 ScDrawLayer::SetCellAnchoredFromPosition(*pObj
, *mpDoc
, mnTab
);
183 // Trigger Object Change
184 if (pObj
->IsInserted() && pObj
->GetPage() && pObj
->GetModel())
186 SdrHint
aHint(*pObj
);
187 pObj
->GetModel()->Broadcast(aHint
);
191 ScTabDeletedHint::ScTabDeletedHint( SCTAB nTabNo
) :
196 ScTabDeletedHint::~ScTabDeletedHint()
200 ScTabSizeChangedHint::ScTabSizeChangedHint( SCTAB nTabNo
) :
205 ScTabSizeChangedHint::~ScTabSizeChangedHint()
209 #define MAXMM 10000000
211 inline long TwipsToHmm (long nVal
)
213 return static_cast< long >( MetricField::ConvertDoubleValue (static_cast<sal_Int64
>(nVal
), 0, 0,
214 FUNIT_TWIP
, FUNIT_100TH_MM
) );
217 inline long HmmToTwips (long nVal
)
219 return static_cast< long > ( MetricField::ConvertDoubleValue (static_cast<sal_Int64
>(nVal
), 0, 0,
220 FUNIT_100TH_MM
, FUNIT_TWIP
) );
223 inline void TwipsToMM( long& nVal
)
225 nVal
= TwipsToHmm (nVal
);
228 inline void ReverseTwipsToMM( long& nVal
)
230 nVal
= HmmToTwips (nVal
);
233 static void lcl_ReverseTwipsToMM( Rectangle
& rRect
)
235 ReverseTwipsToMM( rRect
.Left() );
236 ReverseTwipsToMM( rRect
.Right() );
237 ReverseTwipsToMM( rRect
.Top() );
238 ReverseTwipsToMM( rRect
.Bottom() );
241 ScDrawLayer::ScDrawLayer( ScDocument
* pDocument
, const OUString
& rName
) :
242 FmFormModel( SvtPathOptions().GetPalettePath(),
243 NULL
, // SfxItemPool* Pool
246 ( pDocument
? pDocument
->GetDocumentShell() : NULL
),
247 true ), // bUseExtColorTable (is set below)
252 bAdjustEnabled( true ),
253 bHyphenatorSet( false )
255 pGlobalDrawPersist
= NULL
; // Only use once
257 SfxObjectShell
* pObjSh
= pDocument
? pDocument
->GetDocumentShell() : NULL
;
258 XColorListRef pXCol
= XColorList::GetStdColorList();
261 SetObjectShell( pObjSh
);
264 const SvxColorListItem
* pColItem
= static_cast<const SvxColorListItem
*>( pObjSh
->GetItem( SID_COLOR_TABLE
) );
266 pXCol
= pColItem
->GetColorList();
268 SetPropertyList( static_cast<XPropertyList
*> (pXCol
.get()) );
270 SetSwapGraphics(true);
272 SetScaleUnit(MAP_100TH_MM
);
273 SfxItemPool
& rPool
= GetItemPool();
274 rPool
.SetDefaultMetric(SFX_MAPUNIT_100TH_MM
);
275 SvxFrameDirectionItem
aModeItem( FRMDIR_ENVIRONMENT
, EE_PARA_WRITINGDIR
);
276 rPool
.SetPoolDefaultItem( aModeItem
);
279 // Set shadow distance defaults as PoolDefaultItems. Details see bug.
280 rPool
.SetPoolDefaultItem(makeSdrShadowXDistItem(300));
281 rPool
.SetPoolDefaultItem(makeSdrShadowYDistItem(300));
283 // default for script spacing depends on locale, see SdDrawDocument ctor in sd
284 LanguageType eOfficeLanguage
= Application::GetSettings().GetLanguageTag().getLanguageType();
285 if (MsLangId::isKorean(eOfficeLanguage
) || eOfficeLanguage
== LANGUAGE_JAPANESE
)
287 // secondary is edit engine pool
288 rPool
.GetSecondaryPool()->SetPoolDefaultItem( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING
) );
291 rPool
.FreezeIdRanges(); // the pool is also used directly
293 SdrLayerAdmin
& rAdmin
= GetLayerAdmin();
294 rAdmin
.NewLayer(OUString("vorne"), SC_LAYER_FRONT
);
295 rAdmin
.NewLayer(OUString("hinten"), SC_LAYER_BACK
);
296 rAdmin
.NewLayer(OUString("intern"), SC_LAYER_INTERN
);
297 rAdmin
.NewLayer(OUString("Controls"), SC_LAYER_CONTROLS
);
298 rAdmin
.NewLayer(OUString("hidden"), SC_LAYER_HIDDEN
);
299 // "Controls" is new - must also be created when loading
301 // Set link for URL-Fields
302 ScModule
* pScMod
= SC_MOD();
303 Outliner
& rOutliner
= GetDrawOutliner();
304 rOutliner
.SetCalcFieldValueHdl( LINK( pScMod
, ScModule
, CalcFieldValueHdl
) );
306 Outliner
& rHitOutliner
= GetHitTestOutliner();
307 rHitOutliner
.SetCalcFieldValueHdl( LINK( pScMod
, ScModule
, CalcFieldValueHdl
) );
309 // set FontHeight pool defaults without changing static SdrEngineDefaults
310 SfxItemPool
* pOutlinerPool
= rOutliner
.GetEditTextObjectPool();
313 pItemPool
->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT
)); // 12Pt
314 pItemPool
->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CJK
)); // 12Pt
315 pItemPool
->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CTL
)); // 12Pt
317 SfxItemPool
* pHitOutlinerPool
= rHitOutliner
.GetEditTextObjectPool();
318 if ( pHitOutlinerPool
)
320 pHitOutlinerPool
->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT
)); // 12Pt
321 pHitOutlinerPool
->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CJK
)); // 12Pt
322 pHitOutlinerPool
->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CTL
)); // 12Pt
325 // initial undo mode as in Calc document
327 EnableUndo( pDoc
->IsUndoEnabled() );
329 // URL-Buttons have no handler anymore, all is done by themselves
333 pFac
= new ScDrawObjFactory
;
334 pF3d
= new E3dObjFactory
;
338 ScDrawLayer::~ScDrawLayer()
340 Broadcast(SdrHint(HINT_MODELCLEARED
));
347 delete pFac
, pFac
= NULL
;
348 delete pF3d
, pF3d
= NULL
;
352 void ScDrawLayer::UseHyphenator()
356 com::sun::star::uno::Reference
< com::sun::star::linguistic2::XHyphenator
>
357 xHyphenator
= LinguMgr::GetHyphenator();
359 GetDrawOutliner().SetHyphenator( xHyphenator
);
360 GetHitTestOutliner().SetHyphenator( xHyphenator
);
362 bHyphenatorSet
= true;
366 SdrPage
* ScDrawLayer::AllocPage(bool bMasterPage
)
368 return new ScDrawPage(*this, bMasterPage
);
371 bool ScDrawLayer::HasObjects() const
375 sal_uInt16 nCount
= GetPageCount();
376 for (sal_uInt16 i
=0; i
<nCount
&& !bFound
; i
++)
377 if (GetPage(i
)->GetObjCount())
383 SdrModel
* ScDrawLayer::AllocModel() const
385 // Allocated model (for clipboard etc) must not have a pointer
386 // to the original model's document, pass NULL as document:
388 return new ScDrawLayer( NULL
, aName
);
391 bool ScDrawLayer::ScAddPage( SCTAB nTab
)
394 return false; // not inserted
396 ScDrawPage
* pPage
= static_cast<ScDrawPage
*>(AllocPage( false ));
397 InsertPage(pPage
, static_cast<sal_uInt16
>(nTab
));
399 AddCalcUndo(new SdrUndoNewPage(*pPage
));
401 ResetTab(nTab
, pDoc
->GetTableCount()-1);
402 return true; // inserted
405 void ScDrawLayer::ScRemovePage( SCTAB nTab
)
410 Broadcast( ScTabDeletedHint( nTab
) );
413 SdrPage
* pPage
= GetPage(static_cast<sal_uInt16
>(nTab
));
414 AddCalcUndo(new SdrUndoDelPage(*pPage
)); // Undo-Action becomes the page owner
415 RemovePage( static_cast<sal_uInt16
>(nTab
) ); // just deliver, not deleting
418 DeletePage( static_cast<sal_uInt16
>(nTab
) ); // just get rid of it
420 ResetTab(nTab
, pDoc
->GetTableCount()-1);
423 void ScDrawLayer::ScRenamePage( SCTAB nTab
, const OUString
& rNewName
)
425 ScDrawPage
* pPage
= static_cast<ScDrawPage
*>( GetPage(static_cast<sal_uInt16
>(nTab
)) );
427 pPage
->SetName(rNewName
);
430 void ScDrawLayer::ScMovePage( sal_uInt16 nOldPos
, sal_uInt16 nNewPos
)
432 MovePage( nOldPos
, nNewPos
);
433 sal_uInt16 nMinPos
= std::min(nOldPos
, nNewPos
);
434 ResetTab(nMinPos
, pDoc
->GetTableCount()-1);
437 void ScDrawLayer::ScCopyPage( sal_uInt16 nOldPos
, sal_uInt16 nNewPos
)
442 SdrPage
* pOldPage
= GetPage(nOldPos
);
443 SdrPage
* pNewPage
= GetPage(nNewPos
);
447 if (pOldPage
&& pNewPage
)
449 SCTAB nOldTab
= static_cast<SCTAB
>(nOldPos
);
450 SCTAB nNewTab
= static_cast<SCTAB
>(nNewPos
);
452 SdrObjListIter
aIter( *pOldPage
, IM_FLAT
);
453 SdrObject
* pOldObject
= aIter
.Next();
456 ScDrawObjData
* pOldData
= GetObjData(pOldObject
);
459 pOldData
->maStart
.SetTab(nOldTab
);
460 pOldData
->maEnd
.SetTab(nOldTab
);
462 SdrObject
* pNewObject
= pOldObject
->Clone();
463 pNewObject
->SetModel(this);
464 pNewObject
->SetPage(pNewPage
);
466 pNewObject
->NbcMove(Size(0,0));
467 pNewPage
->InsertObject( pNewObject
);
468 ScDrawObjData
* pNewData
= GetObjData(pNewObject
);
471 pNewData
->maStart
.SetTab(nNewTab
);
472 pNewData
->maEnd
.SetTab(nNewTab
);
476 AddCalcUndo( new SdrUndoInsertObj( *pNewObject
) );
478 pOldObject
= aIter
.Next();
482 ResetTab(static_cast<SCTAB
>(nNewPos
), pDoc
->GetTableCount()-1);
485 void ScDrawLayer::ResetTab( SCTAB nStart
, SCTAB nEnd
)
487 SCTAB nPageSize
= static_cast<SCTAB
>(GetPageCount());
489 // No drawing pages exist.
492 if (nEnd
>= nPageSize
)
493 // Avoid iterating beyond the last existing page.
494 nEnd
= nPageSize
- 1;
496 for (SCTAB i
= nStart
; i
<= nEnd
; ++i
)
498 SdrPage
* pPage
= GetPage(static_cast<sal_uInt16
>(i
));
502 SdrObjListIter
aIter(*pPage
, IM_FLAT
);
503 for (SdrObject
* pObj
= aIter
.Next(); pObj
; pObj
= aIter
.Next())
505 ScDrawObjData
* pData
= GetObjData(pObj
);
509 pData
->maStart
.SetTab(i
);
510 pData
->maEnd
.SetTab(i
);
515 inline bool IsInBlock( const ScAddress
& rPos
, SCCOL nCol1
,SCROW nRow1
, SCCOL nCol2
,SCROW nRow2
)
517 return rPos
.Col() >= nCol1
&& rPos
.Col() <= nCol2
&&
518 rPos
.Row() >= nRow1
&& rPos
.Row() <= nRow2
;
521 void ScDrawLayer::MoveCells( SCTAB nTab
, SCCOL nCol1
,SCROW nRow1
, SCCOL nCol2
,SCROW nRow2
,
522 SCsCOL nDx
,SCsROW nDy
, bool bUpdateNoteCaptionPos
)
524 SdrPage
* pPage
= GetPage(static_cast<sal_uInt16
>(nTab
));
525 OSL_ENSURE(pPage
,"Page not found");
529 bool bNegativePage
= pDoc
&& pDoc
->IsNegativePage( nTab
);
531 const size_t nCount
= pPage
->GetObjCount();
532 for ( size_t i
= 0; i
< nCount
; ++i
)
534 SdrObject
* pObj
= pPage
->GetObj( i
);
535 ScDrawObjData
* pData
= GetObjDataTab( pObj
, nTab
);
538 const ScAddress aOldStt
= pData
->maStart
;
539 const ScAddress aOldEnd
= pData
->maEnd
;
540 bool bChange
= false;
541 if ( aOldStt
.IsValid() && IsInBlock( aOldStt
, nCol1
,nRow1
, nCol2
,nRow2
) )
543 pData
->maStart
.IncCol( nDx
);
544 pData
->maStart
.IncRow( nDy
);
547 if ( aOldEnd
.IsValid() && IsInBlock( aOldEnd
, nCol1
,nRow1
, nCol2
,nRow2
) )
549 pData
->maEnd
.IncCol( nDx
);
550 pData
->maEnd
.IncRow( nDy
);
555 if ( pObj
->ISA( SdrRectObj
) && pData
->maStart
.IsValid() && pData
->maEnd
.IsValid() )
556 pData
->maStart
.PutInOrder( pData
->maEnd
);
558 // Update also an untransformed anchor thats what we stored ( and still do ) to xml
559 ScDrawObjData
* pNoRotatedAnchor
= GetNonRotatedObjData( pObj
, false );
560 if ( pNoRotatedAnchor
)
562 pNoRotatedAnchor
->maStart
= pData
->maStart
;
563 pNoRotatedAnchor
->maEnd
= pData
->maEnd
;
566 AddCalcUndo( new ScUndoObjData( pObj
, aOldStt
, aOldEnd
, pData
->maStart
, pData
->maEnd
) );
567 RecalcPos( pObj
, *pData
, bNegativePage
, bUpdateNoteCaptionPos
);
573 void ScDrawLayer::SetPageSize( sal_uInt16 nPageNo
, const Size
& rSize
, bool bUpdateNoteCaptionPos
)
575 SdrPage
* pPage
= GetPage(nPageNo
);
578 if ( rSize
!= pPage
->GetSize() )
580 pPage
->SetSize( rSize
);
581 Broadcast( ScTabSizeChangedHint( static_cast<SCTAB
>(nPageNo
) ) ); // SetWorkArea() an den Views
584 // Implement Detective lines (adjust to new heights / widths)
585 // even if size is still the same
586 // (individual rows/columns can have been changed))
588 bool bNegativePage
= pDoc
&& pDoc
->IsNegativePage( static_cast<SCTAB
>(nPageNo
) );
590 const size_t nCount
= pPage
->GetObjCount();
591 for ( size_t i
= 0; i
< nCount
; ++i
)
593 SdrObject
* pObj
= pPage
->GetObj( i
);
594 ScDrawObjData
* pData
= GetObjDataTab( pObj
, static_cast<SCTAB
>(nPageNo
) );
596 RecalcPos( pObj
, *pData
, bNegativePage
, bUpdateNoteCaptionPos
);
603 //Can't have a zero width dimension
604 Rectangle
lcl_makeSafeRectangle(const Rectangle
&rNew
)
606 Rectangle aRect
= rNew
;
607 if (aRect
.Bottom() == aRect
.Top())
608 aRect
.Bottom() = aRect
.Top()+1;
609 if (aRect
.Right() == aRect
.Left())
610 aRect
.Right() = aRect
.Left()+1;
614 Point
lcl_calcAvailableDiff(ScDocument
&rDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
, const Point
&aWantedDiff
)
616 Point
aAvailableDiff(aWantedDiff
);
617 long nHeight
= static_cast<long>(rDoc
.GetRowHeight( nRow
, nTab
) * HMM_PER_TWIPS
);
618 long nWidth
= static_cast<long>(rDoc
.GetColWidth( nCol
, nTab
) * HMM_PER_TWIPS
);
619 if (aAvailableDiff
.Y() > nHeight
)
620 aAvailableDiff
.Y() = nHeight
;
621 if (aAvailableDiff
.X() > nWidth
)
622 aAvailableDiff
.X() = nWidth
;
623 return aAvailableDiff
;
626 Rectangle
lcl_UpdateCalcPoly(basegfx::B2DPolygon
&rCalcPoly
, int nWhichPoint
, const Point
&rPos
)
628 rCalcPoly
.setB2DPoint(nWhichPoint
, basegfx::B2DPoint(rPos
.X(), rPos
.Y()));
629 basegfx::B2DRange
aRange(basegfx::tools::getRange(rCalcPoly
));
630 return Rectangle(static_cast<long>(aRange
.getMinX()), static_cast<long>(aRange
.getMinY()),
631 static_cast<long>(aRange
.getMaxX()), static_cast<long>(aRange
.getMaxY()));
634 void ScDrawLayer::ResizeLastRectFromAnchor( SdrObject
* pObj
, ScDrawObjData
& rData
, bool bUseLogicRect
, bool bNegativePage
, bool bCanResize
, bool bHiddenAsZero
)
636 rData
.maLastRect
= ( bUseLogicRect
? pObj
->GetLogicRect() : pObj
->GetSnapRect() );
637 SCCOL nCol1
= rData
.maStart
.Col();
638 SCROW nRow1
= rData
.maStart
.Row();
639 SCTAB nTab1
= rData
.maStart
.Tab();
640 SCCOL nCol2
= rData
.maEnd
.Col();
641 SCROW nRow2
= rData
.maEnd
.Row();
642 SCTAB nTab2
= rData
.maEnd
.Tab();
643 Point
aPos( pDoc
->GetColOffset( nCol1
, nTab1
, bHiddenAsZero
), pDoc
->GetRowOffset( nRow1
, nTab1
, bHiddenAsZero
) );
644 TwipsToMM( aPos
.X() );
645 TwipsToMM( aPos
.Y() );
646 aPos
+= lcl_calcAvailableDiff(*pDoc
, nCol1
, nRow1
, nTab1
, rData
.maStartOffset
);
650 Point
aEnd( pDoc
->GetColOffset( nCol2
, nTab2
, bHiddenAsZero
), pDoc
->GetRowOffset( nRow2
, nTab2
, bHiddenAsZero
) );
651 TwipsToMM( aEnd
.X() );
652 TwipsToMM( aEnd
.Y() );
653 aEnd
+= lcl_calcAvailableDiff(*pDoc
, nCol2
, nRow2
, nTab2
, rData
.maEndOffset
);
655 Rectangle aNew
= Rectangle( aPos
, aEnd
);
657 MirrorRectRTL( aNew
);
659 rData
.maLastRect
= lcl_makeSafeRectangle(aNew
);
664 aPos
.X() = -aPos
.X() - rData
.maLastRect
.GetWidth();
665 // shouldn't we initialise maLastRect with the object rectangle ?
666 rData
.maLastRect
.SetPos( aPos
);
670 void ScDrawLayer::RecalcPos( SdrObject
* pObj
, ScDrawObjData
& rData
, bool bNegativePage
, bool bUpdateNoteCaptionPos
)
672 OSL_ENSURE( pDoc
, "ScDrawLayer::RecalcPos - missing document" );
676 if (rData
.meType
== ScDrawObjData::CellNote
)
678 OSL_ENSURE( rData
.maStart
.IsValid(), "ScDrawLayer::RecalcPos - invalid position for cell note" );
679 /* #i109372# On insert/remove rows/columns/cells: Updating the caption
680 position must not be done, if the cell containing the note has not
681 been moved yet in the document. The calling code now passes an
682 additional boolean stating if the cells are already moved. */
683 if( bUpdateNoteCaptionPos
)
684 /* When inside an undo action, there may be pending note captions
685 where cell note is already deleted (thus document cannot find
686 the note object anymore). The caption will be deleted later
687 with drawing undo. */
688 if( ScPostIt
* pNote
= pDoc
->GetNote( rData
.maStart
) )
689 pNote
->UpdateCaptionPos( rData
.maStart
);
693 bool bValid1
= rData
.maStart
.IsValid();
694 SCCOL nCol1
= rData
.maStart
.Col();
695 SCROW nRow1
= rData
.maStart
.Row();
696 SCTAB nTab1
= rData
.maStart
.Tab();
697 bool bValid2
= rData
.maEnd
.IsValid();
698 SCCOL nCol2
= rData
.maEnd
.Col();
699 SCROW nRow2
= rData
.maEnd
.Row();
700 SCTAB nTab2
= rData
.maEnd
.Tab();
702 if (rData
.meType
== ScDrawObjData::ValidationCircle
)
704 // Validation circle for detective.
705 rData
.maLastRect
= pObj
->GetLogicRect();
707 Point
aPos( pDoc
->GetColOffset( nCol1
, nTab1
), pDoc
->GetRowOffset( nRow1
, nTab1
) );
708 TwipsToMM( aPos
.X() );
709 TwipsToMM( aPos
.Y() );
711 // Calculations and values as in detfunc.cxx
713 Size
aSize( (long)( TwipsToHmm( pDoc
->GetColWidth( nCol1
, nTab1
) ) ),
714 (long)( TwipsToHmm( pDoc
->GetRowHeight( nRow1
, nTab1
) ) ) );
715 Rectangle
aRect( aPos
, aSize
);
717 aRect
.Right() += 250;
719 aRect
.Bottom() += 70;
721 MirrorRectRTL( aRect
);
723 if ( pObj
->GetLogicRect() != aRect
)
726 AddCalcUndo( new SdrUndoGeoObj( *pObj
) );
727 rData
.maLastRect
= lcl_makeSafeRectangle(aRect
);
728 pObj
->SetLogicRect(rData
.maLastRect
);
731 else if (rData
.meType
== ScDrawObjData::DetectiveArrow
)
733 rData
.maLastRect
= pObj
->GetLogicRect();
734 basegfx::B2DPolygon aCalcPoly
;
735 Point
aOrigStartPos(pObj
->GetPoint(0));
736 Point
aOrigEndPos(pObj
->GetPoint(1));
737 aCalcPoly
.append(basegfx::B2DPoint(aOrigStartPos
.X(), aOrigStartPos
.Y()));
738 aCalcPoly
.append(basegfx::B2DPoint(aOrigEndPos
.X(), aOrigEndPos
.Y()));
739 //TODO: do not create multiple Undos for one object (last one can be omitted then)
745 Point
aPos( pDoc
->GetColOffset( nCol1
, nTab1
), pDoc
->GetRowOffset( nRow1
, nTab1
) );
746 if (!pDoc
->ColHidden(nCol1
, nTab1
, NULL
, &nLastCol
))
747 aPos
.X() += pDoc
->GetColWidth( nCol1
, nTab1
) / 4;
748 if (!pDoc
->RowHidden(nRow1
, nTab1
, NULL
, &nLastRow
))
749 aPos
.Y() += pDoc
->GetRowHeight( nRow1
, nTab1
) / 2;
750 TwipsToMM( aPos
.X() );
751 TwipsToMM( aPos
.Y() );
752 Point aStartPos
= aPos
;
754 aStartPos
.X() = -aStartPos
.X(); // don't modify aPos - used below
755 if ( pObj
->GetPoint( 0 ) != aStartPos
)
758 AddCalcUndo( new SdrUndoGeoObj( *pObj
) );
760 rData
.maLastRect
= lcl_UpdateCalcPoly(aCalcPoly
, 0, aStartPos
);
761 pObj
->SetPoint( aStartPos
, 0 );
766 Point
aEndPos( aPos
.X() + DET_ARROW_OFFSET
, aPos
.Y() - DET_ARROW_OFFSET
);
768 aEndPos
.Y() += (2 * DET_ARROW_OFFSET
);
770 aEndPos
.X() = -aEndPos
.X();
771 if ( pObj
->GetPoint( 1 ) != aEndPos
)
774 AddCalcUndo( new SdrUndoGeoObj( *pObj
) );
776 rData
.maLastRect
= lcl_UpdateCalcPoly(aCalcPoly
, 1, aEndPos
);
777 pObj
->SetPoint( aEndPos
, 1 );
783 Point
aPos( pDoc
->GetColOffset( nCol2
, nTab2
), pDoc
->GetRowOffset( nRow2
, nTab2
) );
784 if (!pDoc
->ColHidden(nCol2
, nTab2
, NULL
, &nLastCol
))
785 aPos
.X() += pDoc
->GetColWidth( nCol2
, nTab2
) / 4;
786 if (!pDoc
->RowHidden(nRow2
, nTab2
, NULL
, &nLastRow
))
787 aPos
.Y() += pDoc
->GetRowHeight( nRow2
, nTab2
) / 2;
788 TwipsToMM( aPos
.X() );
789 TwipsToMM( aPos
.Y() );
790 Point aEndPos
= aPos
;
792 aEndPos
.X() = -aEndPos
.X(); // don't modify aPos - used below
793 if ( pObj
->GetPoint( 1 ) != aEndPos
)
796 AddCalcUndo( new SdrUndoGeoObj( *pObj
) );
798 rData
.maLastRect
= lcl_UpdateCalcPoly(aCalcPoly
, 1, aEndPos
);
799 pObj
->SetPoint( aEndPos
, 1 );
804 Point
aStartPos( aPos
.X() - DET_ARROW_OFFSET
, aPos
.Y() - DET_ARROW_OFFSET
);
805 if (aStartPos
.X() < 0)
806 aStartPos
.X() += (2 * DET_ARROW_OFFSET
);
807 if (aStartPos
.Y() < 0)
808 aStartPos
.Y() += (2 * DET_ARROW_OFFSET
);
810 aStartPos
.X() = -aStartPos
.X();
811 if ( pObj
->GetPoint( 0 ) != aStartPos
)
814 AddCalcUndo( new SdrUndoGeoObj( *pObj
) );
816 rData
.maLastRect
= lcl_UpdateCalcPoly(aCalcPoly
, 0, aStartPos
);
817 pObj
->SetPoint( aStartPos
, 0 );
824 bool bCanResize
= bValid2
&& !pObj
->IsResizeProtect();
826 //First time positioning, must be able to at least move it
827 ScDrawObjData
& rNoRotatedAnchor
= *GetNonRotatedObjData( pObj
, true );
828 if (rData
.maLastRect
.IsEmpty())
830 // Every shape it is saved with an negative offset relative to cell
831 if (ScDrawLayer::GetAnchorType(*pObj
) == SCA_CELL
)
839 basegfx::B2DTuple aScale
;
840 basegfx::B2DTuple aTranslate
;
841 basegfx::B2DPolyPolygon aPolyPolygon
;
842 basegfx::B2DHomMatrix aOriginalMatrix
;
844 aRect
= pDoc
->GetMMRect(nCol1
, nRow1
, nCol1
, nRow1
, nTab1
);
847 aPoint
.X() = aRect
.Right();
849 aPoint
.X() = aRect
.Left();
850 aPoint
.Y() = aRect
.Top();
852 pObj
->TRGetBaseGeometry(aOriginalMatrix
, aPolyPolygon
);
853 aOriginalMatrix
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
854 aTranslate
+= ::basegfx::B2DTuple(aPoint
.X(), aPoint
.Y());
855 aOriginalMatrix
= basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
860 pObj
->TRSetBaseGeometry(aOriginalMatrix
, aPolyPolygon
);
863 // It's confusing ( but blame that we persist the anchor in terms of unrotated shape )
864 // that the initial anchor we get here is in terms of an unrotated shape ( if the shape is rotated )
865 // we need to save the old anchor ( for persisting ) and also track any resize or repositions that happen.
867 // This is an evil hack, having a anchor that is one minute in terms of untransformed object and then later
868 // in terms of the transformed object is not ideal, similary having 2 anchors per object is wasteful, can't
869 // see another way out of this at the moment though.
870 rNoRotatedAnchor
.maStart
= rData
.maStart
;
871 rNoRotatedAnchor
.maEnd
= rData
.maEnd
;
872 rNoRotatedAnchor
.maStartOffset
= rData
.maStartOffset
;
873 rNoRotatedAnchor
.maEndOffset
= rData
.maEndOffset
;
875 Rectangle aRect
= pObj
->GetLogicRect();
877 // get bounding rectangle of shape ( include any hidden row/columns ), <sigh> we need to do this
878 // because if the shape is rotated the anchor from xml is in terms of the unrotated shape, if
879 // the shape is hidden ( by the rows that contain the shape being hidden ) then our hack of
880 // trying to infer the 'real' e.g. rotated anchor from the SnapRect will fail ( because the LogicRect will
881 // not have the correct position or size ) The only way we can possible do this is to first get the
882 // 'unrotated' shape dimensions from the persisted Anchor (from xml) and then 'create' an Anchor from the
883 // associated rotated shape ( note: we do this by actually setting the LogicRect for the shape temporarily to the
884 // *full* size then grabbing the SnapRect ( which gives the transformed rotated dimensions ), it would be
885 // wonderful if we could do this mathematically without having to temporarily tweak the object... othoh this way
886 // is guaranteed to get consistent results )
887 ResizeLastRectFromAnchor( pObj
, rData
, true, bNegativePage
, bCanResize
, false );
888 // aFullRect contains the unrotated size and position of the shape ( regardless of any hidden row/columns )
889 Rectangle aFullRect
= rData
.maLastRect
;
891 // get current size and position from the anchor for use later
892 ResizeLastRectFromAnchor( pObj
, rNoRotatedAnchor
, true, bNegativePage
, bCanResize
);
894 // resize/position the shape to *full* size e.g. how it would be ( if no hidden rows/cols affected things )
895 pObj
->SetLogicRect(aFullRect
);
896 // capture rotated shape ( if relevant )
897 aRect
= pObj
->GetSnapRect();
899 // Ok, here is more nastyness, from xml the Anchor is in terms of the LogicRect which is the
900 // untransformed unrotated shape, here we swap out that initial anchor and from now on use
901 // an Anchor based on the SnapRect ( which is what you see on the screen )
902 ScDrawLayer::GetCellAnchorFromPosition( *pObj
, rData
, *pDoc
, nTab1
, false, false );
903 // reset shape to true 'maybe affected by hidden rows/cols' size calculated previously
904 pObj
->SetLogicRect(rNoRotatedAnchor
.maLastRect
);
907 // update anchor with snap rect
908 ResizeLastRectFromAnchor( pObj
, rData
, false, bNegativePage
, bCanResize
);
912 Rectangle aNew
= rData
.maLastRect
;
914 if ( pObj
->GetSnapRect() != aNew
)
916 Rectangle
aOld(pObj
->GetSnapRect());
919 AddCalcUndo( new SdrUndoGeoObj( *pObj
) );
920 long nOldWidth
= aOld
.GetWidth();
921 long nOldHeight
= aOld
.GetHeight();
922 if (pObj
->IsPolyObj() && nOldWidth
&& nOldHeight
)
924 // Polyline objects need special treatment.
925 Size
aSizeMove(aNew
.Left()-aOld
.Left(), aNew
.Top()-aOld
.Top());
926 pObj
->NbcMove(aSizeMove
);
928 double fXFrac
= static_cast<double>(aNew
.GetWidth()) / static_cast<double>(nOldWidth
);
929 double fYFrac
= static_cast<double>(aNew
.GetHeight()) / static_cast<double>(nOldHeight
);
930 pObj
->NbcResize(aNew
.TopLeft(), Fraction(fXFrac
), Fraction(fYFrac
));
932 // order of these lines is important, modify rData.maLastRect carefully it is used as both
933 // a value and a flag for initialisation
934 rData
.maLastRect
= lcl_makeSafeRectangle(rData
.maLastRect
);
935 pObj
->SetSnapRect(rData
.maLastRect
);
936 // update 'unrotated anchor' it's the anchor we persist, it must be kept in sync
937 // with the normal Anchor
938 ResizeLastRectFromAnchor( pObj
, rNoRotatedAnchor
, true, bNegativePage
, bCanResize
);
943 Point
aPos( rData
.maLastRect
.getX(), rData
.maLastRect
.getY() );
944 if ( pObj
->GetRelativePos() != aPos
)
947 AddCalcUndo( new SdrUndoGeoObj( *pObj
) );
948 pObj
->SetRelativePos( aPos
);
952 * If we were not allowed resize the object, then the end cell anchor
953 * is possibly incorrect now, and if the object has no end-cell (e.g.
954 * missing in original .xml) we are also forced to generate one
956 bool bEndAnchorIsBad
= !bValid2
|| pObj
->IsResizeProtect();
959 // update 'rotated' anchor
960 ScDrawLayer::UpdateCellAnchorFromPositionEnd(*pObj
, rData
, *pDoc
, nTab1
, false);
961 // update 'unrotated' anchor
962 ScDrawLayer::UpdateCellAnchorFromPositionEnd(*pObj
, rNoRotatedAnchor
, *pDoc
, nTab1
);
967 bool ScDrawLayer::GetPrintArea( ScRange
& rRange
, bool bSetHor
, bool bSetVer
) const
969 OSL_ENSURE( pDoc
, "ScDrawLayer::GetPrintArea without document" );
973 SCTAB nTab
= rRange
.aStart
.Tab();
974 OSL_ENSURE( rRange
.aEnd
.Tab() == nTab
, "GetPrintArea: Tab differ" );
976 bool bNegativePage
= pDoc
->IsNegativePage( nTab
);
981 long nStartX
= LONG_MAX
;
982 long nStartY
= LONG_MAX
;
989 SCCOL nStartCol
= rRange
.aStart
.Col();
991 for (i
=0; i
<nStartCol
; i
++)
992 nStartX
+=pDoc
->GetColWidth(i
,nTab
);
994 SCCOL nEndCol
= rRange
.aEnd
.Col();
995 for (i
=nStartCol
; i
<=nEndCol
; i
++)
996 nEndX
+= pDoc
->GetColWidth(i
,nTab
);
997 nStartX
= TwipsToHmm( nStartX
);
998 nEndX
= TwipsToHmm( nEndX
);
1002 nStartY
= pDoc
->GetRowHeight( 0, rRange
.aStart
.Row()-1, nTab
);
1003 nEndY
= nStartY
+ pDoc
->GetRowHeight( rRange
.aStart
.Row(),
1004 rRange
.aEnd
.Row(), nTab
);
1005 nStartY
= TwipsToHmm( nStartY
);
1006 nEndY
= TwipsToHmm( nEndY
);
1009 if ( bNegativePage
)
1011 nStartX
= -nStartX
; // positions are negative, swap start/end so the same comparisons work
1013 ::std::swap( nStartX
, nEndX
);
1016 const SdrPage
* pPage
= GetPage(static_cast<sal_uInt16
>(nTab
));
1017 OSL_ENSURE(pPage
,"Page not found");
1020 SdrObjListIter
aIter( *pPage
, IM_FLAT
);
1021 SdrObject
* pObject
= aIter
.Next();
1024 //TODO: test Flags (hidden?)
1026 Rectangle aObjRect
= pObject
->GetCurrentBoundRect();
1028 if ( !bSetHor
&& ( aObjRect
.Right() < nStartX
|| aObjRect
.Left() > nEndX
) )
1030 if ( !bSetVer
&& ( aObjRect
.Bottom() < nStartY
|| aObjRect
.Top() > nEndY
) )
1032 // #i104716# don't include hidden note objects
1033 if ( bFit
&& pObject
->GetLayer() != SC_LAYER_HIDDEN
)
1037 if (aObjRect
.Left() < nStartX
) nStartX
= aObjRect
.Left();
1038 if (aObjRect
.Right() > nEndX
) nEndX
= aObjRect
.Right();
1042 if (aObjRect
.Top() < nStartY
) nStartY
= aObjRect
.Top();
1043 if (aObjRect
.Bottom() > nEndY
) nEndY
= aObjRect
.Bottom();
1048 pObject
= aIter
.Next();
1052 if ( bNegativePage
)
1054 nStartX
= -nStartX
; // reverse transformation, so the same cell address calculation works
1056 ::std::swap( nStartX
, nEndX
);
1061 OSL_ENSURE( nStartX
<=nEndX
&& nStartY
<=nEndY
, "Start/End wrong in ScDrawLayer::GetPrintArea" );
1065 nStartX
= HmmToTwips( nStartX
);
1066 nEndX
= HmmToTwips( nEndX
);
1071 for (i
=0; i
<=MAXCOL
&& nWidth
<=nStartX
; i
++)
1072 nWidth
+= pDoc
->GetColWidth(i
,nTab
);
1073 rRange
.aStart
.SetCol( i
>0 ? (i
-1) : 0 );
1076 for (i
=0; i
<=MAXCOL
&& nWidth
<=nEndX
; i
++) //TODO: start at Start
1077 nWidth
+= pDoc
->GetColWidth(i
,nTab
);
1078 rRange
.aEnd
.SetCol( i
>0 ? (i
-1) : 0 );
1083 nStartY
= HmmToTwips( nStartY
);
1084 nEndY
= HmmToTwips( nEndY
);
1085 SCROW nRow
= pDoc
->GetRowForHeight( nTab
, nStartY
);
1086 rRange
.aStart
.SetRow( nRow
>0 ? (nRow
-1) : 0);
1087 nRow
= pDoc
->GetRowForHeight( nTab
, nEndY
);
1088 rRange
.aEnd
.SetRow( nRow
== MAXROW
? MAXROW
:
1089 (nRow
>0 ? (nRow
-1) : 0));
1096 rRange
.aStart
.SetCol(0);
1097 rRange
.aEnd
.SetCol(0);
1101 rRange
.aStart
.SetRow(0);
1102 rRange
.aEnd
.SetRow(0);
1108 void ScDrawLayer::AddCalcUndo( SdrUndoAction
* pUndo
)
1113 pUndoGroup
= new SdrUndoGroup(*this);
1115 pUndoGroup
->AddAction( pUndo
);
1121 void ScDrawLayer::BeginCalcUndo(bool bDisableTextEditUsesCommonUndoManager
)
1123 SetDisableTextEditUsesCommonUndoManager(bDisableTextEditUsesCommonUndoManager
);
1124 DELETEZ(pUndoGroup
);
1128 SdrUndoGroup
* ScDrawLayer::GetCalcUndo()
1130 SdrUndoGroup
* pRet
= pUndoGroup
;
1133 SetDisableTextEditUsesCommonUndoManager(false);
1137 void ScDrawLayer::MoveArea( SCTAB nTab
, SCCOL nCol1
,SCROW nRow1
, SCCOL nCol2
,SCROW nRow2
,
1138 SCsCOL nDx
,SCsROW nDy
, bool bInsDel
, bool bUpdateNoteCaptionPos
)
1140 OSL_ENSURE( pDoc
, "ScDrawLayer::MoveArea without document" );
1144 if (!bAdjustEnabled
)
1147 bool bNegativePage
= pDoc
->IsNegativePage( nTab
);
1149 Rectangle aRect
= pDoc
->GetMMRect( nCol1
, nRow1
, nCol2
, nRow2
, nTab
);
1150 lcl_ReverseTwipsToMM( aRect
);
1151 //TODO: use twips directly?
1156 for (SCsCOL s
=0; s
<nDx
; s
++)
1157 aMove
.X() += pDoc
->GetColWidth(s
+(SCsCOL
)nCol1
,nTab
);
1159 for (SCsCOL s
=-1; s
>=nDx
; s
--)
1160 aMove
.X() -= pDoc
->GetColWidth(s
+(SCsCOL
)nCol1
,nTab
);
1162 aMove
.Y() += pDoc
->GetRowHeight( nRow1
, nRow1
+nDy
-1, nTab
);
1164 aMove
.Y() -= pDoc
->GetRowHeight( nRow1
+nDy
, nRow1
-1, nTab
);
1166 if ( bNegativePage
)
1167 aMove
.X() = -aMove
.X();
1169 Point aTopLeft
= aRect
.TopLeft(); // Beginning when zoomed out
1172 if ( aMove
.X() != 0 && nDx
< 0 ) // nDx counts cells, sign is independent of RTL
1173 aTopLeft
.X() += aMove
.X();
1174 if ( aMove
.Y() < 0 )
1175 aTopLeft
.Y() += aMove
.Y();
1178 // Detectiv arrows: Adjust cell position
1180 MoveCells( nTab
, nCol1
,nRow1
, nCol2
,nRow2
, nDx
,nDy
, bUpdateNoteCaptionPos
);
1183 bool ScDrawLayer::HasObjectsInRows( SCTAB nTab
, SCROW nStartRow
, SCROW nEndRow
)
1185 OSL_ENSURE( pDoc
, "ScDrawLayer::HasObjectsInRows without document" );
1189 SdrPage
* pPage
= GetPage(static_cast<sal_uInt16
>(nTab
));
1190 OSL_ENSURE(pPage
,"Page not found");
1194 // for an empty page, there's no need to calculate the row heights
1195 if (!pPage
->GetObjCount())
1198 Rectangle aTestRect
;
1200 aTestRect
.Top() += pDoc
->GetRowHeight( 0, nStartRow
-1, nTab
);
1202 if (nEndRow
==MAXROW
)
1203 aTestRect
.Bottom() = MAXMM
;
1206 aTestRect
.Bottom() = aTestRect
.Top();
1207 aTestRect
.Bottom() += pDoc
->GetRowHeight( nStartRow
, nEndRow
, nTab
);
1208 TwipsToMM( aTestRect
.Bottom() );
1211 TwipsToMM( aTestRect
.Top() );
1213 aTestRect
.Left() = 0;
1214 aTestRect
.Right() = MAXMM
;
1216 bool bNegativePage
= pDoc
->IsNegativePage( nTab
);
1217 if ( bNegativePage
)
1218 MirrorRectRTL( aTestRect
);
1220 bool bFound
= false;
1223 SdrObjListIter
aIter( *pPage
);
1224 SdrObject
* pObject
= aIter
.Next();
1225 while ( pObject
&& !bFound
)
1227 aObjRect
= pObject
->GetSnapRect(); //TODO: GetLogicRect ?
1228 if (aTestRect
.IsInside(aObjRect
.TopLeft()) || aTestRect
.IsInside(aObjRect
.BottomLeft()))
1231 pObject
= aIter
.Next();
1237 void ScDrawLayer::DeleteObjectsInArea( SCTAB nTab
, SCCOL nCol1
,SCROW nRow1
,
1238 SCCOL nCol2
,SCROW nRow2
)
1240 OSL_ENSURE( pDoc
, "ScDrawLayer::DeleteObjectsInArea without document" );
1244 SdrPage
* pPage
= GetPage(static_cast<sal_uInt16
>(nTab
));
1245 OSL_ENSURE(pPage
,"Page ?");
1249 pPage
->RecalcObjOrdNums();
1251 const size_t nObjCount
= pPage
->GetObjCount();
1254 size_t nDelCount
= 0;
1255 Rectangle aDelRect
= pDoc
->GetMMRect( nCol1
, nRow1
, nCol2
, nRow2
, nTab
);
1257 boost::scoped_array
<SdrObject
*> ppObj(new SdrObject
*[nObjCount
]);
1259 SdrObjListIter
aIter( *pPage
, IM_FLAT
);
1260 SdrObject
* pObject
= aIter
.Next();
1263 // do not delete note caption, they are always handled by the cell note
1264 // TODO: detective objects are still deleted, is this desired?
1265 if (!IsNoteCaption( pObject
))
1267 Rectangle aObjRect
= pObject
->GetCurrentBoundRect();
1268 if ( aDelRect
.IsInside( aObjRect
) )
1269 ppObj
[nDelCount
++] = pObject
;
1272 pObject
= aIter
.Next();
1276 for (size_t i
=1; i
<=nDelCount
; ++i
)
1277 AddCalcUndo( new SdrUndoRemoveObj( *ppObj
[nDelCount
-i
] ) );
1279 for (size_t i
=1; i
<=nDelCount
; ++i
)
1280 pPage
->RemoveObject( ppObj
[nDelCount
-i
]->GetOrdNum() );
1284 void ScDrawLayer::DeleteObjectsInSelection( const ScMarkData
& rMark
)
1286 OSL_ENSURE( pDoc
, "ScDrawLayer::DeleteObjectsInSelection without document" );
1290 if ( !rMark
.IsMultiMarked() )
1294 rMark
.GetMultiMarkArea( aMarkRange
);
1296 SCTAB nTabCount
= pDoc
->GetTableCount();
1297 ScMarkData::const_iterator itr
= rMark
.begin(), itrEnd
= rMark
.end();
1298 for (; itr
!= itrEnd
&& *itr
< nTabCount
; ++itr
)
1301 SdrPage
* pPage
= GetPage(static_cast<sal_uInt16
>(nTab
));
1304 pPage
->RecalcObjOrdNums();
1305 const size_t nObjCount
= pPage
->GetObjCount();
1308 size_t nDelCount
= 0;
1309 // Rectangle around the whole selection
1310 Rectangle aMarkBound
= pDoc
->GetMMRect(
1311 aMarkRange
.aStart
.Col(), aMarkRange
.aStart
.Row(),
1312 aMarkRange
.aEnd
.Col(), aMarkRange
.aEnd
.Row(), nTab
);
1314 boost::scoped_array
<SdrObject
*> ppObj(new SdrObject
*[nObjCount
]);
1316 SdrObjListIter
aIter( *pPage
, IM_FLAT
);
1317 SdrObject
* pObject
= aIter
.Next();
1320 // do not delete note caption, they are always handled by the cell note
1321 // TODO: detective objects are still deleted, is this desired?
1322 if (!IsNoteCaption( pObject
))
1324 Rectangle aObjRect
= pObject
->GetCurrentBoundRect();
1325 if ( aMarkBound
.IsInside( aObjRect
) )
1327 ScRange aRange
= pDoc
->GetRange( nTab
, aObjRect
);
1328 if (rMark
.IsAllMarked(aRange
))
1329 ppObj
[nDelCount
++] = pObject
;
1333 pObject
= aIter
.Next();
1336 // Delete objects (backwards)
1339 for (size_t i
=1; i
<=nDelCount
; ++i
)
1340 AddCalcUndo( new SdrUndoRemoveObj( *ppObj
[nDelCount
-i
] ) );
1342 for (size_t i
=1; i
<=nDelCount
; ++i
)
1343 pPage
->RemoveObject( ppObj
[nDelCount
-i
]->GetOrdNum() );
1353 void ScDrawLayer::CopyToClip( ScDocument
* pClipDoc
, SCTAB nTab
, const Rectangle
& rRange
)
1355 // copy everything in the specified range into the same page (sheet) in the clipboard doc
1357 SdrPage
* pSrcPage
= GetPage(static_cast<sal_uInt16
>(nTab
));
1360 ScDrawLayer
* pDestModel
= NULL
;
1361 SdrPage
* pDestPage
= NULL
;
1363 SdrObjListIter
aIter( *pSrcPage
, IM_FLAT
);
1364 SdrObject
* pOldObject
= aIter
.Next();
1367 Rectangle aObjRect
= pOldObject
->GetCurrentBoundRect();
1368 // do not copy internal objects (detective) and note captions
1369 if ( rRange
.IsInside( aObjRect
) && (pOldObject
->GetLayer() != SC_LAYER_INTERN
) && !IsNoteCaption( pOldObject
) )
1373 pDestModel
= pClipDoc
->GetDrawLayer(); // does the document already have a drawing layer?
1376 // allocate drawing layer in clipboard document only if there are objects to copy
1378 pClipDoc
->InitDrawLayer(); //TODO: create contiguous pages
1379 pDestModel
= pClipDoc
->GetDrawLayer();
1382 pDestPage
= pDestModel
->GetPage( static_cast<sal_uInt16
>(nTab
) );
1385 OSL_ENSURE( pDestPage
, "no page" );
1388 SdrObject
* pNewObject
= pOldObject
->Clone();
1389 pNewObject
->SetModel(pDestModel
);
1390 pNewObject
->SetPage(pDestPage
);
1392 uno::Reference
< chart2::XChartDocument
> xOldChart( ScChartHelper::GetChartFromSdrObject( pOldObject
) );
1393 if(!xOldChart
.is())//#i110034# do not move charts as they lose all their data references otherwise
1394 pNewObject
->NbcMove(Size(0,0));
1395 pDestPage
->InsertObject( pNewObject
);
1397 // no undo needed in clipboard document
1398 // charts are not updated
1402 pOldObject
= aIter
.Next();
1407 static bool lcl_IsAllInRange( const ::std::vector
< ScRangeList
>& rRangesVector
, const ScRange
& rClipRange
)
1409 // check if every range of rRangesVector is completely in rClipRange
1411 ::std::vector
< ScRangeList
>::const_iterator aIt
= rRangesVector
.begin();
1412 for( ;aIt
!=rRangesVector
.end(); ++aIt
)
1414 const ScRangeList
& rRanges
= *aIt
;
1415 for ( size_t i
= 0, nCount
= rRanges
.size(); i
< nCount
; i
++ )
1417 ScRange aRange
= *rRanges
[ i
];
1418 if ( !rClipRange
.In( aRange
) )
1420 return false; // at least one range is not valid
1425 return true; // everything is fine
1428 static bool lcl_MoveRanges( ::std::vector
< ScRangeList
>& rRangesVector
, const ScRange
& rSourceRange
, const ScAddress
& rDestPos
)
1430 bool bChanged
= false;
1432 ::std::vector
< ScRangeList
>::iterator aIt
= rRangesVector
.begin();
1433 for( ;aIt
!=rRangesVector
.end(); ++aIt
)
1435 ScRangeList
& rRanges
= *aIt
;
1436 for ( size_t i
= 0, nCount
= rRanges
.size(); i
< nCount
; i
++ )
1438 ScRange
* pRange
= rRanges
[ i
];
1439 if ( rSourceRange
.In( *pRange
) )
1441 SCsCOL nDiffX
= rDestPos
.Col() - (SCsCOL
)rSourceRange
.aStart
.Col();
1442 SCsROW nDiffY
= rDestPos
.Row() - (SCsROW
)rSourceRange
.aStart
.Row();
1443 SCsTAB nDiffZ
= rDestPos
.Tab() - (SCsTAB
)rSourceRange
.aStart
.Tab();
1444 pRange
->Move( nDiffX
, nDiffY
, nDiffZ
);
1453 void ScDrawLayer::CopyFromClip( ScDrawLayer
* pClipModel
, SCTAB nSourceTab
, const Rectangle
& rSourceRange
,
1454 const ScAddress
& rDestPos
, const Rectangle
& rDestRange
)
1456 OSL_ENSURE( pDoc
, "ScDrawLayer::CopyFromClip without document" );
1463 if (bDrawIsInUndo
) //TODO: can this happen?
1465 OSL_FAIL("CopyFromClip, bDrawIsInUndo");
1469 bool bMirrorObj
= ( rSourceRange
.Left() < 0 && rSourceRange
.Right() < 0 &&
1470 rDestRange
.Left() > 0 && rDestRange
.Right() > 0 ) ||
1471 ( rSourceRange
.Left() > 0 && rSourceRange
.Right() > 0 &&
1472 rDestRange
.Left() < 0 && rDestRange
.Right() < 0 );
1473 Rectangle aMirroredSource
= rSourceRange
;
1475 MirrorRectRTL( aMirroredSource
);
1477 SCTAB nDestTab
= rDestPos
.Tab();
1479 SdrPage
* pSrcPage
= pClipModel
->GetPage(static_cast<sal_uInt16
>(nSourceTab
));
1480 SdrPage
* pDestPage
= GetPage(static_cast<sal_uInt16
>(nDestTab
));
1481 OSL_ENSURE( pSrcPage
&& pDestPage
, "draw page missing" );
1482 if ( !pSrcPage
|| !pDestPage
)
1485 SdrObjListIter
aIter( *pSrcPage
, IM_FLAT
);
1486 SdrObject
* pOldObject
= aIter
.Next();
1488 ScDocument
* pClipDoc
= pClipModel
->GetDocument();
1489 // a clipboard document and its source share the same document item pool,
1490 // so the pointers can be compared to see if this is copy&paste within
1491 // the same document
1492 bool bSameDoc
= pDoc
&& pClipDoc
&& pDoc
->GetPool() == pClipDoc
->GetPool();
1493 bool bDestClip
= pDoc
&& pDoc
->IsClipboard();
1495 //#i110034# charts need correct sheet names for xml range conversion during load
1496 //so the target sheet name is temporarily renamed (if we have any SdrObjects)
1497 OUString aDestTabName
;
1498 bool bRestoreDestTabName
= false;
1499 if( pOldObject
&& !bSameDoc
&& !bDestClip
)
1501 if( pDoc
&& pClipDoc
)
1503 OUString aSourceTabName
;
1504 if( pClipDoc
->GetName( nSourceTab
, aSourceTabName
)
1505 && pDoc
->GetName( nDestTab
, aDestTabName
) )
1507 if( !aSourceTabName
.equals(aDestTabName
) &&
1508 pDoc
->ValidNewTabName(aSourceTabName
) )
1510 bRestoreDestTabName
= pDoc
->RenameTab( nDestTab
, aSourceTabName
); //sal_Bool bUpdateRef = sal_True, sal_Bool bExternalDocument = sal_False
1516 // first mirror, then move
1517 Size
aMove( rDestRange
.Left() - aMirroredSource
.Left(), rDestRange
.Top() - aMirroredSource
.Top() );
1519 long nDestWidth
= rDestRange
.GetWidth();
1520 long nDestHeight
= rDestRange
.GetHeight();
1521 long nSourceWidth
= rSourceRange
.GetWidth();
1522 long nSourceHeight
= rSourceRange
.GetHeight();
1524 long nWidthDiff
= nDestWidth
- nSourceWidth
;
1525 long nHeightDiff
= nDestHeight
- nSourceHeight
;
1527 Fraction
aHorFract(1,1);
1528 Fraction
aVerFract(1,1);
1529 bool bResize
= false;
1530 // sizes can differ by 1 from twips->1/100mm conversion for equal cell sizes,
1531 // don't resize to empty size when pasting into hidden columns or rows
1532 if ( std::abs(nWidthDiff
) > 1 && nDestWidth
> 1 && nSourceWidth
> 1 )
1534 aHorFract
= Fraction( nDestWidth
, nSourceWidth
);
1537 if ( std::abs(nHeightDiff
) > 1 && nDestHeight
> 1 && nSourceHeight
> 1 )
1539 aVerFract
= Fraction( nDestHeight
, nSourceHeight
);
1542 Point aRefPos
= rDestRange
.TopLeft(); // for resizing (after moving)
1546 Rectangle aObjRect
= pOldObject
->GetCurrentBoundRect();
1547 // do not copy internal objects (detective) and note captions
1548 if ( rSourceRange
.IsInside( aObjRect
) && (pOldObject
->GetLayer() != SC_LAYER_INTERN
) && !IsNoteCaption( pOldObject
) )
1550 SdrObject
* pNewObject
= pOldObject
->Clone();
1551 pNewObject
->SetModel(this);
1552 pNewObject
->SetPage(pDestPage
);
1555 MirrorRTL( pNewObject
); // first mirror, then move
1557 pNewObject
->NbcMove( aMove
);
1559 pNewObject
->NbcResize( aRefPos
, aHorFract
, aVerFract
);
1561 pDestPage
->InsertObject( pNewObject
);
1563 AddCalcUndo( new SdrUndoInsertObj( *pNewObject
) );
1565 //#i110034# handle chart data references (after InsertObject)
1567 if ( pNewObject
->GetObjIdentifier() == OBJ_OLE2
)
1569 uno::Reference
< embed::XEmbeddedObject
> xIPObj
= static_cast<SdrOle2Obj
*>(pNewObject
)->GetObjRef();
1570 uno::Reference
< embed::XClassifiedObject
> xClassified( xIPObj
, uno::UNO_QUERY
);
1571 SvGlobalName aObjectClassName
;
1572 if ( xClassified
.is() )
1575 aObjectClassName
= SvGlobalName( xClassified
->getClassID() );
1576 } catch( uno::Exception
& )
1578 // TODO: handle error?
1582 if ( xIPObj
.is() && SotExchange::IsChart( aObjectClassName
) )
1584 uno::Reference
< chart2::XChartDocument
> xNewChart( ScChartHelper::GetChartFromSdrObject( pNewObject
) );
1585 if( xNewChart
.is() && !xNewChart
->hasInternalDataProvider() )
1587 OUString aChartName
= static_cast<SdrOle2Obj
*>(pNewObject
)->GetPersistName();
1588 ::std::vector
< ScRangeList
> aRangesVector
;
1589 pDoc
->GetChartRanges( aChartName
, aRangesVector
, pDoc
);
1590 if( !aRangesVector
.empty() )
1592 bool bInSourceRange
= false;
1600 pClipDoc
->GetClipStart( nClipStartX
, nClipStartY
);
1601 pClipDoc
->GetClipArea( nClipEndX
, nClipEndY
, true );
1602 nClipEndX
= nClipEndX
+ nClipStartX
;
1603 nClipEndY
+= nClipStartY
; // GetClipArea returns the difference
1605 SCTAB nClipTab
= bRestoreDestTabName
? nDestTab
: nSourceTab
;
1606 aClipRange
= ScRange( nClipStartX
, nClipStartY
, nClipTab
,
1607 nClipEndX
, nClipEndY
, nClipTab
);
1609 bInSourceRange
= lcl_IsAllInRange( aRangesVector
, aClipRange
);
1612 // always lose references when pasting into a clipboard document (transpose)
1613 if ( ( bInSourceRange
|| bSameDoc
) && !bDestClip
)
1615 if ( bInSourceRange
)
1617 if ( rDestPos
!= aClipRange
.aStart
)
1619 // update the data ranges to the new (copied) position
1620 if ( lcl_MoveRanges( aRangesVector
, aClipRange
, rDestPos
) )
1621 pDoc
->SetChartRanges( aChartName
, aRangesVector
);
1626 // leave the ranges unchanged
1631 // pasting into a new document without the complete source data
1632 // -> break connection to source data and switch to own data
1634 uno::Reference
< chart::XChartDocument
> xOldChartDoc( ScChartHelper::GetChartFromSdrObject( pOldObject
), uno::UNO_QUERY
);
1635 uno::Reference
< chart::XChartDocument
> xNewChartDoc( xNewChart
, uno::UNO_QUERY
);
1636 if( xOldChartDoc
.is() && xNewChartDoc
.is() )
1637 xNewChartDoc
->attachData( xOldChartDoc
->getData() );
1639 // (see ScDocument::UpdateChartListenerCollection, PastingDrawFromOtherDoc)
1647 pOldObject
= aIter
.Next();
1650 if( bRestoreDestTabName
)
1651 pDoc
->RenameTab( nDestTab
, aDestTabName
);
1654 void ScDrawLayer::MirrorRTL( SdrObject
* pObj
)
1656 sal_uInt16 nIdent
= pObj
->GetObjIdentifier();
1658 // don't mirror OLE or graphics, otherwise ask the object
1659 // if it can be mirrored
1660 bool bCanMirror
= ( nIdent
!= OBJ_GRAF
&& nIdent
!= OBJ_OLE2
);
1663 SdrObjTransformInfoRec aInfo
;
1664 pObj
->TakeObjInfo( aInfo
);
1665 bCanMirror
= aInfo
.bMirror90Allowed
;
1670 Point
aRef1( 0, 0 );
1671 Point
aRef2( 0, 1 );
1673 AddCalcUndo( new SdrUndoGeoObj( *pObj
) );
1674 pObj
->Mirror( aRef1
, aRef2
);
1678 // Move instead of mirroring:
1679 // New start position is negative of old end position
1680 // -> move by sum of start and end position
1681 Rectangle aObjRect
= pObj
->GetLogicRect();
1682 Size
aMoveSize( -(aObjRect
.Left() + aObjRect
.Right()), 0 );
1684 AddCalcUndo( new SdrUndoMoveObj( *pObj
, aMoveSize
) );
1685 pObj
->Move( aMoveSize
);
1689 void ScDrawLayer::MirrorRectRTL( Rectangle
& rRect
)
1691 // mirror and swap left/right
1692 long nTemp
= rRect
.Left();
1693 rRect
.Left() = -rRect
.Right();
1694 rRect
.Right() = -nTemp
;
1697 Rectangle
ScDrawLayer::GetCellRect( ScDocument
& rDoc
, const ScAddress
& rPos
, bool bMergedCell
)
1699 Rectangle aCellRect
;
1700 OSL_ENSURE( ValidColRowTab( rPos
.Col(), rPos
.Row(), rPos
.Tab() ), "ScDrawLayer::GetCellRect - invalid cell address" );
1701 if( ValidColRowTab( rPos
.Col(), rPos
.Row(), rPos
.Tab() ) )
1703 // find top left position of passed cell address
1705 for( SCCOL nCol
= 0; nCol
< rPos
.Col(); ++nCol
)
1706 aTopLeft
.X() += rDoc
.GetColWidth( nCol
, rPos
.Tab() );
1707 if( rPos
.Row() > 0 )
1708 aTopLeft
.Y() += rDoc
.GetRowHeight( 0, rPos
.Row() - 1, rPos
.Tab() );
1710 // find bottom-right position of passed cell address
1711 ScAddress aEndPos
= rPos
;
1714 const ScMergeAttr
* pMerge
= static_cast< const ScMergeAttr
* >( rDoc
.GetAttr( rPos
.Col(), rPos
.Row(), rPos
.Tab(), ATTR_MERGE
) );
1715 if( pMerge
->GetColMerge() > 1 )
1716 aEndPos
.IncCol( pMerge
->GetColMerge() - 1 );
1717 if( pMerge
->GetRowMerge() > 1 )
1718 aEndPos
.IncRow( pMerge
->GetRowMerge() - 1 );
1720 Point aBotRight
= aTopLeft
;
1721 for( SCCOL nCol
= rPos
.Col(); nCol
<= aEndPos
.Col(); ++nCol
)
1722 aBotRight
.X() += rDoc
.GetColWidth( nCol
, rPos
.Tab() );
1723 aBotRight
.Y() += rDoc
.GetRowHeight( rPos
.Row(), aEndPos
.Row(), rPos
.Tab() );
1725 // twips -> 1/100 mm
1726 aTopLeft
.X() = static_cast< long >( aTopLeft
.X() * HMM_PER_TWIPS
);
1727 aTopLeft
.Y() = static_cast< long >( aTopLeft
.Y() * HMM_PER_TWIPS
);
1728 aBotRight
.X() = static_cast< long >( aBotRight
.X() * HMM_PER_TWIPS
);
1729 aBotRight
.Y() = static_cast< long >( aBotRight
.Y() * HMM_PER_TWIPS
);
1731 aCellRect
= Rectangle( aTopLeft
, aBotRight
);
1732 if( rDoc
.IsNegativePage( rPos
.Tab() ) )
1733 MirrorRectRTL( aCellRect
);
1738 OUString
ScDrawLayer::GetVisibleName( SdrObject
* pObj
)
1740 OUString aName
= pObj
->GetName();
1741 if ( pObj
->GetObjIdentifier() == OBJ_OLE2
)
1743 // For OLE, the user defined name (GetName) is used
1744 // if it's not empty (accepting possibly duplicate names),
1745 // otherwise the persist name is used so every object appears
1746 // in the Navigator at all.
1748 if ( aName
.isEmpty() )
1749 aName
= static_cast<SdrOle2Obj
*>(pObj
)->GetPersistName();
1754 inline bool IsNamedObject( SdrObject
* pObj
, const OUString
& rName
)
1756 // sal_True if rName is the object's Name or PersistName
1757 // (used to find a named object)
1759 return ( pObj
->GetName().equals(rName
) ||
1760 ( pObj
->GetObjIdentifier() == OBJ_OLE2
&&
1761 static_cast<SdrOle2Obj
*>(pObj
)->GetPersistName() == rName
) );
1764 SdrObject
* ScDrawLayer::GetNamedObject( const OUString
& rName
, sal_uInt16 nId
, SCTAB
& rFoundTab
) const
1766 sal_uInt16 nTabCount
= GetPageCount();
1767 for (sal_uInt16 nTab
=0; nTab
<nTabCount
; nTab
++)
1769 const SdrPage
* pPage
= GetPage(nTab
);
1770 OSL_ENSURE(pPage
,"Page ?");
1773 SdrObjListIter
aIter( *pPage
, IM_DEEPWITHGROUPS
);
1774 SdrObject
* pObject
= aIter
.Next();
1777 if ( nId
== 0 || pObject
->GetObjIdentifier() == nId
)
1778 if ( IsNamedObject( pObject
, rName
) )
1780 rFoundTab
= static_cast<SCTAB
>(nTab
);
1784 pObject
= aIter
.Next();
1792 OUString
ScDrawLayer::GetNewGraphicName( long* pnCounter
) const
1794 OUString aBase
= ScGlobal::GetRscString(STR_GRAPHICNAME
);
1798 OUString aGraphicName
;
1800 long nId
= pnCounter
? *pnCounter
: 0;
1804 aGraphicName
= aBase
;
1805 aGraphicName
+= OUString::number( nId
);
1806 bThere
= ( GetNamedObject( aGraphicName
, 0, nDummy
) != NULL
);
1812 return aGraphicName
;
1815 void ScDrawLayer::EnsureGraphicNames()
1817 // make sure all graphic objects have names (after Excel import etc.)
1819 sal_uInt16 nTabCount
= GetPageCount();
1820 for (sal_uInt16 nTab
=0; nTab
<nTabCount
; nTab
++)
1822 SdrPage
* pPage
= GetPage(nTab
);
1823 OSL_ENSURE(pPage
,"Page ?");
1826 SdrObjListIter
aIter( *pPage
, IM_DEEPWITHGROUPS
);
1827 SdrObject
* pObject
= aIter
.Next();
1829 /* The index passed to GetNewGraphicName() will be set to
1830 the used index in each call. This prevents the repeated search
1831 for all names from 1 to current index. */
1836 if ( pObject
->GetObjIdentifier() == OBJ_GRAF
&& pObject
->GetName().isEmpty())
1837 pObject
->SetName( GetNewGraphicName( &nCounter
) );
1839 pObject
= aIter
.Next();
1847 SdrObjUserData
* GetFirstUserDataOfType(const SdrObject
*pObj
, sal_uInt16 nId
)
1849 sal_uInt16 nCount
= pObj
? pObj
->GetUserDataCount() : 0;
1850 for( sal_uInt16 i
= 0; i
< nCount
; i
++ )
1852 SdrObjUserData
* pData
= pObj
->GetUserData( i
);
1853 if( pData
&& pData
->GetInventor() == SC_DRAWLAYER
&& pData
->GetId() == nId
)
1859 void DeleteFirstUserDataOfType(SdrObject
*pObj
, sal_uInt16 nId
)
1861 sal_uInt16 nCount
= pObj
? pObj
->GetUserDataCount() : 0;
1862 for( sal_uInt16 i
= nCount
; i
> 0; i
-- )
1864 SdrObjUserData
* pData
= pObj
->GetUserData( i
-1 );
1865 if( pData
&& pData
->GetInventor() == SC_DRAWLAYER
&& pData
->GetId() == nId
)
1866 pObj
->DeleteUserData(i
-1);
1871 void ScDrawLayer::SetVisualCellAnchored( SdrObject
&rObj
, const ScDrawObjData
&rAnchor
)
1873 ScDrawObjData
* pAnchor
= GetNonRotatedObjData( &rObj
, true );
1874 pAnchor
->maStart
= rAnchor
.maStart
;
1875 pAnchor
->maEnd
= rAnchor
.maEnd
;
1876 pAnchor
->maStartOffset
= rAnchor
.maStartOffset
;
1877 pAnchor
->maEndOffset
= rAnchor
.maEndOffset
;
1880 void ScDrawLayer::SetCellAnchored( SdrObject
&rObj
, const ScDrawObjData
&rAnchor
)
1882 ScDrawObjData
* pAnchor
= GetObjData( &rObj
, true );
1883 pAnchor
->maStart
= rAnchor
.maStart
;
1884 pAnchor
->maEnd
= rAnchor
.maEnd
;
1885 pAnchor
->maStartOffset
= rAnchor
.maStartOffset
;
1886 pAnchor
->maEndOffset
= rAnchor
.maEndOffset
;
1889 void ScDrawLayer::SetCellAnchoredFromPosition( SdrObject
&rObj
, const ScDocument
&rDoc
, SCTAB nTab
)
1891 ScDrawObjData aAnchor
;
1892 // set anchor in terms of the visual ( SnapRect )
1893 // object ( e.g. for when object is rotated )
1894 GetCellAnchorFromPosition( rObj
, aAnchor
, rDoc
, nTab
, false );
1895 SetCellAnchored( rObj
, aAnchor
);
1896 // - keep also an anchor in terms of the Logic ( untransformed ) object
1897 // because thats what we stored ( and still do ) to xml
1898 ScDrawObjData aVisAnchor
;
1899 GetCellAnchorFromPosition( rObj
, aVisAnchor
, rDoc
, nTab
);
1900 SetVisualCellAnchored( rObj
, aVisAnchor
);
1901 // absolutely necessary to set flag that in order to preven ScDrawLayer::RecalcPos
1902 // doing an initialisation hack
1903 if ( ScDrawObjData
* pAnchor
= GetObjData( &rObj
) )
1905 pAnchor
->maLastRect
= rObj
.GetSnapRect();
1909 void ScDrawLayer::GetCellAnchorFromPosition( SdrObject
&rObj
, ScDrawObjData
&rAnchor
, const ScDocument
&rDoc
, SCTAB nTab
, bool bUseLogicRect
, bool bHiddenAsZero
)
1911 Rectangle
aObjRect( bUseLogicRect
? rObj
.GetLogicRect() : rObj
.GetSnapRect() );
1912 ScRange aRange
= rDoc
.GetRange( nTab
, aObjRect
, bHiddenAsZero
);
1914 Rectangle aCellRect
;
1916 rAnchor
.maStart
= aRange
.aStart
;
1917 aCellRect
= rDoc
.GetMMRect( aRange
.aStart
.Col(), aRange
.aStart
.Row(),
1918 aRange
.aStart
.Col(), aRange
.aStart
.Row(), aRange
.aStart
.Tab(), bHiddenAsZero
);
1919 rAnchor
.maStartOffset
.Y() = aObjRect
.Top()-aCellRect
.Top();
1920 if (!rDoc
.IsNegativePage(nTab
))
1921 rAnchor
.maStartOffset
.X() = aObjRect
.Left()-aCellRect
.Left();
1923 rAnchor
.maStartOffset
.X() = aCellRect
.Right()-aObjRect
.Right();
1925 rAnchor
.maEnd
= aRange
.aEnd
;
1926 aCellRect
= rDoc
.GetMMRect( aRange
.aEnd
.Col(), aRange
.aEnd
.Row(),
1927 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), aRange
.aEnd
.Tab(), bHiddenAsZero
);
1928 rAnchor
.maEndOffset
.Y() = aObjRect
.Bottom()-aCellRect
.Top();
1929 if (!rDoc
.IsNegativePage(nTab
))
1930 rAnchor
.maEndOffset
.X() = aObjRect
.Right()-aCellRect
.Left();
1932 rAnchor
.maEndOffset
.X() = aCellRect
.Right()-aObjRect
.Left();
1936 void ScDrawLayer::UpdateCellAnchorFromPositionEnd( SdrObject
&rObj
, ScDrawObjData
&rAnchor
, const ScDocument
&rDoc
, SCTAB nTab
, bool bUseLogicRect
)
1938 Rectangle
aObjRect(bUseLogicRect
? rObj
.GetLogicRect() : rObj
.GetSnapRect());
1939 ScRange aRange
= rDoc
.GetRange( nTab
, aObjRect
);
1941 ScDrawObjData
* pAnchor
= &rAnchor
;
1942 pAnchor
->maEnd
= aRange
.aEnd
;
1944 Rectangle aCellRect
;
1945 aCellRect
= rDoc
.GetMMRect( aRange
.aEnd
.Col(), aRange
.aEnd
.Row(),
1946 aRange
.aEnd
.Col(), aRange
.aEnd
.Row(), aRange
.aEnd
.Tab() );
1947 pAnchor
->maEndOffset
.Y() = aObjRect
.Bottom()-aCellRect
.Top();
1948 if (!rDoc
.IsNegativePage(nTab
))
1949 pAnchor
->maEndOffset
.X() = aObjRect
.Right()-aCellRect
.Left();
1951 pAnchor
->maEndOffset
.X() = aCellRect
.Right()-aObjRect
.Left();
1954 bool ScDrawLayer::IsCellAnchored( const SdrObject
& rObj
)
1956 // Cell anchored object always has a user data, to store the anchor cell
1957 // info. If it doesn't then it's page-anchored.
1958 return GetFirstUserDataOfType(&rObj
, SC_UD_OBJDATA
) != NULL
;
1961 void ScDrawLayer::SetPageAnchored( SdrObject
&rObj
)
1963 DeleteFirstUserDataOfType(&rObj
, SC_UD_OBJDATA
);
1964 DeleteFirstUserDataOfType(&rObj
, SC_UD_OBJDATA
);
1967 ScAnchorType
ScDrawLayer::GetAnchorType( const SdrObject
&rObj
)
1969 //If this object has a cell anchor associated with it
1970 //then its cell-anchored, otherwise its page-anchored
1971 return ScDrawLayer::GetObjData(const_cast<SdrObject
*>(&rObj
)) ? SCA_CELL
: SCA_PAGE
;
1974 ScDrawObjData
* ScDrawLayer::GetNonRotatedObjData( SdrObject
* pObj
, bool bCreate
)
1976 sal_uInt16 nCount
= pObj
? pObj
->GetUserDataCount() : 0;
1977 sal_uInt16 nFound
= 0;
1978 for( sal_uInt16 i
= 0; i
< nCount
; i
++ )
1980 SdrObjUserData
* pData
= pObj
->GetUserData( i
);
1981 if( pData
&& pData
->GetInventor() == SC_DRAWLAYER
&& pData
->GetId() == SC_UD_OBJDATA
&& ++nFound
== 2 )
1982 return static_cast<ScDrawObjData
*>(pData
);
1984 if( pObj
&& bCreate
)
1986 ScDrawObjData
* pData
= new ScDrawObjData
;
1987 pObj
->AppendUserData(pData
);
1993 ScDrawObjData
* ScDrawLayer::GetObjData( SdrObject
* pObj
, bool bCreate
)
1995 if (SdrObjUserData
*pData
= GetFirstUserDataOfType(pObj
, SC_UD_OBJDATA
))
1996 return static_cast<ScDrawObjData
*>(pData
);
1998 if( pObj
&& bCreate
)
2000 ScDrawObjData
* pData
= new ScDrawObjData
;
2001 pObj
->AppendUserData(pData
);
2007 ScDrawObjData
* ScDrawLayer::GetObjDataTab( SdrObject
* pObj
, SCTAB nTab
)
2009 ScDrawObjData
* pData
= GetObjData( pObj
);
2012 if ( pData
->maStart
.IsValid() )
2013 pData
->maStart
.SetTab( nTab
);
2014 if ( pData
->maEnd
.IsValid() )
2015 pData
->maEnd
.SetTab( nTab
);
2020 bool ScDrawLayer::IsNoteCaption( SdrObject
* pObj
)
2022 ScDrawObjData
* pData
= pObj
? GetObjData( pObj
) : 0;
2023 return pData
&& pData
->meType
== ScDrawObjData::CellNote
;
2026 ScDrawObjData
* ScDrawLayer::GetNoteCaptionData( SdrObject
* pObj
, SCTAB nTab
)
2028 ScDrawObjData
* pData
= pObj
? GetObjDataTab( pObj
, nTab
) : 0;
2029 return (pData
&& pData
->meType
== ScDrawObjData::CellNote
) ? pData
: 0;
2032 ScIMapInfo
* ScDrawLayer::GetIMapInfo( SdrObject
* pObj
)
2034 return static_cast<ScIMapInfo
*>(GetFirstUserDataOfType(pObj
, SC_UD_IMAPDATA
));
2037 IMapObject
* ScDrawLayer::GetHitIMapObject( SdrObject
* pObj
,
2038 const Point
& rWinPoint
, const vcl::Window
& rCmpWnd
)
2040 const MapMode
aMap100( MAP_100TH_MM
);
2041 MapMode aWndMode
= rCmpWnd
.GetMapMode();
2042 Point
aRelPoint( rCmpWnd
.LogicToLogic( rWinPoint
, &aWndMode
, &aMap100
) );
2043 Rectangle aLogRect
= rCmpWnd
.LogicToLogic( pObj
->GetLogicRect(), &aWndMode
, &aMap100
);
2044 ScIMapInfo
* pIMapInfo
= GetIMapInfo( pObj
);
2045 IMapObject
* pIMapObj
= NULL
;
2050 ImageMap
& rImageMap
= (ImageMap
&) pIMapInfo
->GetImageMap();
2052 bool bObjSupported
= false;
2054 if ( pObj
->ISA( SdrGrafObj
) ) // Simple Graphics object
2056 const SdrGrafObj
* pGrafObj
= static_cast<const SdrGrafObj
*>( pObj
);
2057 const GeoStat
& rGeo
= pGrafObj
->GetGeoStat();
2058 const Graphic
& rGraphic
= pGrafObj
->GetGraphic();
2061 if ( rGeo
.nRotationAngle
)
2062 RotatePoint( aRelPoint
, aLogRect
.TopLeft(), -rGeo
.nSin
, rGeo
.nCos
);
2064 // Reverse mirroring
2065 if ( static_cast<const SdrGrafObjGeoData
*>( pGrafObj
->GetGeoData() )->bMirrored
)
2066 aRelPoint
.X() = aLogRect
.Right() + aLogRect
.Left() - aRelPoint
.X();
2068 // Possible Unshear:
2069 if ( rGeo
.nShearAngle
)
2070 ShearPoint( aRelPoint
, aLogRect
.TopLeft(), -rGeo
.nTan
);
2072 if ( rGraphic
.GetPrefMapMode().GetMapUnit() == MAP_PIXEL
)
2073 aGraphSize
= rCmpWnd
.PixelToLogic( rGraphic
.GetPrefSize(),
2076 aGraphSize
= OutputDevice::LogicToLogic( rGraphic
.GetPrefSize(),
2077 rGraphic
.GetPrefMapMode(),
2080 bObjSupported
= true;
2082 else if ( pObj
->ISA( SdrOle2Obj
) ) // OLE object
2084 // TODO/LEAN: working with visual area needs running state
2085 aGraphSize
= static_cast<const SdrOle2Obj
*>(pObj
)->GetOrigObjSize();
2086 bObjSupported
= true;
2089 // If everything has worked out, then perform HitTest
2090 if ( bObjSupported
)
2092 // Calculate relative mouse point
2093 aRelPoint
-= aLogRect
.TopLeft();
2094 pIMapObj
= rImageMap
.GetHitIMapObject( aGraphSize
, aLogRect
.GetSize(), aRelPoint
);
2101 ScMacroInfo
* ScDrawLayer::GetMacroInfo( SdrObject
* pObj
, bool bCreate
)
2103 if (SdrObjUserData
*pData
= GetFirstUserDataOfType(pObj
, SC_UD_MACRODATA
))
2104 return static_cast<ScMacroInfo
*>(pData
);
2108 ScMacroInfo
* pData
= new ScMacroInfo
;
2109 pObj
->AppendUserData(pData
);
2115 ImageMap
* ScDrawLayer::GetImageMapForObject(SdrObject
* pObj
)
2117 ScIMapInfo
* pIMapInfo
= const_cast<ScIMapInfo
*>( GetIMapInfo( pObj
) );
2120 return const_cast<ImageMap
*>( &(pIMapInfo
->GetImageMap()) );
2125 sal_Int32
ScDrawLayer::GetHyperlinkCount(SdrObject
* pObj
)
2127 sal_Int32 nHLCount
= 0;
2128 ScMacroInfo
* pMacroInfo
= GetMacroInfo(pObj
, false);
2130 // MT IA2: GetHlink*( doesn't exist in DEV300 anymore...
2131 nHLCount
= 0; // pMacroInfo->GetHlink().getLength() > 0 ? 1 : 0;
2135 void ScDrawLayer::SetGlobalDrawPersist(SfxObjectShell
* pPersist
)
2137 OSL_ENSURE(!pGlobalDrawPersist
,"Multiple SetGlobalDrawPersist");
2138 pGlobalDrawPersist
= pPersist
;
2141 void ScDrawLayer::SetChanged( bool bFlg
/* = true */ )
2144 pDoc
->SetChartListenerCollectionNeedsUpdate( true );
2145 FmFormModel::SetChanged( bFlg
);
2148 SdrLayerID
ScDrawLayer::GetControlExportLayerId( const SdrObject
& ) const
2150 // Layer for export of Form-Controls in Versions before 5.0 - always SC_LAYER_FRONT
2151 return SC_LAYER_FRONT
;
2154 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> ScDrawLayer::createUnoModel()
2156 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> xRet
;
2157 if( pDoc
&& pDoc
->GetDocumentShell() )
2158 xRet
= pDoc
->GetDocumentShell()->GetModel();
2163 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */