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