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