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