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