Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
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>
31 :
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>
61 :
62 : #include <basegfx/polygon/b2dpolygon.hxx>
63 : #include <basegfx/polygon/b2dpolygontools.hxx>
64 :
65 : #include "drwlayer.hxx"
66 : #include "drawpage.hxx"
67 : #include "global.hxx"
68 : #include "document.hxx"
69 : #include "rechead.hxx"
70 : #include "userdat.hxx"
71 : #include "markdata.hxx"
72 : #include "globstr.hrc"
73 : #include "scmod.hxx"
74 : #include "chartarr.hxx"
75 : #include "postit.hxx"
76 : #include "attrib.hxx"
77 : #include "charthelper.hxx"
78 : #include <basegfx/matrix/b2dhommatrix.hxx>
79 :
80 : #include <vcl/field.hxx>
81 : #include <boost/scoped_array.hpp>
82 :
83 : #define DET_ARROW_OFFSET 1000
84 :
85 : using namespace ::com::sun::star;
86 :
87 : // STATIC DATA -----------------------------------------------------------
88 :
89 : static ScDrawObjFactory* pFac = NULL;
90 : static E3dObjFactory* pF3d = NULL;
91 : static sal_uInt16 nInst = 0;
92 :
93 : SfxObjectShell* ScDrawLayer::pGlobalDrawPersist = NULL;
94 :
95 : bool bDrawIsInUndo = false; //TODO: Member
96 :
97 14 : ScUndoObjData::ScUndoObjData( SdrObject* pObjP, const ScAddress& rOS, const ScAddress& rOE,
98 : const ScAddress& rNS, const ScAddress& rNE ) :
99 : SdrUndoObj( *pObjP ),
100 : aOldStt( rOS ),
101 : aOldEnd( rOE ),
102 : aNewStt( rNS ),
103 14 : aNewEnd( rNE )
104 : {
105 14 : }
106 :
107 28 : ScUndoObjData::~ScUndoObjData()
108 : {
109 28 : }
110 :
111 1 : void ScUndoObjData::Undo()
112 : {
113 1 : ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj );
114 : OSL_ENSURE(pData,"ScUndoObjData: Data missing");
115 1 : if (pData)
116 : {
117 1 : pData->maStart = aOldStt;
118 1 : pData->maEnd = aOldEnd;
119 : }
120 :
121 : // Undo also an untransformed anchor
122 1 : pData = ScDrawLayer::GetNonRotatedObjData( pObj );
123 1 : if (pData)
124 : {
125 1 : pData->maStart = aOldStt;
126 1 : pData->maEnd = aOldEnd;
127 : }
128 1 : }
129 :
130 0 : void ScUndoObjData::Redo()
131 : {
132 0 : ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj );
133 : OSL_ENSURE(pData,"ScUndoObjData: Data missing");
134 0 : if (pData)
135 : {
136 0 : pData->maStart = aNewStt;
137 0 : pData->maEnd = aNewEnd;
138 : }
139 :
140 : // Redo also an untransformed anchor
141 0 : pData = ScDrawLayer::GetNonRotatedObjData( pObj );
142 0 : if (pData)
143 : {
144 0 : pData->maStart = aNewStt;
145 0 : pData->maEnd = aNewEnd;
146 : }
147 0 : }
148 :
149 2 : ScUndoAnchorData::ScUndoAnchorData( SdrObject* pObjP, ScDocument* pDoc, SCTAB nTab ) :
150 : SdrUndoObj( *pObjP ),
151 : mpDoc( pDoc ),
152 2 : mnTab( nTab )
153 : {
154 2 : mbWasCellAnchored = ScDrawLayer::IsCellAnchored( *pObjP );
155 2 : }
156 :
157 0 : ScUndoAnchorData::~ScUndoAnchorData()
158 : {
159 0 : }
160 :
161 2 : void ScUndoAnchorData::Undo()
162 : {
163 : // Trigger Object Change
164 2 : if (pObj->IsInserted() && pObj->GetPage() && pObj->GetModel())
165 : {
166 2 : SdrHint aHint(*pObj);
167 2 : pObj->GetModel()->Broadcast(aHint);
168 : }
169 :
170 2 : if (mbWasCellAnchored)
171 1 : ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *mpDoc, mnTab);
172 : else
173 1 : ScDrawLayer::SetPageAnchored( *pObj );
174 2 : }
175 :
176 2 : void ScUndoAnchorData::Redo()
177 : {
178 2 : if (mbWasCellAnchored)
179 1 : ScDrawLayer::SetPageAnchored( *pObj );
180 : else
181 1 : ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *mpDoc, mnTab);
182 :
183 : // Trigger Object Change
184 2 : if (pObj->IsInserted() && pObj->GetPage() && pObj->GetModel())
185 : {
186 2 : SdrHint aHint(*pObj);
187 2 : pObj->GetModel()->Broadcast(aHint);
188 : }
189 2 : }
190 :
191 21 : ScTabDeletedHint::ScTabDeletedHint( SCTAB nTabNo ) :
192 21 : nTab( nTabNo )
193 : {
194 21 : }
195 :
196 21 : ScTabDeletedHint::~ScTabDeletedHint()
197 : {
198 21 : }
199 :
200 1980 : ScTabSizeChangedHint::ScTabSizeChangedHint( SCTAB nTabNo ) :
201 1980 : nTab( nTabNo )
202 : {
203 1980 : }
204 :
205 1980 : ScTabSizeChangedHint::~ScTabSizeChangedHint()
206 : {
207 1980 : }
208 :
209 : #define MAXMM 10000000
210 :
211 1742 : inline long TwipsToHmm (long nVal)
212 : {
213 : return static_cast< long >( MetricField::ConvertDoubleValue (static_cast<sal_Int64>(nVal), 0, 0,
214 1742 : FUNIT_TWIP, FUNIT_100TH_MM) );
215 : }
216 :
217 7220 : inline long HmmToTwips (long nVal)
218 : {
219 : return static_cast< long > ( MetricField::ConvertDoubleValue (static_cast<sal_Int64>(nVal), 0, 0,
220 7220 : FUNIT_100TH_MM, FUNIT_TWIP) );
221 : }
222 :
223 1674 : inline void TwipsToMM( long& nVal )
224 : {
225 1674 : nVal = TwipsToHmm (nVal);
226 1674 : }
227 :
228 108 : inline void ReverseTwipsToMM( long& nVal )
229 : {
230 108 : nVal = HmmToTwips (nVal);
231 108 : }
232 :
233 27 : static void lcl_ReverseTwipsToMM( Rectangle& rRect )
234 : {
235 27 : ReverseTwipsToMM( rRect.Left() );
236 27 : ReverseTwipsToMM( rRect.Right() );
237 27 : ReverseTwipsToMM( rRect.Top() );
238 27 : ReverseTwipsToMM( rRect.Bottom() );
239 27 : }
240 :
241 549 : ScDrawLayer::ScDrawLayer( ScDocument* pDocument, const OUString& rName ) :
242 1098 : FmFormModel( SvtPathOptions().GetPalettePath(),
243 : NULL, // SfxItemPool* Pool
244 : pGlobalDrawPersist ?
245 : pGlobalDrawPersist :
246 : ( pDocument ? pDocument->GetDocumentShell() : NULL ),
247 : true ), // bUseExtColorTable (is set below)
248 : aName( rName ),
249 : pDoc( pDocument ),
250 : pUndoGroup( NULL ),
251 : bRecording( false ),
252 : bAdjustEnabled( true ),
253 1647 : bHyphenatorSet( false )
254 : {
255 549 : pGlobalDrawPersist = NULL; // Only use once
256 :
257 549 : SfxObjectShell* pObjSh = pDocument ? pDocument->GetDocumentShell() : NULL;
258 549 : XColorListRef pXCol = XColorList::GetStdColorList();
259 549 : if ( pObjSh )
260 : {
261 548 : SetObjectShell( pObjSh );
262 :
263 : // set color table
264 548 : const SvxColorListItem* pColItem = static_cast<const SvxColorListItem*>( pObjSh->GetItem( SID_COLOR_TABLE ) );
265 548 : if ( pColItem )
266 457 : pXCol = pColItem->GetColorList();
267 : }
268 549 : SetPropertyList( static_cast<XPropertyList *> (pXCol.get()) );
269 :
270 549 : SetSwapGraphics(true);
271 :
272 549 : SetScaleUnit(MAP_100TH_MM);
273 549 : SfxItemPool& rPool = GetItemPool();
274 549 : rPool.SetDefaultMetric(SFX_MAPUNIT_100TH_MM);
275 1098 : SvxFrameDirectionItem aModeItem( FRMDIR_ENVIRONMENT, EE_PARA_WRITINGDIR );
276 549 : rPool.SetPoolDefaultItem( aModeItem );
277 :
278 : // #i33700#
279 : // Set shadow distance defaults as PoolDefaultItems. Details see bug.
280 549 : rPool.SetPoolDefaultItem(makeSdrShadowXDistItem(300));
281 549 : rPool.SetPoolDefaultItem(makeSdrShadowYDistItem(300));
282 :
283 : // default for script spacing depends on locale, see SdDrawDocument ctor in sd
284 549 : LanguageType eOfficeLanguage = Application::GetSettings().GetLanguageTag().getLanguageType();
285 549 : if (MsLangId::isKorean(eOfficeLanguage) || eOfficeLanguage == LANGUAGE_JAPANESE)
286 : {
287 : // secondary is edit engine pool
288 0 : rPool.GetSecondaryPool()->SetPoolDefaultItem( SvxScriptSpaceItem( false, EE_PARA_ASIANCJKSPACING ) );
289 : }
290 :
291 549 : rPool.FreezeIdRanges(); // the pool is also used directly
292 :
293 549 : SdrLayerAdmin& rAdmin = GetLayerAdmin();
294 549 : rAdmin.NewLayer(OUString("vorne"), SC_LAYER_FRONT);
295 549 : rAdmin.NewLayer(OUString("hinten"), SC_LAYER_BACK);
296 549 : rAdmin.NewLayer(OUString("intern"), SC_LAYER_INTERN);
297 549 : rAdmin.NewLayer(OUString("Controls"), SC_LAYER_CONTROLS);
298 549 : rAdmin.NewLayer(OUString("hidden"), SC_LAYER_HIDDEN);
299 : // "Controls" is new - must also be created when loading
300 :
301 : // Set link for URL-Fields
302 549 : ScModule* pScMod = SC_MOD();
303 549 : Outliner& rOutliner = GetDrawOutliner();
304 549 : rOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) );
305 :
306 549 : Outliner& rHitOutliner = GetHitTestOutliner();
307 549 : rHitOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) );
308 :
309 : // set FontHeight pool defaults without changing static SdrEngineDefaults
310 549 : SfxItemPool* pOutlinerPool = rOutliner.GetEditTextObjectPool();
311 549 : if ( pOutlinerPool )
312 : {
313 549 : pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt
314 549 : pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CJK )); // 12Pt
315 549 : pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CTL )); // 12Pt
316 : }
317 549 : SfxItemPool* pHitOutlinerPool = rHitOutliner.GetEditTextObjectPool();
318 549 : if ( pHitOutlinerPool )
319 : {
320 549 : pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT )); // 12Pt
321 549 : pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CJK )); // 12Pt
322 549 : pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CTL )); // 12Pt
323 : }
324 :
325 : // initial undo mode as in Calc document
326 549 : if( pDoc )
327 549 : EnableUndo( pDoc->IsUndoEnabled() );
328 :
329 : // URL-Buttons have no handler anymore, all is done by themselves
330 :
331 549 : if( !nInst++ )
332 : {
333 437 : pFac = new ScDrawObjFactory;
334 437 : pF3d = new E3dObjFactory;
335 549 : }
336 549 : }
337 :
338 1620 : ScDrawLayer::~ScDrawLayer()
339 : {
340 540 : Broadcast(SdrHint(HINT_MODELCLEARED));
341 :
342 540 : ClearModel(true);
343 :
344 540 : delete pUndoGroup;
345 540 : if( !--nInst )
346 : {
347 432 : delete pFac, pFac = NULL;
348 432 : delete pF3d, pF3d = NULL;
349 : }
350 1080 : }
351 :
352 6009 : void ScDrawLayer::UseHyphenator()
353 : {
354 6009 : if (!bHyphenatorSet)
355 : {
356 : com::sun::star::uno::Reference< com::sun::star::linguistic2::XHyphenator >
357 184 : xHyphenator = LinguMgr::GetHyphenator();
358 :
359 184 : GetDrawOutliner().SetHyphenator( xHyphenator );
360 184 : GetHitTestOutliner().SetHyphenator( xHyphenator );
361 :
362 184 : bHyphenatorSet = true;
363 : }
364 6009 : }
365 :
366 964 : SdrPage* ScDrawLayer::AllocPage(bool bMasterPage)
367 : {
368 964 : return new ScDrawPage(*this, bMasterPage);
369 : }
370 :
371 28 : bool ScDrawLayer::HasObjects() const
372 : {
373 28 : bool bFound = false;
374 :
375 28 : sal_uInt16 nCount = GetPageCount();
376 56 : for (sal_uInt16 i=0; i<nCount && !bFound; i++)
377 28 : if (GetPage(i)->GetObjCount())
378 0 : bFound = true;
379 :
380 28 : return bFound;
381 : }
382 :
383 0 : SdrModel* ScDrawLayer::AllocModel() const
384 : {
385 : // Allocated model (for clipboard etc) must not have a pointer
386 : // to the original model's document, pass NULL as document:
387 :
388 0 : return new ScDrawLayer( NULL, aName );
389 : }
390 :
391 964 : bool ScDrawLayer::ScAddPage( SCTAB nTab )
392 : {
393 964 : if (bDrawIsInUndo)
394 0 : return false; // not inserted
395 :
396 964 : ScDrawPage* pPage = static_cast<ScDrawPage*>(AllocPage( false ));
397 964 : InsertPage(pPage, static_cast<sal_uInt16>(nTab));
398 964 : if (bRecording)
399 37 : AddCalcUndo(new SdrUndoNewPage(*pPage));
400 :
401 964 : ResetTab(nTab, pDoc->GetTableCount()-1);
402 964 : return true; // inserted
403 : }
404 :
405 21 : void ScDrawLayer::ScRemovePage( SCTAB nTab )
406 : {
407 21 : if (bDrawIsInUndo)
408 21 : return;
409 :
410 21 : Broadcast( ScTabDeletedHint( nTab ) );
411 21 : if (bRecording)
412 : {
413 18 : SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
414 18 : AddCalcUndo(new SdrUndoDelPage(*pPage)); // Undo-Action becomes the page owner
415 18 : RemovePage( static_cast<sal_uInt16>(nTab) ); // just deliver, not deleting
416 : }
417 : else
418 3 : DeletePage( static_cast<sal_uInt16>(nTab) ); // just get rid of it
419 :
420 21 : ResetTab(nTab, pDoc->GetTableCount()-1);
421 : }
422 :
423 964 : void ScDrawLayer::ScRenamePage( SCTAB nTab, const OUString& rNewName )
424 : {
425 964 : ScDrawPage* pPage = static_cast<ScDrawPage*>( GetPage(static_cast<sal_uInt16>(nTab)) );
426 964 : if (pPage)
427 964 : pPage->SetName(rNewName);
428 964 : }
429 :
430 1 : void ScDrawLayer::ScMovePage( sal_uInt16 nOldPos, sal_uInt16 nNewPos )
431 : {
432 1 : MovePage( nOldPos, nNewPos );
433 1 : sal_uInt16 nMinPos = std::min(nOldPos, nNewPos);
434 1 : ResetTab(nMinPos, pDoc->GetTableCount()-1);
435 1 : }
436 :
437 2 : void ScDrawLayer::ScCopyPage( sal_uInt16 nOldPos, sal_uInt16 nNewPos)
438 : {
439 2 : if (bDrawIsInUndo)
440 2 : return;
441 :
442 2 : SdrPage* pOldPage = GetPage(nOldPos);
443 2 : SdrPage* pNewPage = GetPage(nNewPos);
444 :
445 : // Copying
446 :
447 2 : if (pOldPage && pNewPage)
448 : {
449 2 : SCTAB nOldTab = static_cast<SCTAB>(nOldPos);
450 2 : SCTAB nNewTab = static_cast<SCTAB>(nNewPos);
451 :
452 2 : SdrObjListIter aIter( *pOldPage, IM_FLAT );
453 2 : SdrObject* pOldObject = aIter.Next();
454 5 : while (pOldObject)
455 : {
456 1 : ScDrawObjData* pOldData = GetObjData(pOldObject);
457 1 : if (pOldData)
458 : {
459 1 : pOldData->maStart.SetTab(nOldTab);
460 1 : pOldData->maEnd.SetTab(nOldTab);
461 : }
462 1 : SdrObject* pNewObject = pOldObject->Clone();
463 1 : pNewObject->SetModel(this);
464 1 : pNewObject->SetPage(pNewPage);
465 :
466 1 : pNewObject->NbcMove(Size(0,0));
467 1 : pNewPage->InsertObject( pNewObject );
468 1 : ScDrawObjData* pNewData = GetObjData(pNewObject);
469 1 : if (pNewData)
470 : {
471 1 : pNewData->maStart.SetTab(nNewTab);
472 1 : pNewData->maEnd.SetTab(nNewTab);
473 : }
474 :
475 1 : if (bRecording)
476 0 : AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) );
477 :
478 1 : pOldObject = aIter.Next();
479 2 : }
480 : }
481 :
482 2 : ResetTab(static_cast<SCTAB>(nNewPos), pDoc->GetTableCount()-1);
483 : }
484 :
485 988 : void ScDrawLayer::ResetTab( SCTAB nStart, SCTAB nEnd )
486 : {
487 988 : SCTAB nPageSize = static_cast<SCTAB>(GetPageCount());
488 988 : if (nPageSize < 0)
489 : // No drawing pages exist.
490 988 : return;
491 :
492 988 : if (nEnd >= nPageSize)
493 : // Avoid iterating beyond the last existing page.
494 184 : nEnd = nPageSize - 1;
495 :
496 1862 : for (SCTAB i = nStart; i <= nEnd; ++i)
497 : {
498 874 : SdrPage* pPage = GetPage(static_cast<sal_uInt16>(i));
499 874 : if (!pPage)
500 0 : continue;
501 :
502 874 : SdrObjListIter aIter(*pPage, IM_FLAT);
503 878 : for (SdrObject* pObj = aIter.Next(); pObj; pObj = aIter.Next())
504 : {
505 4 : ScDrawObjData* pData = GetObjData(pObj);
506 4 : if (!pData)
507 0 : continue;
508 :
509 4 : pData->maStart.SetTab(i);
510 4 : pData->maEnd.SetTab(i);
511 : }
512 874 : }
513 : }
514 :
515 39 : inline bool IsInBlock( const ScAddress& rPos, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2 )
516 : {
517 101 : return rPos.Col() >= nCol1 && rPos.Col() <= nCol2 &&
518 98 : rPos.Row() >= nRow1 && rPos.Row() <= nRow2;
519 : }
520 :
521 27 : void ScDrawLayer::MoveCells( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2,
522 : SCsCOL nDx,SCsROW nDy, bool bUpdateNoteCaptionPos )
523 : {
524 27 : SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
525 : OSL_ENSURE(pPage,"Page not found");
526 27 : if (!pPage)
527 27 : return;
528 :
529 27 : bool bNegativePage = pDoc && pDoc->IsNegativePage( nTab );
530 :
531 27 : const size_t nCount = pPage->GetObjCount();
532 48 : for ( size_t i = 0; i < nCount; ++i )
533 : {
534 21 : SdrObject* pObj = pPage->GetObj( i );
535 21 : ScDrawObjData* pData = GetObjDataTab( pObj, nTab );
536 21 : if( pData )
537 : {
538 21 : const ScAddress aOldStt = pData->maStart;
539 21 : const ScAddress aOldEnd = pData->maEnd;
540 21 : bool bChange = false;
541 21 : if ( aOldStt.IsValid() && IsInBlock( aOldStt, nCol1,nRow1, nCol2,nRow2 ) )
542 : {
543 14 : pData->maStart.IncCol( nDx );
544 14 : pData->maStart.IncRow( nDy );
545 14 : bChange = true;
546 : }
547 21 : if ( aOldEnd.IsValid() && IsInBlock( aOldEnd, nCol1,nRow1, nCol2,nRow2 ) )
548 : {
549 14 : pData->maEnd.IncCol( nDx );
550 14 : pData->maEnd.IncRow( nDy );
551 14 : bChange = true;
552 : }
553 21 : if (bChange)
554 : {
555 14 : if ( pObj->ISA( SdrRectObj ) && pData->maStart.IsValid() && pData->maEnd.IsValid() )
556 12 : pData->maStart.PutInOrder( pData->maEnd );
557 :
558 : // Update also an untransformed anchor thats what we stored ( and still do ) to xml
559 14 : ScDrawObjData* pNoRotatedAnchor = GetNonRotatedObjData( pObj, false );
560 14 : if ( pNoRotatedAnchor )
561 : {
562 14 : pNoRotatedAnchor->maStart = pData->maStart;
563 14 : pNoRotatedAnchor->maEnd = pData->maEnd;
564 : }
565 :
566 14 : AddCalcUndo( new ScUndoObjData( pObj, aOldStt, aOldEnd, pData->maStart, pData->maEnd ) );
567 14 : RecalcPos( pObj, *pData, bNegativePage, bUpdateNoteCaptionPos );
568 : }
569 : }
570 : }
571 : }
572 :
573 3255 : void ScDrawLayer::SetPageSize( sal_uInt16 nPageNo, const Size& rSize, bool bUpdateNoteCaptionPos )
574 : {
575 3255 : SdrPage* pPage = GetPage(nPageNo);
576 3255 : if (pPage)
577 : {
578 3255 : if ( rSize != pPage->GetSize() )
579 : {
580 1980 : pPage->SetSize( rSize );
581 1980 : Broadcast( ScTabSizeChangedHint( static_cast<SCTAB>(nPageNo) ) ); // SetWorkArea() an den Views
582 : }
583 :
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))
587 :
588 3255 : bool bNegativePage = pDoc && pDoc->IsNegativePage( static_cast<SCTAB>(nPageNo) );
589 :
590 3255 : const size_t nCount = pPage->GetObjCount();
591 3604 : for ( size_t i = 0; i < nCount; ++i )
592 : {
593 349 : SdrObject* pObj = pPage->GetObj( i );
594 349 : ScDrawObjData* pData = GetObjDataTab( pObj, static_cast<SCTAB>(nPageNo) );
595 349 : if( pData )
596 138 : RecalcPos( pObj, *pData, bNegativePage, bUpdateNoteCaptionPos );
597 : }
598 : }
599 3255 : }
600 :
601 : namespace
602 : {
603 : //Can't have a zero width dimension
604 433 : Rectangle lcl_makeSafeRectangle(const Rectangle &rNew)
605 : {
606 433 : Rectangle aRect = rNew;
607 433 : if (aRect.Bottom() == aRect.Top())
608 3 : aRect.Bottom() = aRect.Top()+1;
609 433 : if (aRect.Right() == aRect.Left())
610 1 : aRect.Right() = aRect.Left()+1;
611 433 : return aRect;
612 : }
613 :
614 686 : Point lcl_calcAvailableDiff(ScDocument &rDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, const Point &aWantedDiff)
615 : {
616 686 : Point aAvailableDiff(aWantedDiff);
617 686 : long nHeight = static_cast<long>(rDoc.GetRowHeight( nRow, nTab ) * HMM_PER_TWIPS);
618 686 : long nWidth = static_cast<long>(rDoc.GetColWidth( nCol, nTab ) * HMM_PER_TWIPS);
619 686 : if (aAvailableDiff.Y() > nHeight)
620 33 : aAvailableDiff.Y() = nHeight;
621 686 : if (aAvailableDiff.X() > nWidth)
622 1 : aAvailableDiff.X() = nWidth;
623 686 : return aAvailableDiff;
624 : }
625 :
626 0 : Rectangle lcl_UpdateCalcPoly(basegfx::B2DPolygon &rCalcPoly, int nWhichPoint, const Point &rPos)
627 : {
628 0 : rCalcPoly.setB2DPoint(nWhichPoint, basegfx::B2DPoint(rPos.X(), rPos.Y()));
629 0 : basegfx::B2DRange aRange(basegfx::tools::getRange(rCalcPoly));
630 0 : return Rectangle(static_cast<long>(aRange.getMinX()), static_cast<long>(aRange.getMinY()),
631 0 : static_cast<long>(aRange.getMaxX()), static_cast<long>(aRange.getMaxY()));
632 : }
633 : }
634 343 : void ScDrawLayer::ResizeLastRectFromAnchor( SdrObject* pObj, ScDrawObjData& rData, bool bUseLogicRect, bool bNegativePage, bool bCanResize, bool bHiddenAsZero )
635 : {
636 343 : rData.maLastRect = ( bUseLogicRect ? pObj->GetLogicRect() : pObj->GetSnapRect() );
637 343 : SCCOL nCol1 = rData.maStart.Col();
638 343 : SCROW nRow1 = rData.maStart.Row();
639 343 : SCTAB nTab1 = rData.maStart.Tab();
640 343 : SCCOL nCol2 = rData.maEnd.Col();
641 343 : SCROW nRow2 = rData.maEnd.Row();
642 343 : SCTAB nTab2 = rData.maEnd.Tab();
643 343 : Point aPos( pDoc->GetColOffset( nCol1, nTab1, bHiddenAsZero ), pDoc->GetRowOffset( nRow1, nTab1, bHiddenAsZero ) );
644 343 : TwipsToMM( aPos.X() );
645 343 : TwipsToMM( aPos.Y() );
646 343 : aPos += lcl_calcAvailableDiff(*pDoc, nCol1, nRow1, nTab1, rData.maStartOffset);
647 :
648 343 : if( bCanResize )
649 : {
650 343 : Point aEnd( pDoc->GetColOffset( nCol2, nTab2, bHiddenAsZero ), pDoc->GetRowOffset( nRow2, nTab2, bHiddenAsZero ) );
651 343 : TwipsToMM( aEnd.X() );
652 343 : TwipsToMM( aEnd.Y() );
653 343 : aEnd += lcl_calcAvailableDiff(*pDoc, nCol2, nRow2, nTab2, rData.maEndOffset);
654 :
655 343 : Rectangle aNew = Rectangle( aPos, aEnd );
656 343 : if ( bNegativePage )
657 0 : MirrorRectRTL( aNew );
658 :
659 343 : rData.maLastRect = lcl_makeSafeRectangle(aNew);
660 : }
661 : else
662 : {
663 0 : if ( bNegativePage )
664 0 : aPos.X() = -aPos.X() - rData.maLastRect.GetWidth();
665 : // shouldn't we initialise maLastRect with the object rectangle ?
666 0 : rData.maLastRect.SetPos( aPos );
667 : }
668 343 : }
669 :
670 152 : void ScDrawLayer::RecalcPos( SdrObject* pObj, ScDrawObjData& rData, bool bNegativePage, bool bUpdateNoteCaptionPos )
671 : {
672 : OSL_ENSURE( pDoc, "ScDrawLayer::RecalcPos - missing document" );
673 152 : if( !pDoc )
674 0 : return;
675 :
676 152 : if (rData.meType == ScDrawObjData::CellNote)
677 : {
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 13 : 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 13 : if( ScPostIt* pNote = pDoc->GetNote( rData.maStart ) )
689 12 : pNote->UpdateCaptionPos( rData.maStart );
690 13 : return;
691 : }
692 :
693 139 : bool bValid1 = rData.maStart.IsValid();
694 139 : SCCOL nCol1 = rData.maStart.Col();
695 139 : SCROW nRow1 = rData.maStart.Row();
696 139 : SCTAB nTab1 = rData.maStart.Tab();
697 139 : bool bValid2 = rData.maEnd.IsValid();
698 139 : SCCOL nCol2 = rData.maEnd.Col();
699 139 : SCROW nRow2 = rData.maEnd.Row();
700 139 : SCTAB nTab2 = rData.maEnd.Tab();
701 :
702 139 : if (rData.meType == ScDrawObjData::ValidationCircle)
703 : {
704 : // Validation circle for detective.
705 0 : rData.maLastRect = pObj->GetLogicRect();
706 :
707 0 : Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
708 0 : TwipsToMM( aPos.X() );
709 0 : TwipsToMM( aPos.Y() );
710 :
711 : // Calculations and values as in detfunc.cxx
712 :
713 0 : Size aSize( (long)( TwipsToHmm( pDoc->GetColWidth( nCol1, nTab1) ) ),
714 0 : (long)( TwipsToHmm( pDoc->GetRowHeight( nRow1, nTab1) ) ) );
715 0 : Rectangle aRect( aPos, aSize );
716 0 : aRect.Left() -= 250;
717 0 : aRect.Right() += 250;
718 0 : aRect.Top() -= 70;
719 0 : aRect.Bottom() += 70;
720 0 : if ( bNegativePage )
721 0 : MirrorRectRTL( aRect );
722 :
723 0 : if ( pObj->GetLogicRect() != aRect )
724 : {
725 0 : if (bRecording)
726 0 : AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
727 0 : rData.maLastRect = lcl_makeSafeRectangle(aRect);
728 0 : pObj->SetLogicRect(rData.maLastRect);
729 : }
730 : }
731 139 : else if (rData.meType == ScDrawObjData::DetectiveArrow)
732 : {
733 0 : rData.maLastRect = pObj->GetLogicRect();
734 0 : basegfx::B2DPolygon aCalcPoly;
735 0 : Point aOrigStartPos(pObj->GetPoint(0));
736 0 : Point aOrigEndPos(pObj->GetPoint(1));
737 0 : aCalcPoly.append(basegfx::B2DPoint(aOrigStartPos.X(), aOrigStartPos.Y()));
738 0 : aCalcPoly.append(basegfx::B2DPoint(aOrigEndPos.X(), aOrigEndPos.Y()));
739 : //TODO: do not create multiple Undos for one object (last one can be omitted then)
740 :
741 : SCCOL nLastCol;
742 : SCROW nLastRow;
743 0 : if( bValid1 )
744 : {
745 0 : Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
746 0 : if (!pDoc->ColHidden(nCol1, nTab1, NULL, &nLastCol))
747 0 : aPos.X() += pDoc->GetColWidth( nCol1, nTab1 ) / 4;
748 0 : if (!pDoc->RowHidden(nRow1, nTab1, NULL, &nLastRow))
749 0 : aPos.Y() += pDoc->GetRowHeight( nRow1, nTab1 ) / 2;
750 0 : TwipsToMM( aPos.X() );
751 0 : TwipsToMM( aPos.Y() );
752 0 : Point aStartPos = aPos;
753 0 : if ( bNegativePage )
754 0 : aStartPos.X() = -aStartPos.X(); // don't modify aPos - used below
755 0 : if ( pObj->GetPoint( 0 ) != aStartPos )
756 : {
757 0 : if (bRecording)
758 0 : AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
759 :
760 0 : rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos);
761 0 : pObj->SetPoint( aStartPos, 0 );
762 : }
763 :
764 0 : if( !bValid2 )
765 : {
766 0 : Point aEndPos( aPos.X() + DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
767 0 : if (aEndPos.Y() < 0)
768 0 : aEndPos.Y() += (2 * DET_ARROW_OFFSET);
769 0 : if ( bNegativePage )
770 0 : aEndPos.X() = -aEndPos.X();
771 0 : if ( pObj->GetPoint( 1 ) != aEndPos )
772 : {
773 0 : if (bRecording)
774 0 : AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
775 :
776 0 : rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos);
777 0 : pObj->SetPoint( aEndPos, 1 );
778 : }
779 : }
780 : }
781 0 : if( bValid2 )
782 : {
783 0 : Point aPos( pDoc->GetColOffset( nCol2, nTab2 ), pDoc->GetRowOffset( nRow2, nTab2 ) );
784 0 : if (!pDoc->ColHidden(nCol2, nTab2, NULL, &nLastCol))
785 0 : aPos.X() += pDoc->GetColWidth( nCol2, nTab2 ) / 4;
786 0 : if (!pDoc->RowHidden(nRow2, nTab2, NULL, &nLastRow))
787 0 : aPos.Y() += pDoc->GetRowHeight( nRow2, nTab2 ) / 2;
788 0 : TwipsToMM( aPos.X() );
789 0 : TwipsToMM( aPos.Y() );
790 0 : Point aEndPos = aPos;
791 0 : if ( bNegativePage )
792 0 : aEndPos.X() = -aEndPos.X(); // don't modify aPos - used below
793 0 : if ( pObj->GetPoint( 1 ) != aEndPos )
794 : {
795 0 : if (bRecording)
796 0 : AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
797 :
798 0 : rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 1, aEndPos);
799 0 : pObj->SetPoint( aEndPos, 1 );
800 : }
801 :
802 0 : if( !bValid1 )
803 : {
804 0 : Point aStartPos( aPos.X() - DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
805 0 : if (aStartPos.X() < 0)
806 0 : aStartPos.X() += (2 * DET_ARROW_OFFSET);
807 0 : if (aStartPos.Y() < 0)
808 0 : aStartPos.Y() += (2 * DET_ARROW_OFFSET);
809 0 : if ( bNegativePage )
810 0 : aStartPos.X() = -aStartPos.X();
811 0 : if ( pObj->GetPoint( 0 ) != aStartPos )
812 : {
813 0 : if (bRecording)
814 0 : AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
815 :
816 0 : rData.maLastRect = lcl_UpdateCalcPoly(aCalcPoly, 0, aStartPos);
817 0 : pObj->SetPoint( aStartPos, 0 );
818 : }
819 : }
820 0 : }
821 : }
822 : else
823 : {
824 139 : bool bCanResize = bValid2 && !pObj->IsResizeProtect();
825 :
826 : //First time positioning, must be able to at least move it
827 139 : ScDrawObjData& rNoRotatedAnchor = *GetNonRotatedObjData( pObj, true );
828 139 : if (rData.maLastRect.IsEmpty())
829 : {
830 : // Every shape it is saved with an negative offset relative to cell
831 57 : if (ScDrawLayer::GetAnchorType(*pObj) == SCA_CELL)
832 : {
833 57 : double fRotate(0.0);
834 57 : double fShearX(0.0);
835 :
836 57 : Point aPoint;
837 57 : Rectangle aRect;
838 :
839 57 : basegfx::B2DTuple aScale;
840 114 : basegfx::B2DTuple aTranslate;
841 114 : basegfx::B2DPolyPolygon aPolyPolygon;
842 114 : basegfx::B2DHomMatrix aOriginalMatrix;
843 :
844 57 : aRect = pDoc->GetMMRect(nCol1, nRow1, nCol1 , nRow1, nTab1);
845 :
846 57 : if (bNegativePage)
847 0 : aPoint.X() = aRect.Right();
848 : else
849 57 : aPoint.X() = aRect.Left();
850 57 : aPoint.Y() = aRect.Top();
851 :
852 57 : pObj->TRGetBaseGeometry(aOriginalMatrix, aPolyPolygon);
853 57 : aOriginalMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
854 57 : aTranslate += ::basegfx::B2DTuple(aPoint.X(), aPoint.Y());
855 114 : aOriginalMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
856 : aScale,
857 : fShearX,
858 : fRotate,
859 57 : aTranslate);
860 114 : pObj->TRSetBaseGeometry(aOriginalMatrix, aPolyPolygon);
861 : }
862 :
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.
866 :
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 57 : rNoRotatedAnchor.maStart = rData.maStart;
871 57 : rNoRotatedAnchor.maEnd = rData.maEnd;
872 57 : rNoRotatedAnchor.maStartOffset = rData.maStartOffset;
873 57 : rNoRotatedAnchor.maEndOffset = rData.maEndOffset;
874 :
875 57 : Rectangle aRect = pObj->GetLogicRect();
876 :
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 57 : 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 57 : Rectangle aFullRect = rData.maLastRect;
890 :
891 : // get current size and position from the anchor for use later
892 57 : ResizeLastRectFromAnchor( pObj, rNoRotatedAnchor, true, bNegativePage, bCanResize );
893 :
894 : // resize/position the shape to *full* size e.g. how it would be ( if no hidden rows/cols affected things )
895 57 : pObj->SetLogicRect(aFullRect);
896 : // capture rotated shape ( if relevant )
897 57 : aRect = pObj->GetSnapRect();
898 :
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 57 : ScDrawLayer::GetCellAnchorFromPosition( *pObj, rData, *pDoc, nTab1, false, false );
903 : // reset shape to true 'maybe affected by hidden rows/cols' size calculated previously
904 57 : pObj->SetLogicRect(rNoRotatedAnchor.maLastRect);
905 : }
906 :
907 : // update anchor with snap rect
908 139 : ResizeLastRectFromAnchor( pObj, rData, false, bNegativePage, bCanResize );
909 :
910 139 : if( bCanResize )
911 : {
912 139 : Rectangle aNew = rData.maLastRect;
913 :
914 139 : if ( pObj->GetSnapRect() != aNew )
915 : {
916 90 : Rectangle aOld(pObj->GetSnapRect());
917 :
918 90 : if (bRecording)
919 9 : AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
920 90 : long nOldWidth = aOld.GetWidth();
921 90 : long nOldHeight = aOld.GetHeight();
922 90 : if (pObj->IsPolyObj() && nOldWidth && nOldHeight)
923 : {
924 : // Polyline objects need special treatment.
925 4 : Size aSizeMove(aNew.Left()-aOld.Left(), aNew.Top()-aOld.Top());
926 4 : pObj->NbcMove(aSizeMove);
927 :
928 4 : double fXFrac = static_cast<double>(aNew.GetWidth()) / static_cast<double>(nOldWidth);
929 4 : double fYFrac = static_cast<double>(aNew.GetHeight()) / static_cast<double>(nOldHeight);
930 4 : pObj->NbcResize(aNew.TopLeft(), Fraction(fXFrac), Fraction(fYFrac));
931 : }
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 90 : rData.maLastRect = lcl_makeSafeRectangle(rData.maLastRect);
935 90 : 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 90 : ResizeLastRectFromAnchor( pObj, rNoRotatedAnchor, true, bNegativePage, bCanResize );
939 : }
940 : }
941 : else
942 : {
943 0 : Point aPos( rData.maLastRect.getX(), rData.maLastRect.getY() );
944 0 : if ( pObj->GetRelativePos() != aPos )
945 : {
946 0 : if (bRecording)
947 0 : AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
948 0 : pObj->SetRelativePos( aPos );
949 : }
950 : }
951 : /*
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
955 : */
956 139 : bool bEndAnchorIsBad = !bValid2 || pObj->IsResizeProtect();
957 139 : if (bEndAnchorIsBad)
958 : {
959 : // update 'rotated' anchor
960 0 : ScDrawLayer::UpdateCellAnchorFromPositionEnd(*pObj, rData, *pDoc, nTab1, false);
961 : // update 'unrotated' anchor
962 0 : ScDrawLayer::UpdateCellAnchorFromPositionEnd(*pObj, rNoRotatedAnchor, *pDoc, nTab1 );
963 : }
964 : }
965 : }
966 :
967 3632 : bool ScDrawLayer::GetPrintArea( ScRange& rRange, bool bSetHor, bool bSetVer ) const
968 : {
969 : OSL_ENSURE( pDoc, "ScDrawLayer::GetPrintArea without document" );
970 3632 : if ( !pDoc )
971 0 : return false;
972 :
973 3632 : SCTAB nTab = rRange.aStart.Tab();
974 : OSL_ENSURE( rRange.aEnd.Tab() == nTab, "GetPrintArea: Tab differ" );
975 :
976 3632 : bool bNegativePage = pDoc->IsNegativePage( nTab );
977 :
978 3632 : bool bAny = false;
979 3632 : long nEndX = 0;
980 3632 : long nEndY = 0;
981 3632 : long nStartX = LONG_MAX;
982 3632 : long nStartY = LONG_MAX;
983 :
984 : // Calculate borders
985 :
986 3632 : if (!bSetHor)
987 : {
988 34 : nStartX = 0;
989 34 : SCCOL nStartCol = rRange.aStart.Col();
990 : SCCOL i;
991 34 : for (i=0; i<nStartCol; i++)
992 0 : nStartX +=pDoc->GetColWidth(i,nTab);
993 34 : nEndX = nStartX;
994 34 : SCCOL nEndCol = rRange.aEnd.Col();
995 146 : for (i=nStartCol; i<=nEndCol; i++)
996 112 : nEndX += pDoc->GetColWidth(i,nTab);
997 34 : nStartX = TwipsToHmm( nStartX );
998 34 : nEndX = TwipsToHmm( nEndX );
999 : }
1000 3632 : if (!bSetVer)
1001 : {
1002 0 : nStartY = pDoc->GetRowHeight( 0, rRange.aStart.Row()-1, nTab);
1003 0 : nEndY = nStartY + pDoc->GetRowHeight( rRange.aStart.Row(),
1004 0 : rRange.aEnd.Row(), nTab);
1005 0 : nStartY = TwipsToHmm( nStartY );
1006 0 : nEndY = TwipsToHmm( nEndY );
1007 : }
1008 :
1009 3632 : if ( bNegativePage )
1010 : {
1011 0 : nStartX = -nStartX; // positions are negative, swap start/end so the same comparisons work
1012 0 : nEndX = -nEndX;
1013 0 : ::std::swap( nStartX, nEndX );
1014 : }
1015 :
1016 3632 : const SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1017 : OSL_ENSURE(pPage,"Page not found");
1018 3632 : if (pPage)
1019 : {
1020 3632 : SdrObjListIter aIter( *pPage, IM_FLAT );
1021 3632 : SdrObject* pObject = aIter.Next();
1022 9212 : while (pObject)
1023 : {
1024 : //TODO: test Flags (hidden?)
1025 :
1026 1948 : Rectangle aObjRect = pObject->GetCurrentBoundRect();
1027 1948 : bool bFit = true;
1028 1948 : if ( !bSetHor && ( aObjRect.Right() < nStartX || aObjRect.Left() > nEndX ) )
1029 0 : bFit = false;
1030 1948 : if ( !bSetVer && ( aObjRect.Bottom() < nStartY || aObjRect.Top() > nEndY ) )
1031 0 : bFit = false;
1032 : // #i104716# don't include hidden note objects
1033 1948 : if ( bFit && pObject->GetLayer() != SC_LAYER_HIDDEN )
1034 : {
1035 1910 : if (bSetHor)
1036 : {
1037 1906 : if (aObjRect.Left() < nStartX) nStartX = aObjRect.Left();
1038 1906 : if (aObjRect.Right() > nEndX) nEndX = aObjRect.Right();
1039 : }
1040 1910 : if (bSetVer)
1041 : {
1042 1910 : if (aObjRect.Top() < nStartY) nStartY = aObjRect.Top();
1043 1910 : if (aObjRect.Bottom() > nEndY) nEndY = aObjRect.Bottom();
1044 : }
1045 1910 : bAny = true;
1046 : }
1047 :
1048 1948 : pObject = aIter.Next();
1049 3632 : }
1050 : }
1051 :
1052 3632 : if ( bNegativePage )
1053 : {
1054 0 : nStartX = -nStartX; // reverse transformation, so the same cell address calculation works
1055 0 : nEndX = -nEndX;
1056 0 : ::std::swap( nStartX, nEndX );
1057 : }
1058 :
1059 3632 : if (bAny)
1060 : {
1061 : OSL_ENSURE( nStartX<=nEndX && nStartY<=nEndY, "Start/End wrong in ScDrawLayer::GetPrintArea" );
1062 :
1063 1780 : if (bSetHor)
1064 : {
1065 1776 : nStartX = HmmToTwips( nStartX );
1066 1776 : nEndX = HmmToTwips( nEndX );
1067 : long nWidth;
1068 : SCCOL i;
1069 :
1070 1776 : nWidth = 0;
1071 12947 : for (i=0; i<=MAXCOL && nWidth<=nStartX; i++)
1072 11171 : nWidth += pDoc->GetColWidth(i,nTab);
1073 1776 : rRange.aStart.SetCol( i>0 ? (i-1) : 0 );
1074 :
1075 1776 : nWidth = 0;
1076 23557 : for (i=0; i<=MAXCOL && nWidth<=nEndX; i++) //TODO: start at Start
1077 21781 : nWidth += pDoc->GetColWidth(i,nTab);
1078 1776 : rRange.aEnd.SetCol( i>0 ? (i-1) : 0 );
1079 : }
1080 :
1081 1780 : if (bSetVer)
1082 : {
1083 1780 : nStartY = HmmToTwips( nStartY );
1084 1780 : nEndY = HmmToTwips( nEndY );
1085 1780 : SCROW nRow = pDoc->GetRowForHeight( nTab, nStartY);
1086 1780 : rRange.aStart.SetRow( nRow>0 ? (nRow-1) : 0);
1087 1780 : nRow = pDoc->GetRowForHeight( nTab, nEndY);
1088 : rRange.aEnd.SetRow( nRow == MAXROW ? MAXROW :
1089 1780 : (nRow>0 ? (nRow-1) : 0));
1090 : }
1091 : }
1092 : else
1093 : {
1094 1852 : if (bSetHor)
1095 : {
1096 1822 : rRange.aStart.SetCol(0);
1097 1822 : rRange.aEnd.SetCol(0);
1098 : }
1099 1852 : if (bSetVer)
1100 : {
1101 1852 : rRange.aStart.SetRow(0);
1102 1852 : rRange.aEnd.SetRow(0);
1103 : }
1104 : }
1105 3632 : return bAny;
1106 : }
1107 :
1108 162 : void ScDrawLayer::AddCalcUndo( SdrUndoAction* pUndo )
1109 : {
1110 162 : if (bRecording)
1111 : {
1112 149 : if (!pUndoGroup)
1113 88 : pUndoGroup = new SdrUndoGroup(*this);
1114 :
1115 149 : pUndoGroup->AddAction( pUndo );
1116 : }
1117 : else
1118 13 : delete pUndo;
1119 162 : }
1120 :
1121 168 : void ScDrawLayer::BeginCalcUndo(bool bDisableTextEditUsesCommonUndoManager)
1122 : {
1123 168 : SetDisableTextEditUsesCommonUndoManager(bDisableTextEditUsesCommonUndoManager);
1124 168 : DELETEZ(pUndoGroup);
1125 168 : bRecording = true;
1126 168 : }
1127 :
1128 214 : SdrUndoGroup* ScDrawLayer::GetCalcUndo()
1129 : {
1130 214 : SdrUndoGroup* pRet = pUndoGroup;
1131 214 : pUndoGroup = NULL;
1132 214 : bRecording = false;
1133 214 : SetDisableTextEditUsesCommonUndoManager(false);
1134 214 : return pRet;
1135 : }
1136 :
1137 30 : void ScDrawLayer::MoveArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2,
1138 : SCsCOL nDx,SCsROW nDy, bool bInsDel, bool bUpdateNoteCaptionPos )
1139 : {
1140 : OSL_ENSURE( pDoc, "ScDrawLayer::MoveArea without document" );
1141 30 : if ( !pDoc )
1142 3 : return;
1143 :
1144 30 : if (!bAdjustEnabled)
1145 3 : return;
1146 :
1147 27 : bool bNegativePage = pDoc->IsNegativePage( nTab );
1148 :
1149 27 : Rectangle aRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
1150 27 : lcl_ReverseTwipsToMM( aRect );
1151 : //TODO: use twips directly?
1152 :
1153 27 : Point aMove;
1154 :
1155 27 : if (nDx > 0)
1156 12 : for (SCsCOL s=0; s<nDx; s++)
1157 7 : aMove.X() += pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab);
1158 : else
1159 30 : for (SCsCOL s=-1; s>=nDx; s--)
1160 8 : aMove.X() -= pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab);
1161 27 : if (nDy > 0)
1162 8 : aMove.Y() += pDoc->GetRowHeight( nRow1, nRow1+nDy-1, nTab);
1163 : else
1164 19 : aMove.Y() -= pDoc->GetRowHeight( nRow1+nDy, nRow1-1, nTab);
1165 :
1166 27 : if ( bNegativePage )
1167 0 : aMove.X() = -aMove.X();
1168 :
1169 27 : Point aTopLeft = aRect.TopLeft(); // Beginning when zoomed out
1170 27 : if (bInsDel)
1171 : {
1172 27 : if ( aMove.X() != 0 && nDx < 0 ) // nDx counts cells, sign is independent of RTL
1173 5 : aTopLeft.X() += aMove.X();
1174 27 : if ( aMove.Y() < 0 )
1175 9 : aTopLeft.Y() += aMove.Y();
1176 : }
1177 :
1178 : // Detectiv arrows: Adjust cell position
1179 :
1180 27 : MoveCells( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy, bUpdateNoteCaptionPos );
1181 : }
1182 :
1183 850 : bool ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow )
1184 : {
1185 : OSL_ENSURE( pDoc, "ScDrawLayer::HasObjectsInRows without document" );
1186 850 : if ( !pDoc )
1187 0 : return false;
1188 :
1189 850 : SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1190 : OSL_ENSURE(pPage,"Page not found");
1191 850 : if (!pPage)
1192 0 : return false;
1193 :
1194 : // for an empty page, there's no need to calculate the row heights
1195 850 : if (!pPage->GetObjCount())
1196 697 : return false;
1197 :
1198 153 : Rectangle aTestRect;
1199 :
1200 153 : aTestRect.Top() += pDoc->GetRowHeight( 0, nStartRow-1, nTab);
1201 :
1202 153 : if (nEndRow==MAXROW)
1203 4 : aTestRect.Bottom() = MAXMM;
1204 : else
1205 : {
1206 149 : aTestRect.Bottom() = aTestRect.Top();
1207 149 : aTestRect.Bottom() += pDoc->GetRowHeight( nStartRow, nEndRow, nTab);
1208 149 : TwipsToMM( aTestRect.Bottom() );
1209 : }
1210 :
1211 153 : TwipsToMM( aTestRect.Top() );
1212 :
1213 153 : aTestRect.Left() = 0;
1214 153 : aTestRect.Right() = MAXMM;
1215 :
1216 153 : bool bNegativePage = pDoc->IsNegativePage( nTab );
1217 153 : if ( bNegativePage )
1218 0 : MirrorRectRTL( aTestRect );
1219 :
1220 153 : bool bFound = false;
1221 :
1222 153 : Rectangle aObjRect;
1223 153 : SdrObjListIter aIter( *pPage );
1224 153 : SdrObject* pObject = aIter.Next();
1225 488 : while ( pObject && !bFound )
1226 : {
1227 182 : aObjRect = pObject->GetSnapRect(); //TODO: GetLogicRect ?
1228 182 : if (aTestRect.IsInside(aObjRect.TopLeft()) || aTestRect.IsInside(aObjRect.BottomLeft()))
1229 20 : bFound = true;
1230 :
1231 182 : pObject = aIter.Next();
1232 : }
1233 :
1234 153 : return bFound;
1235 : }
1236 :
1237 1 : void ScDrawLayer::DeleteObjectsInArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1,
1238 : SCCOL nCol2,SCROW nRow2 )
1239 : {
1240 : OSL_ENSURE( pDoc, "ScDrawLayer::DeleteObjectsInArea without document" );
1241 1 : if ( !pDoc )
1242 0 : return;
1243 :
1244 1 : SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1245 : OSL_ENSURE(pPage,"Page ?");
1246 1 : if (!pPage)
1247 0 : return;
1248 :
1249 1 : pPage->RecalcObjOrdNums();
1250 :
1251 1 : const size_t nObjCount = pPage->GetObjCount();
1252 1 : if (nObjCount)
1253 : {
1254 1 : size_t nDelCount = 0;
1255 1 : Rectangle aDelRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
1256 :
1257 1 : boost::scoped_array<SdrObject*> ppObj(new SdrObject*[nObjCount]);
1258 :
1259 2 : SdrObjListIter aIter( *pPage, IM_FLAT );
1260 1 : SdrObject* pObject = aIter.Next();
1261 3 : while (pObject)
1262 : {
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 1 : if (!IsNoteCaption( pObject ))
1266 : {
1267 1 : Rectangle aObjRect = pObject->GetCurrentBoundRect();
1268 1 : if ( aDelRect.IsInside( aObjRect ) )
1269 0 : ppObj[nDelCount++] = pObject;
1270 : }
1271 :
1272 1 : pObject = aIter.Next();
1273 : }
1274 :
1275 1 : if (bRecording)
1276 1 : for (size_t i=1; i<=nDelCount; ++i)
1277 0 : AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
1278 :
1279 1 : for (size_t i=1; i<=nDelCount; ++i)
1280 1 : pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1281 : }
1282 : }
1283 :
1284 0 : void ScDrawLayer::DeleteObjectsInSelection( const ScMarkData& rMark )
1285 : {
1286 : OSL_ENSURE( pDoc, "ScDrawLayer::DeleteObjectsInSelection without document" );
1287 0 : if ( !pDoc )
1288 0 : return;
1289 :
1290 0 : if ( !rMark.IsMultiMarked() )
1291 0 : return;
1292 :
1293 0 : ScRange aMarkRange;
1294 0 : rMark.GetMultiMarkArea( aMarkRange );
1295 :
1296 0 : SCTAB nTabCount = pDoc->GetTableCount();
1297 0 : ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1298 0 : for (; itr != itrEnd && *itr < nTabCount; ++itr)
1299 : {
1300 0 : SCTAB nTab = *itr;
1301 0 : SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1302 0 : if (pPage)
1303 : {
1304 0 : pPage->RecalcObjOrdNums();
1305 0 : const size_t nObjCount = pPage->GetObjCount();
1306 0 : if (nObjCount)
1307 : {
1308 0 : size_t nDelCount = 0;
1309 : // Rectangle around the whole selection
1310 : Rectangle aMarkBound = pDoc->GetMMRect(
1311 0 : aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
1312 0 : aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab );
1313 :
1314 0 : boost::scoped_array<SdrObject*> ppObj(new SdrObject*[nObjCount]);
1315 :
1316 0 : SdrObjListIter aIter( *pPage, IM_FLAT );
1317 0 : SdrObject* pObject = aIter.Next();
1318 0 : while (pObject)
1319 : {
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 0 : if (!IsNoteCaption( pObject ))
1323 : {
1324 0 : Rectangle aObjRect = pObject->GetCurrentBoundRect();
1325 0 : if ( aMarkBound.IsInside( aObjRect ) )
1326 : {
1327 0 : ScRange aRange = pDoc->GetRange( nTab, aObjRect );
1328 0 : if (rMark.IsAllMarked(aRange))
1329 0 : ppObj[nDelCount++] = pObject;
1330 : }
1331 : }
1332 :
1333 0 : pObject = aIter.Next();
1334 : }
1335 :
1336 : // Delete objects (backwards)
1337 :
1338 0 : if (bRecording)
1339 0 : for (size_t i=1; i<=nDelCount; ++i)
1340 0 : AddCalcUndo( new SdrUndoRemoveObj( *ppObj[nDelCount-i] ) );
1341 :
1342 0 : for (size_t i=1; i<=nDelCount; ++i)
1343 0 : pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1344 : }
1345 : }
1346 : else
1347 : {
1348 : OSL_FAIL("pPage?");
1349 : }
1350 : }
1351 : }
1352 :
1353 14 : void ScDrawLayer::CopyToClip( ScDocument* pClipDoc, SCTAB nTab, const Rectangle& rRange )
1354 : {
1355 : // copy everything in the specified range into the same page (sheet) in the clipboard doc
1356 :
1357 14 : SdrPage* pSrcPage = GetPage(static_cast<sal_uInt16>(nTab));
1358 14 : if (pSrcPage)
1359 : {
1360 14 : ScDrawLayer* pDestModel = NULL;
1361 14 : SdrPage* pDestPage = NULL;
1362 :
1363 14 : SdrObjListIter aIter( *pSrcPage, IM_FLAT );
1364 14 : SdrObject* pOldObject = aIter.Next();
1365 42 : while (pOldObject)
1366 : {
1367 14 : Rectangle aObjRect = pOldObject->GetCurrentBoundRect();
1368 : // do not copy internal objects (detective) and note captions
1369 14 : if ( rRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) )
1370 : {
1371 0 : if ( !pDestModel )
1372 : {
1373 0 : pDestModel = pClipDoc->GetDrawLayer(); // does the document already have a drawing layer?
1374 0 : if ( !pDestModel )
1375 : {
1376 : // allocate drawing layer in clipboard document only if there are objects to copy
1377 :
1378 0 : pClipDoc->InitDrawLayer(); //TODO: create contiguous pages
1379 0 : pDestModel = pClipDoc->GetDrawLayer();
1380 : }
1381 0 : if (pDestModel)
1382 0 : pDestPage = pDestModel->GetPage( static_cast<sal_uInt16>(nTab) );
1383 : }
1384 :
1385 : OSL_ENSURE( pDestPage, "no page" );
1386 0 : if (pDestPage)
1387 : {
1388 0 : SdrObject* pNewObject = pOldObject->Clone();
1389 0 : pNewObject->SetModel(pDestModel);
1390 0 : pNewObject->SetPage(pDestPage);
1391 :
1392 0 : uno::Reference< chart2::XChartDocument > xOldChart( ScChartHelper::GetChartFromSdrObject( pOldObject ) );
1393 0 : if(!xOldChart.is())//#i110034# do not move charts as they lose all their data references otherwise
1394 0 : pNewObject->NbcMove(Size(0,0));
1395 0 : pDestPage->InsertObject( pNewObject );
1396 :
1397 : // no undo needed in clipboard document
1398 : // charts are not updated
1399 : }
1400 : }
1401 :
1402 14 : pOldObject = aIter.Next();
1403 14 : }
1404 : }
1405 14 : }
1406 :
1407 0 : static bool lcl_IsAllInRange( const ::std::vector< ScRangeList >& rRangesVector, const ScRange& rClipRange )
1408 : {
1409 : // check if every range of rRangesVector is completely in rClipRange
1410 :
1411 0 : ::std::vector< ScRangeList >::const_iterator aIt = rRangesVector.begin();
1412 0 : for( ;aIt!=rRangesVector.end(); ++aIt )
1413 : {
1414 0 : const ScRangeList& rRanges = *aIt;
1415 0 : for ( size_t i = 0, nCount = rRanges.size(); i < nCount; i++ )
1416 : {
1417 0 : ScRange aRange = *rRanges[ i ];
1418 0 : if ( !rClipRange.In( aRange ) )
1419 : {
1420 0 : return false; // at least one range is not valid
1421 : }
1422 : }
1423 : }
1424 :
1425 0 : return true; // everything is fine
1426 : }
1427 :
1428 0 : static bool lcl_MoveRanges( ::std::vector< ScRangeList >& rRangesVector, const ScRange& rSourceRange, const ScAddress& rDestPos )
1429 : {
1430 0 : bool bChanged = false;
1431 :
1432 0 : ::std::vector< ScRangeList >::iterator aIt = rRangesVector.begin();
1433 0 : for( ;aIt!=rRangesVector.end(); ++aIt )
1434 : {
1435 0 : ScRangeList& rRanges = *aIt;
1436 0 : for ( size_t i = 0, nCount = rRanges.size(); i < nCount; i++ )
1437 : {
1438 0 : ScRange* pRange = rRanges[ i ];
1439 0 : if ( rSourceRange.In( *pRange ) )
1440 : {
1441 0 : SCsCOL nDiffX = rDestPos.Col() - (SCsCOL)rSourceRange.aStart.Col();
1442 0 : SCsROW nDiffY = rDestPos.Row() - (SCsROW)rSourceRange.aStart.Row();
1443 0 : SCsTAB nDiffZ = rDestPos.Tab() - (SCsTAB)rSourceRange.aStart.Tab();
1444 0 : pRange->Move( nDiffX, nDiffY, nDiffZ );
1445 0 : bChanged = true;
1446 : }
1447 : }
1448 : }
1449 :
1450 0 : return bChanged;
1451 : }
1452 :
1453 0 : void ScDrawLayer::CopyFromClip( ScDrawLayer* pClipModel, SCTAB nSourceTab, const Rectangle& rSourceRange,
1454 : const ScAddress& rDestPos, const Rectangle& rDestRange )
1455 : {
1456 : OSL_ENSURE( pDoc, "ScDrawLayer::CopyFromClip without document" );
1457 0 : if ( !pDoc )
1458 0 : return;
1459 :
1460 0 : if (!pClipModel)
1461 0 : return;
1462 :
1463 0 : if (bDrawIsInUndo) //TODO: can this happen?
1464 : {
1465 : OSL_FAIL("CopyFromClip, bDrawIsInUndo");
1466 0 : return;
1467 : }
1468 :
1469 0 : bool bMirrorObj = ( rSourceRange.Left() < 0 && rSourceRange.Right() < 0 &&
1470 0 : rDestRange.Left() > 0 && rDestRange.Right() > 0 ) ||
1471 0 : ( rSourceRange.Left() > 0 && rSourceRange.Right() > 0 &&
1472 0 : rDestRange.Left() < 0 && rDestRange.Right() < 0 );
1473 0 : Rectangle aMirroredSource = rSourceRange;
1474 0 : if ( bMirrorObj )
1475 0 : MirrorRectRTL( aMirroredSource );
1476 :
1477 0 : SCTAB nDestTab = rDestPos.Tab();
1478 :
1479 0 : SdrPage* pSrcPage = pClipModel->GetPage(static_cast<sal_uInt16>(nSourceTab));
1480 0 : SdrPage* pDestPage = GetPage(static_cast<sal_uInt16>(nDestTab));
1481 : OSL_ENSURE( pSrcPage && pDestPage, "draw page missing" );
1482 0 : if ( !pSrcPage || !pDestPage )
1483 0 : return;
1484 :
1485 0 : SdrObjListIter aIter( *pSrcPage, IM_FLAT );
1486 0 : SdrObject* pOldObject = aIter.Next();
1487 :
1488 0 : 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 0 : bool bSameDoc = pDoc && pClipDoc && pDoc->GetPool() == pClipDoc->GetPool();
1493 0 : bool bDestClip = pDoc && pDoc->IsClipboard();
1494 :
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 0 : OUString aDestTabName;
1498 0 : bool bRestoreDestTabName = false;
1499 0 : if( pOldObject && !bSameDoc && !bDestClip )
1500 : {
1501 0 : if( pDoc && pClipDoc )
1502 : {
1503 0 : OUString aSourceTabName;
1504 0 : if( pClipDoc->GetName( nSourceTab, aSourceTabName )
1505 0 : && pDoc->GetName( nDestTab, aDestTabName ) )
1506 : {
1507 0 : if( !aSourceTabName.equals(aDestTabName) &&
1508 0 : pDoc->ValidNewTabName(aSourceTabName) )
1509 : {
1510 0 : bRestoreDestTabName = pDoc->RenameTab( nDestTab, aSourceTabName ); //sal_Bool bUpdateRef = sal_True, sal_Bool bExternalDocument = sal_False
1511 : }
1512 0 : }
1513 : }
1514 : }
1515 :
1516 : // first mirror, then move
1517 0 : Size aMove( rDestRange.Left() - aMirroredSource.Left(), rDestRange.Top() - aMirroredSource.Top() );
1518 :
1519 0 : long nDestWidth = rDestRange.GetWidth();
1520 0 : long nDestHeight = rDestRange.GetHeight();
1521 0 : long nSourceWidth = rSourceRange.GetWidth();
1522 0 : long nSourceHeight = rSourceRange.GetHeight();
1523 :
1524 0 : long nWidthDiff = nDestWidth - nSourceWidth;
1525 0 : long nHeightDiff = nDestHeight - nSourceHeight;
1526 :
1527 0 : Fraction aHorFract(1,1);
1528 0 : Fraction aVerFract(1,1);
1529 0 : 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 0 : if ( std::abs(nWidthDiff) > 1 && nDestWidth > 1 && nSourceWidth > 1 )
1533 : {
1534 0 : aHorFract = Fraction( nDestWidth, nSourceWidth );
1535 0 : bResize = true;
1536 : }
1537 0 : if ( std::abs(nHeightDiff) > 1 && nDestHeight > 1 && nSourceHeight > 1 )
1538 : {
1539 0 : aVerFract = Fraction( nDestHeight, nSourceHeight );
1540 0 : bResize = true;
1541 : }
1542 0 : Point aRefPos = rDestRange.TopLeft(); // for resizing (after moving)
1543 :
1544 0 : while (pOldObject)
1545 : {
1546 0 : Rectangle aObjRect = pOldObject->GetCurrentBoundRect();
1547 : // do not copy internal objects (detective) and note captions
1548 0 : if ( rSourceRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) )
1549 : {
1550 0 : SdrObject* pNewObject = pOldObject->Clone();
1551 0 : pNewObject->SetModel(this);
1552 0 : pNewObject->SetPage(pDestPage);
1553 :
1554 0 : if ( bMirrorObj )
1555 0 : MirrorRTL( pNewObject ); // first mirror, then move
1556 :
1557 0 : pNewObject->NbcMove( aMove );
1558 0 : if ( bResize )
1559 0 : pNewObject->NbcResize( aRefPos, aHorFract, aVerFract );
1560 :
1561 0 : pDestPage->InsertObject( pNewObject );
1562 0 : if (bRecording)
1563 0 : AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) );
1564 :
1565 : //#i110034# handle chart data references (after InsertObject)
1566 :
1567 0 : if ( pNewObject->GetObjIdentifier() == OBJ_OLE2 )
1568 : {
1569 0 : uno::Reference< embed::XEmbeddedObject > xIPObj = static_cast<SdrOle2Obj*>(pNewObject)->GetObjRef();
1570 0 : uno::Reference< embed::XClassifiedObject > xClassified( xIPObj, uno::UNO_QUERY );
1571 0 : SvGlobalName aObjectClassName;
1572 0 : if ( xClassified.is() )
1573 : {
1574 : try {
1575 0 : aObjectClassName = SvGlobalName( xClassified->getClassID() );
1576 0 : } catch( uno::Exception& )
1577 : {
1578 : // TODO: handle error?
1579 : }
1580 : }
1581 :
1582 0 : if ( xIPObj.is() && SotExchange::IsChart( aObjectClassName ) )
1583 : {
1584 0 : uno::Reference< chart2::XChartDocument > xNewChart( ScChartHelper::GetChartFromSdrObject( pNewObject ) );
1585 0 : if( xNewChart.is() && !xNewChart->hasInternalDataProvider() )
1586 : {
1587 0 : OUString aChartName = static_cast<SdrOle2Obj*>(pNewObject)->GetPersistName();
1588 0 : ::std::vector< ScRangeList > aRangesVector;
1589 0 : pDoc->GetChartRanges( aChartName, aRangesVector, pDoc );
1590 0 : if( !aRangesVector.empty() )
1591 : {
1592 0 : bool bInSourceRange = false;
1593 0 : ScRange aClipRange;
1594 0 : if ( pClipDoc )
1595 : {
1596 : SCCOL nClipStartX;
1597 : SCROW nClipStartY;
1598 : SCCOL nClipEndX;
1599 : SCROW nClipEndY;
1600 0 : pClipDoc->GetClipStart( nClipStartX, nClipStartY );
1601 0 : pClipDoc->GetClipArea( nClipEndX, nClipEndY, true );
1602 0 : nClipEndX = nClipEndX + nClipStartX;
1603 0 : nClipEndY += nClipStartY; // GetClipArea returns the difference
1604 :
1605 0 : SCTAB nClipTab = bRestoreDestTabName ? nDestTab : nSourceTab;
1606 0 : aClipRange = ScRange( nClipStartX, nClipStartY, nClipTab,
1607 0 : nClipEndX, nClipEndY, nClipTab );
1608 :
1609 0 : bInSourceRange = lcl_IsAllInRange( aRangesVector, aClipRange );
1610 : }
1611 :
1612 : // always lose references when pasting into a clipboard document (transpose)
1613 0 : if ( ( bInSourceRange || bSameDoc ) && !bDestClip )
1614 : {
1615 0 : if ( bInSourceRange )
1616 : {
1617 0 : if ( rDestPos != aClipRange.aStart )
1618 : {
1619 : // update the data ranges to the new (copied) position
1620 0 : if ( lcl_MoveRanges( aRangesVector, aClipRange, rDestPos ) )
1621 0 : pDoc->SetChartRanges( aChartName, aRangesVector );
1622 : }
1623 : }
1624 : else
1625 : {
1626 : // leave the ranges unchanged
1627 : }
1628 : }
1629 : else
1630 : {
1631 : // pasting into a new document without the complete source data
1632 : // -> break connection to source data and switch to own data
1633 :
1634 0 : uno::Reference< chart::XChartDocument > xOldChartDoc( ScChartHelper::GetChartFromSdrObject( pOldObject ), uno::UNO_QUERY );
1635 0 : uno::Reference< chart::XChartDocument > xNewChartDoc( xNewChart, uno::UNO_QUERY );
1636 0 : if( xOldChartDoc.is() && xNewChartDoc.is() )
1637 0 : xNewChartDoc->attachData( xOldChartDoc->getData() );
1638 :
1639 : // (see ScDocument::UpdateChartListenerCollection, PastingDrawFromOtherDoc)
1640 : }
1641 0 : }
1642 0 : }
1643 0 : }
1644 : }
1645 : }
1646 :
1647 0 : pOldObject = aIter.Next();
1648 : }
1649 :
1650 0 : if( bRestoreDestTabName )
1651 0 : pDoc->RenameTab( nDestTab, aDestTabName );
1652 : }
1653 :
1654 2 : void ScDrawLayer::MirrorRTL( SdrObject* pObj )
1655 : {
1656 2 : sal_uInt16 nIdent = pObj->GetObjIdentifier();
1657 :
1658 : // don't mirror OLE or graphics, otherwise ask the object
1659 : // if it can be mirrored
1660 2 : bool bCanMirror = ( nIdent != OBJ_GRAF && nIdent != OBJ_OLE2 );
1661 2 : if (bCanMirror)
1662 : {
1663 2 : SdrObjTransformInfoRec aInfo;
1664 2 : pObj->TakeObjInfo( aInfo );
1665 2 : bCanMirror = aInfo.bMirror90Allowed;
1666 : }
1667 :
1668 2 : if (bCanMirror)
1669 : {
1670 2 : Point aRef1( 0, 0 );
1671 2 : Point aRef2( 0, 1 );
1672 2 : if (bRecording)
1673 0 : AddCalcUndo( new SdrUndoGeoObj( *pObj ) );
1674 2 : pObj->Mirror( aRef1, aRef2 );
1675 : }
1676 : else
1677 : {
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 0 : Rectangle aObjRect = pObj->GetLogicRect();
1682 0 : Size aMoveSize( -(aObjRect.Left() + aObjRect.Right()), 0 );
1683 0 : if (bRecording)
1684 0 : AddCalcUndo( new SdrUndoMoveObj( *pObj, aMoveSize ) );
1685 0 : pObj->Move( aMoveSize );
1686 : }
1687 2 : }
1688 :
1689 0 : void ScDrawLayer::MirrorRectRTL( Rectangle& rRect )
1690 : {
1691 : // mirror and swap left/right
1692 0 : long nTemp = rRect.Left();
1693 0 : rRect.Left() = -rRect.Right();
1694 0 : rRect.Right() = -nTemp;
1695 0 : }
1696 :
1697 105 : Rectangle ScDrawLayer::GetCellRect( ScDocument& rDoc, const ScAddress& rPos, bool bMergedCell )
1698 : {
1699 105 : Rectangle aCellRect;
1700 : OSL_ENSURE( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ), "ScDrawLayer::GetCellRect - invalid cell address" );
1701 105 : if( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ) )
1702 : {
1703 : // find top left position of passed cell address
1704 105 : Point aTopLeft;
1705 271 : for( SCCOL nCol = 0; nCol < rPos.Col(); ++nCol )
1706 166 : aTopLeft.X() += rDoc.GetColWidth( nCol, rPos.Tab() );
1707 105 : if( rPos.Row() > 0 )
1708 76 : aTopLeft.Y() += rDoc.GetRowHeight( 0, rPos.Row() - 1, rPos.Tab() );
1709 :
1710 : // find bottom-right position of passed cell address
1711 105 : ScAddress aEndPos = rPos;
1712 105 : if( bMergedCell )
1713 : {
1714 105 : const ScMergeAttr* pMerge = static_cast< const ScMergeAttr* >( rDoc.GetAttr( rPos.Col(), rPos.Row(), rPos.Tab(), ATTR_MERGE ) );
1715 105 : if( pMerge->GetColMerge() > 1 )
1716 0 : aEndPos.IncCol( pMerge->GetColMerge() - 1 );
1717 105 : if( pMerge->GetRowMerge() > 1 )
1718 0 : aEndPos.IncRow( pMerge->GetRowMerge() - 1 );
1719 : }
1720 105 : Point aBotRight = aTopLeft;
1721 210 : for( SCCOL nCol = rPos.Col(); nCol <= aEndPos.Col(); ++nCol )
1722 105 : aBotRight.X() += rDoc.GetColWidth( nCol, rPos.Tab() );
1723 105 : aBotRight.Y() += rDoc.GetRowHeight( rPos.Row(), aEndPos.Row(), rPos.Tab() );
1724 :
1725 : // twips -> 1/100 mm
1726 105 : aTopLeft.X() = static_cast< long >( aTopLeft.X() * HMM_PER_TWIPS );
1727 105 : aTopLeft.Y() = static_cast< long >( aTopLeft.Y() * HMM_PER_TWIPS );
1728 105 : aBotRight.X() = static_cast< long >( aBotRight.X() * HMM_PER_TWIPS );
1729 105 : aBotRight.Y() = static_cast< long >( aBotRight.Y() * HMM_PER_TWIPS );
1730 :
1731 105 : aCellRect = Rectangle( aTopLeft, aBotRight );
1732 105 : if( rDoc.IsNegativePage( rPos.Tab() ) )
1733 0 : MirrorRectRTL( aCellRect );
1734 : }
1735 105 : return aCellRect;
1736 : }
1737 :
1738 0 : OUString ScDrawLayer::GetVisibleName( SdrObject* pObj )
1739 : {
1740 0 : OUString aName = pObj->GetName();
1741 0 : if ( pObj->GetObjIdentifier() == OBJ_OLE2 )
1742 : {
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.
1747 :
1748 0 : if ( aName.isEmpty() )
1749 0 : aName = static_cast<SdrOle2Obj*>(pObj)->GetPersistName();
1750 : }
1751 0 : return aName;
1752 : }
1753 :
1754 1 : inline bool IsNamedObject( SdrObject* pObj, const OUString& rName )
1755 : {
1756 : // sal_True if rName is the object's Name or PersistName
1757 : // (used to find a named object)
1758 :
1759 4 : return ( pObj->GetName().equals(rName) ||
1760 3 : ( pObj->GetObjIdentifier() == OBJ_OLE2 &&
1761 4 : static_cast<SdrOle2Obj*>(pObj)->GetPersistName() == rName ) );
1762 : }
1763 :
1764 7 : SdrObject* ScDrawLayer::GetNamedObject( const OUString& rName, sal_uInt16 nId, SCTAB& rFoundTab ) const
1765 : {
1766 7 : sal_uInt16 nTabCount = GetPageCount();
1767 14 : for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++)
1768 : {
1769 7 : const SdrPage* pPage = GetPage(nTab);
1770 : OSL_ENSURE(pPage,"Page ?");
1771 7 : if (pPage)
1772 : {
1773 7 : SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
1774 7 : SdrObject* pObject = aIter.Next();
1775 15 : while (pObject)
1776 : {
1777 1 : if ( nId == 0 || pObject->GetObjIdentifier() == nId )
1778 1 : if ( IsNamedObject( pObject, rName ) )
1779 : {
1780 0 : rFoundTab = static_cast<SCTAB>(nTab);
1781 0 : return pObject;
1782 : }
1783 :
1784 1 : pObject = aIter.Next();
1785 7 : }
1786 : }
1787 : }
1788 :
1789 7 : return NULL;
1790 : }
1791 :
1792 0 : OUString ScDrawLayer::GetNewGraphicName( long* pnCounter ) const
1793 : {
1794 0 : OUString aBase = ScGlobal::GetRscString(STR_GRAPHICNAME);
1795 0 : aBase += " ";
1796 :
1797 0 : bool bThere = true;
1798 0 : OUString aGraphicName;
1799 : SCTAB nDummy;
1800 0 : long nId = pnCounter ? *pnCounter : 0;
1801 0 : while (bThere)
1802 : {
1803 0 : ++nId;
1804 0 : aGraphicName = aBase;
1805 0 : aGraphicName += OUString::number( nId );
1806 0 : bThere = ( GetNamedObject( aGraphicName, 0, nDummy ) != NULL );
1807 : }
1808 :
1809 0 : if ( pnCounter )
1810 0 : *pnCounter = nId;
1811 :
1812 0 : return aGraphicName;
1813 : }
1814 :
1815 85 : void ScDrawLayer::EnsureGraphicNames()
1816 : {
1817 : // make sure all graphic objects have names (after Excel import etc.)
1818 :
1819 85 : sal_uInt16 nTabCount = GetPageCount();
1820 313 : for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++)
1821 : {
1822 228 : SdrPage* pPage = GetPage(nTab);
1823 : OSL_ENSURE(pPage,"Page ?");
1824 228 : if (pPage)
1825 : {
1826 228 : SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
1827 228 : SdrObject* pObject = aIter.Next();
1828 :
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. */
1832 228 : long nCounter = 0;
1833 :
1834 564 : while (pObject)
1835 : {
1836 108 : if ( pObject->GetObjIdentifier() == OBJ_GRAF && pObject->GetName().isEmpty())
1837 0 : pObject->SetName( GetNewGraphicName( &nCounter ) );
1838 :
1839 108 : pObject = aIter.Next();
1840 228 : }
1841 : }
1842 : }
1843 85 : }
1844 :
1845 : namespace
1846 : {
1847 2595 : SdrObjUserData* GetFirstUserDataOfType(const SdrObject *pObj, sal_uInt16 nId)
1848 : {
1849 2595 : sal_uInt16 nCount = pObj ? pObj->GetUserDataCount() : 0;
1850 2687 : for( sal_uInt16 i = 0; i < nCount; i++ )
1851 : {
1852 1496 : SdrObjUserData* pData = pObj->GetUserData( i );
1853 1496 : if( pData && pData->GetInventor() == SC_DRAWLAYER && pData->GetId() == nId )
1854 1404 : return pData;
1855 : }
1856 1191 : return NULL;
1857 : }
1858 :
1859 152 : void DeleteFirstUserDataOfType(SdrObject *pObj, sal_uInt16 nId)
1860 : {
1861 152 : sal_uInt16 nCount = pObj ? pObj->GetUserDataCount() : 0;
1862 158 : for( sal_uInt16 i = nCount; i > 0; i-- )
1863 : {
1864 6 : SdrObjUserData* pData = pObj->GetUserData( i-1 );
1865 6 : if( pData && pData->GetInventor() == SC_DRAWLAYER && pData->GetId() == nId )
1866 6 : pObj->DeleteUserData(i-1);
1867 : }
1868 152 : }
1869 : }
1870 :
1871 201 : void ScDrawLayer::SetVisualCellAnchored( SdrObject &rObj, const ScDrawObjData &rAnchor )
1872 : {
1873 201 : ScDrawObjData* pAnchor = GetNonRotatedObjData( &rObj, true );
1874 201 : pAnchor->maStart = rAnchor.maStart;
1875 201 : pAnchor->maEnd = rAnchor.maEnd;
1876 201 : pAnchor->maStartOffset = rAnchor.maStartOffset;
1877 201 : pAnchor->maEndOffset = rAnchor.maEndOffset;
1878 201 : }
1879 :
1880 259 : void ScDrawLayer::SetCellAnchored( SdrObject &rObj, const ScDrawObjData &rAnchor )
1881 : {
1882 259 : ScDrawObjData* pAnchor = GetObjData( &rObj, true );
1883 259 : pAnchor->maStart = rAnchor.maStart;
1884 259 : pAnchor->maEnd = rAnchor.maEnd;
1885 259 : pAnchor->maStartOffset = rAnchor.maStartOffset;
1886 259 : pAnchor->maEndOffset = rAnchor.maEndOffset;
1887 259 : }
1888 :
1889 201 : void ScDrawLayer::SetCellAnchoredFromPosition( SdrObject &rObj, const ScDocument &rDoc, SCTAB nTab )
1890 : {
1891 201 : ScDrawObjData aAnchor;
1892 : // set anchor in terms of the visual ( SnapRect )
1893 : // object ( e.g. for when object is rotated )
1894 201 : GetCellAnchorFromPosition( rObj, aAnchor, rDoc, nTab, false );
1895 201 : 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 402 : ScDrawObjData aVisAnchor;
1899 201 : GetCellAnchorFromPosition( rObj, aVisAnchor, rDoc, nTab );
1900 201 : SetVisualCellAnchored( rObj, aVisAnchor );
1901 : // absolutely necessary to set flag that in order to preven ScDrawLayer::RecalcPos
1902 : // doing an initialisation hack
1903 201 : if ( ScDrawObjData* pAnchor = GetObjData( &rObj ) )
1904 : {
1905 201 : pAnchor->maLastRect = rObj.GetSnapRect();
1906 201 : }
1907 201 : }
1908 :
1909 610 : void ScDrawLayer::GetCellAnchorFromPosition( SdrObject &rObj, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab, bool bUseLogicRect, bool bHiddenAsZero )
1910 : {
1911 610 : Rectangle aObjRect( bUseLogicRect ? rObj.GetLogicRect() : rObj.GetSnapRect() );
1912 610 : ScRange aRange = rDoc.GetRange( nTab, aObjRect, bHiddenAsZero );
1913 :
1914 610 : Rectangle aCellRect;
1915 :
1916 610 : rAnchor.maStart = aRange.aStart;
1917 610 : aCellRect = rDoc.GetMMRect( aRange.aStart.Col(), aRange.aStart.Row(),
1918 1220 : aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab(), bHiddenAsZero );
1919 610 : rAnchor.maStartOffset.Y() = aObjRect.Top()-aCellRect.Top();
1920 610 : if (!rDoc.IsNegativePage(nTab))
1921 610 : rAnchor.maStartOffset.X() = aObjRect.Left()-aCellRect.Left();
1922 : else
1923 0 : rAnchor.maStartOffset.X() = aCellRect.Right()-aObjRect.Right();
1924 :
1925 610 : rAnchor.maEnd = aRange.aEnd;
1926 610 : aCellRect = rDoc.GetMMRect( aRange.aEnd.Col(), aRange.aEnd.Row(),
1927 1220 : aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab(), bHiddenAsZero );
1928 610 : rAnchor.maEndOffset.Y() = aObjRect.Bottom()-aCellRect.Top();
1929 610 : if (!rDoc.IsNegativePage(nTab))
1930 610 : rAnchor.maEndOffset.X() = aObjRect.Right()-aCellRect.Left();
1931 : else
1932 0 : rAnchor.maEndOffset.X() = aCellRect.Right()-aObjRect.Left();
1933 :
1934 610 : }
1935 :
1936 1 : void ScDrawLayer::UpdateCellAnchorFromPositionEnd( SdrObject &rObj, ScDrawObjData &rAnchor, const ScDocument &rDoc, SCTAB nTab, bool bUseLogicRect )
1937 : {
1938 1 : Rectangle aObjRect(bUseLogicRect ? rObj.GetLogicRect() : rObj.GetSnapRect());
1939 1 : ScRange aRange = rDoc.GetRange( nTab, aObjRect );
1940 :
1941 1 : ScDrawObjData* pAnchor = &rAnchor;
1942 1 : pAnchor->maEnd = aRange.aEnd;
1943 :
1944 1 : Rectangle aCellRect;
1945 1 : aCellRect = rDoc.GetMMRect( aRange.aEnd.Col(), aRange.aEnd.Row(),
1946 2 : aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aEnd.Tab() );
1947 1 : pAnchor->maEndOffset.Y() = aObjRect.Bottom()-aCellRect.Top();
1948 1 : if (!rDoc.IsNegativePage(nTab))
1949 1 : pAnchor->maEndOffset.X() = aObjRect.Right()-aCellRect.Left();
1950 : else
1951 0 : pAnchor->maEndOffset.X() = aCellRect.Right()-aObjRect.Left();
1952 1 : }
1953 :
1954 2 : bool ScDrawLayer::IsCellAnchored( const SdrObject& rObj )
1955 : {
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 2 : return GetFirstUserDataOfType(&rObj, SC_UD_OBJDATA) != NULL;
1959 : }
1960 :
1961 76 : void ScDrawLayer::SetPageAnchored( SdrObject &rObj )
1962 : {
1963 76 : DeleteFirstUserDataOfType(&rObj, SC_UD_OBJDATA);
1964 76 : DeleteFirstUserDataOfType(&rObj, SC_UD_OBJDATA);
1965 76 : }
1966 :
1967 162 : ScAnchorType ScDrawLayer::GetAnchorType( const SdrObject &rObj )
1968 : {
1969 : //If this object has a cell anchor associated with it
1970 : //then its cell-anchored, otherwise its page-anchored
1971 162 : return ScDrawLayer::GetObjData(const_cast<SdrObject*>(&rObj)) ? SCA_CELL : SCA_PAGE;
1972 : }
1973 :
1974 377 : ScDrawObjData* ScDrawLayer::GetNonRotatedObjData( SdrObject* pObj, bool bCreate )
1975 : {
1976 377 : sal_uInt16 nCount = pObj ? pObj->GetUserDataCount() : 0;
1977 377 : sal_uInt16 nFound = 0;
1978 748 : for( sal_uInt16 i = 0; i < nCount; i++ )
1979 : {
1980 482 : SdrObjUserData* pData = pObj->GetUserData( i );
1981 482 : if( pData && pData->GetInventor() == SC_DRAWLAYER && pData->GetId() == SC_UD_OBJDATA && ++nFound == 2 )
1982 111 : return static_cast<ScDrawObjData*>(pData);
1983 : }
1984 266 : if( pObj && bCreate )
1985 : {
1986 257 : ScDrawObjData* pData = new ScDrawObjData;
1987 257 : pObj->AppendUserData(pData);
1988 257 : return pData;
1989 : }
1990 9 : return 0;
1991 : }
1992 :
1993 2491 : ScDrawObjData* ScDrawLayer::GetObjData( SdrObject* pObj, bool bCreate )
1994 : {
1995 2491 : if (SdrObjUserData *pData = GetFirstUserDataOfType(pObj, SC_UD_OBJDATA))
1996 1391 : return static_cast<ScDrawObjData*>(pData);
1997 :
1998 1100 : if( pObj && bCreate )
1999 : {
2000 346 : ScDrawObjData* pData = new ScDrawObjData;
2001 346 : pObj->AppendUserData(pData);
2002 346 : return pData;
2003 : }
2004 754 : return 0;
2005 : }
2006 :
2007 396 : ScDrawObjData* ScDrawLayer::GetObjDataTab( SdrObject* pObj, SCTAB nTab )
2008 : {
2009 396 : ScDrawObjData* pData = GetObjData( pObj );
2010 396 : if ( pData )
2011 : {
2012 175 : if ( pData->maStart.IsValid() )
2013 175 : pData->maStart.SetTab( nTab );
2014 175 : if ( pData->maEnd.IsValid() )
2015 145 : pData->maEnd.SetTab( nTab );
2016 : }
2017 396 : return pData;
2018 : }
2019 :
2020 338 : bool ScDrawLayer::IsNoteCaption( SdrObject* pObj )
2021 : {
2022 338 : ScDrawObjData* pData = pObj ? GetObjData( pObj ) : 0;
2023 338 : return pData && pData->meType == ScDrawObjData::CellNote;
2024 : }
2025 :
2026 14 : ScDrawObjData* ScDrawLayer::GetNoteCaptionData( SdrObject* pObj, SCTAB nTab )
2027 : {
2028 14 : ScDrawObjData* pData = pObj ? GetObjDataTab( pObj, nTab ) : 0;
2029 14 : return (pData && pData->meType == ScDrawObjData::CellNote) ? pData : 0;
2030 : }
2031 :
2032 5 : ScIMapInfo* ScDrawLayer::GetIMapInfo( SdrObject* pObj )
2033 : {
2034 5 : return static_cast<ScIMapInfo*>(GetFirstUserDataOfType(pObj, SC_UD_IMAPDATA));
2035 : }
2036 :
2037 0 : IMapObject* ScDrawLayer::GetHitIMapObject( SdrObject* pObj,
2038 : const Point& rWinPoint, const vcl::Window& rCmpWnd )
2039 : {
2040 0 : const MapMode aMap100( MAP_100TH_MM );
2041 0 : MapMode aWndMode = rCmpWnd.GetMapMode();
2042 0 : Point aRelPoint( rCmpWnd.LogicToLogic( rWinPoint, &aWndMode, &aMap100 ) );
2043 0 : Rectangle aLogRect = rCmpWnd.LogicToLogic( pObj->GetLogicRect(), &aWndMode, &aMap100 );
2044 0 : ScIMapInfo* pIMapInfo = GetIMapInfo( pObj );
2045 0 : IMapObject* pIMapObj = NULL;
2046 :
2047 0 : if ( pIMapInfo )
2048 : {
2049 0 : Size aGraphSize;
2050 0 : ImageMap& rImageMap = (ImageMap&) pIMapInfo->GetImageMap();
2051 0 : Graphic aGraphic;
2052 0 : bool bObjSupported = false;
2053 :
2054 0 : if ( pObj->ISA( SdrGrafObj ) ) // Simple Graphics object
2055 : {
2056 0 : const SdrGrafObj* pGrafObj = static_cast<const SdrGrafObj*>( pObj );
2057 0 : const GeoStat& rGeo = pGrafObj->GetGeoStat();
2058 0 : const Graphic& rGraphic = pGrafObj->GetGraphic();
2059 :
2060 : // Reverse rotation
2061 0 : if ( rGeo.nRotationAngle )
2062 0 : RotatePoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nSin, rGeo.nCos );
2063 :
2064 : // Reverse mirroring
2065 0 : if ( static_cast<const SdrGrafObjGeoData*>( pGrafObj->GetGeoData() )->bMirrored )
2066 0 : aRelPoint.X() = aLogRect.Right() + aLogRect.Left() - aRelPoint.X();
2067 :
2068 : // Possible Unshear:
2069 0 : if ( rGeo.nShearAngle )
2070 0 : ShearPoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nTan );
2071 :
2072 0 : if ( rGraphic.GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
2073 : aGraphSize = rCmpWnd.PixelToLogic( rGraphic.GetPrefSize(),
2074 0 : aMap100 );
2075 : else
2076 : aGraphSize = OutputDevice::LogicToLogic( rGraphic.GetPrefSize(),
2077 : rGraphic.GetPrefMapMode(),
2078 0 : aMap100 );
2079 :
2080 0 : bObjSupported = true;
2081 : }
2082 0 : else if ( pObj->ISA( SdrOle2Obj ) ) // OLE object
2083 : {
2084 : // TODO/LEAN: working with visual area needs running state
2085 0 : aGraphSize = static_cast<const SdrOle2Obj*>(pObj)->GetOrigObjSize();
2086 0 : bObjSupported = true;
2087 : }
2088 :
2089 : // If everything has worked out, then perform HitTest
2090 0 : if ( bObjSupported )
2091 : {
2092 : // Calculate relative mouse point
2093 0 : aRelPoint -= aLogRect.TopLeft();
2094 0 : pIMapObj = rImageMap.GetHitIMapObject( aGraphSize, aLogRect.GetSize(), aRelPoint );
2095 0 : }
2096 : }
2097 :
2098 0 : return pIMapObj;
2099 : }
2100 :
2101 97 : ScMacroInfo* ScDrawLayer::GetMacroInfo( SdrObject* pObj, bool bCreate )
2102 : {
2103 97 : if (SdrObjUserData *pData = GetFirstUserDataOfType(pObj, SC_UD_MACRODATA))
2104 12 : return static_cast<ScMacroInfo*>(pData);
2105 :
2106 85 : if ( bCreate )
2107 : {
2108 4 : ScMacroInfo* pData = new ScMacroInfo;
2109 4 : pObj->AppendUserData(pData);
2110 4 : return pData;
2111 : }
2112 81 : return 0;
2113 : }
2114 :
2115 0 : ImageMap* ScDrawLayer::GetImageMapForObject(SdrObject* pObj)
2116 : {
2117 0 : ScIMapInfo* pIMapInfo = GetIMapInfo( pObj );
2118 0 : if ( pIMapInfo )
2119 : {
2120 0 : return const_cast<ImageMap*>( &(pIMapInfo->GetImageMap()) );
2121 : }
2122 0 : return NULL;
2123 : }
2124 :
2125 0 : sal_Int32 ScDrawLayer::GetHyperlinkCount(SdrObject* pObj)
2126 : {
2127 0 : sal_Int32 nHLCount = 0;
2128 0 : ScMacroInfo* pMacroInfo = GetMacroInfo(pObj, false);
2129 0 : if (pMacroInfo)
2130 : // MT IA2: GetHlink*( doesn't exist in DEV300 anymore...
2131 0 : nHLCount = 0; // pMacroInfo->GetHlink().getLength() > 0 ? 1 : 0;
2132 0 : return nHLCount;
2133 : }
2134 :
2135 56 : void ScDrawLayer::SetGlobalDrawPersist(SfxObjectShell* pPersist)
2136 : {
2137 : OSL_ENSURE(!pGlobalDrawPersist,"Multiple SetGlobalDrawPersist");
2138 56 : pGlobalDrawPersist = pPersist;
2139 56 : }
2140 :
2141 15825 : void ScDrawLayer::SetChanged( bool bFlg /* = true */ )
2142 : {
2143 15825 : if ( bFlg && pDoc )
2144 15825 : pDoc->SetChartListenerCollectionNeedsUpdate( true );
2145 15825 : FmFormModel::SetChanged( bFlg );
2146 15825 : }
2147 :
2148 0 : SdrLayerID ScDrawLayer::GetControlExportLayerId( const SdrObject & ) const
2149 : {
2150 : // Layer for export of Form-Controls in Versions before 5.0 - always SC_LAYER_FRONT
2151 0 : return SC_LAYER_FRONT;
2152 : }
2153 :
2154 117 : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ScDrawLayer::createUnoModel()
2155 : {
2156 117 : ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xRet;
2157 117 : if( pDoc && pDoc->GetDocumentShell() )
2158 117 : xRet = pDoc->GetDocumentShell()->GetModel();
2159 :
2160 117 : return xRet;
2161 156 : }
2162 :
2163 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|