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