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