xref: /trunk/main/sc/source/ui/view/viewfun7.cxx (revision fe9b7f6a5f0c378e0c911bf69d0633ad596c6f08)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sc.hxx"
24 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
25 
26 // INCLUDE ---------------------------------------------------------------
27 
28 #include <svx/svditer.hxx>
29 #include <svx/svdograf.hxx>
30 #include <svx/svdoole2.hxx>
31 #include <svx/svdouno.hxx>
32 #include <svx/svdpage.hxx>
33 #include <svx/svdpagv.hxx>
34 #include <svx/svdundo.hxx>
35 #include <svx/xbtmpit.hxx>
36 #include <svx/xoutbmp.hxx>
37 #include <sfx2/objsh.hxx>
38 #include <sfx2/viewfrm.hxx>
39 #include <toolkit/helper/vclunohelper.hxx>
40 #include <com/sun/star/embed/Aspects.hpp>
41 
42 #include "document.hxx" // für MapMode Initialisierung in PasteDraw
43 #include "viewfunc.hxx"
44 #include "tabvwsh.hxx"
45 #include "drawview.hxx"
46 #include "scmod.hxx"
47 #include "drwlayer.hxx"
48 #include "drwtrans.hxx"
49 #include "globstr.hrc"
50 #include "chartlis.hxx"
51 #include "docuno.hxx"
52 #include "docsh.hxx"
53 #include "convuno.hxx"
54 
55 extern Point aDragStartDiff;
56 
57 // STATIC DATA -----------------------------------------------------------
58 
59 sal_Bool bPasteIsMove = sal_False;
60 
61 using namespace com::sun::star;
62 
63 //==================================================================
64 
lcl_AdjustInsertPos(ScViewData * pData,Point & rPos,Size & rSize)65 void lcl_AdjustInsertPos( ScViewData* pData, Point& rPos, Size& rSize )
66 {
67 //  SdrPage* pPage = pData->GetDocument()->GetDrawLayer()->GetPage( pData->GetTabNo() );
68     SdrPage* pPage = pData->GetScDrawView()->GetModel()->GetPage( static_cast<sal_uInt16>(pData->GetTabNo()) );
69     DBG_ASSERT(pPage,"pPage ???");
70     Size aPgSize( pPage->GetSize() );
71     if (aPgSize.Width() < 0)
72         aPgSize.Width() = -aPgSize.Width();
73     long x = aPgSize.Width() - rPos.X() - rSize.Width();
74     long y = aPgSize.Height() - rPos.Y() - rSize.Height();
75     // ggf. Ajustments (80/200) fuer Pixel-Rundungsfehler
76     if( x < 0 )
77         rPos.X() += x + 80;
78     if( y < 0 )
79         rPos.Y() += y + 200;
80     rPos.X() += rSize.Width() / 2; // Position bei Paste gibt Mittelpunkt an
81     rPos.Y() += rSize.Height() / 2;
82 }
83 
PasteDraw(const Point & rLogicPos,SdrModel * pModel,sal_Bool bGroup,sal_Bool bSameDocClipboard)84 void ScViewFunc::PasteDraw( const Point& rLogicPos, SdrModel* pModel,
85         sal_Bool bGroup, sal_Bool bSameDocClipboard )
86 {
87     MakeDrawLayer();
88     Point aPos( rLogicPos );
89 
90     //  #64184# MapMode am Outliner-RefDevice muss stimmen (wie in FuText::MakeOutliner)
91     //! mit FuText::MakeOutliner zusammenfassen?
92     MapMode aOldMapMode;
93     OutputDevice* pRef = GetViewData()->GetDocument()->GetDrawLayer()->GetRefDevice();
94     if (pRef)
95     {
96         aOldMapMode = pRef->GetMapMode();
97         pRef->SetMapMode( MapMode(MAP_100TH_MM) );
98     }
99 
100     sal_Bool bNegativePage = GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() );
101 
102     SdrView* pDragEditView = NULL;
103     ScModule* pScMod = SC_MOD();
104     const ScDragData& rData = pScMod->GetDragData();
105     ScDrawTransferObj* pDrawTrans = rData.pDrawTransfer;
106     if (pDrawTrans)
107     {
108         pDragEditView = pDrawTrans->GetDragSourceView();
109 
110         aPos -= aDragStartDiff;
111         if ( bNegativePage )
112         {
113             if (aPos.X() > 0) aPos.X() = 0;
114         }
115         else
116         {
117             if (aPos.X() < 0) aPos.X() = 0;
118         }
119         if (aPos.Y() < 0) aPos.Y() = 0;
120     }
121 
122     ScDrawView* pScDrawView = GetScDrawView();
123     if (bGroup)
124         pScDrawView->BegUndo( ScGlobal::GetRscString( STR_UNDO_PASTE ) );
125 
126     sal_Bool bSameDoc = ( pDragEditView && pDragEditView->GetModel() == pScDrawView->GetModel() );
127     if (bSameDoc)
128     {
129             // lokal kopieren - incl. Charts
130 
131         Point aSourceStart = pDragEditView->GetAllMarkedRect().TopLeft();
132         long nDiffX = aPos.X() - aSourceStart.X();
133         long nDiffY = aPos.Y() - aSourceStart.Y();
134 
135             // innerhalb einer Page verschieben?
136 
137         if ( bPasteIsMove &&
138                 pScDrawView->GetSdrPageView()->GetPage() ==
139                 pDragEditView->GetSdrPageView()->GetPage() )
140         {
141             if ( nDiffX != 0 || nDiffY != 0 )
142                 pDragEditView->MoveAllMarked(Size(nDiffX,nDiffY), sal_False);
143         }
144         else
145         {
146             SdrModel* pDrawModel = pDragEditView->GetModel();
147             SCTAB nTab = GetViewData()->GetTabNo();
148             SdrPage* pDestPage = pDrawModel->GetPage( static_cast< sal_uInt16 >( nTab ) );
149             DBG_ASSERT(pDestPage,"nanu, Page?");
150 
151             ::std::vector< ::rtl::OUString > aExcludedChartNames;
152             if ( pDestPage )
153             {
154                 ScChartHelper::GetChartNames( aExcludedChartNames, pDestPage );
155             }
156 
157             SdrMarkList aMark = pDragEditView->GetMarkedObjectList();
158             aMark.ForceSort();
159             sal_uLong nMarkAnz=aMark.GetMarkCount();
160             for (sal_uLong nm=0; nm<nMarkAnz; nm++) {
161                 const SdrMark* pM=aMark.GetMark(nm);
162                 const SdrObject* pObj=pM->GetMarkedSdrObj();
163 
164                 // #116235#
165                 SdrObject* pNewObj=pObj->Clone();
166                 //SdrObject* pNewObj=pObj->Clone(pDestPage,pDrawModel);
167 
168                 if (pNewObj!=NULL)
169                 {
170                     pNewObj->SetModel(pDrawModel);
171                     pNewObj->SetPage(pDestPage);
172 
173                     //  #68787# copy graphics within the same model - always needs new name
174                     if ( pNewObj->ISA(SdrGrafObj) && !bPasteIsMove )
175                         pNewObj->SetName(((ScDrawLayer*)pDrawModel)->GetNewGraphicName());
176 
177                     if (nDiffX!=0 || nDiffY!=0)
178                         pNewObj->NbcMove(Size(nDiffX,nDiffY));
179                     pDestPage->InsertObject( pNewObj );
180                     pScDrawView->AddUndo(new SdrUndoInsertObj( *pNewObj ));
181 
182                     //  Chart braucht nicht mehr getrennt behandelt zu werden,
183                     //  weil es seine Daten jetzt selber hat
184                 }
185             }
186 
187             if (bPasteIsMove)
188                 pDragEditView->DeleteMarked();
189 
190             ScDocument* pDocument = GetViewData()->GetDocument();
191             ScDocShell* pDocShell = GetViewData()->GetDocShell();
192             ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL );
193             if ( pDocument && pDestPage && pModelObj && pDrawTrans )
194             {
195                 const ScRangeListVector& rProtectedChartRangesVector( pDrawTrans->GetProtectedChartRangesVector() );
196                 ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pDestPage, pModelObj, nTab,
197                     rProtectedChartRangesVector, aExcludedChartNames, bSameDoc );
198             }
199         }
200     }
201     else
202     {
203         bPasteIsMove = sal_False; // kein internes Verschieben passiert
204 
205         SdrView aView(pModel); // #i71529# never create a base class of SdrView directly!
206         SdrPageView* pPv = aView.ShowSdrPage(aView.GetModel()->GetPage(0));
207         aView.MarkAllObj(pPv);
208         Size aSize = aView.GetAllMarkedRect().GetSize();
209         lcl_AdjustInsertPos( GetViewData(), aPos, aSize );
210 
211         //  #41333# Markierung nicht ändern, wenn Ole-Objekt aktiv
212         //  (bei Drop aus OLE-Objekt würde sonst mitten im ExecuteDrag deaktiviert!)
213 
214         sal_uLong nOptions = 0;
215         SfxInPlaceClient* pClient = GetViewData()->GetViewShell()->GetIPClient();
216         if ( pClient && pClient->IsObjectInPlaceActive() )
217             nOptions |= SDRINSERT_DONTMARK;
218 
219         ::std::vector< ::rtl::OUString > aExcludedChartNames;
220         SCTAB nTab = GetViewData()->GetTabNo();
221         SdrPage* pPage = pScDrawView->GetModel()->GetPage( static_cast< sal_uInt16 >( nTab ) );
222         DBG_ASSERT( pPage, "Page?" );
223         if ( pPage )
224         {
225             ScChartHelper::GetChartNames( aExcludedChartNames, pPage );
226         }
227 
228         // #89247# Set flag for ScDocument::UpdateChartListeners() which is
229         // called during paste.
230         if ( !bSameDocClipboard )
231             GetViewData()->GetDocument()->SetPastingDrawFromOtherDoc( sal_True );
232 
233         pScDrawView->Paste( *pModel, aPos, NULL, nOptions );
234 
235         if ( !bSameDocClipboard )
236             GetViewData()->GetDocument()->SetPastingDrawFromOtherDoc( sal_False );
237 
238         // #68991# Paste puts all objects on the active (front) layer
239         // controls must be on SC_LAYER_CONTROLS
240         if (pPage)
241         {
242             SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS );
243             SdrObject* pObject = aIter.Next();
244             while (pObject)
245             {
246                 if ( pObject->ISA(SdrUnoObj) && pObject->GetLayer() != SC_LAYER_CONTROLS )
247                     pObject->NbcSetLayer(SC_LAYER_CONTROLS);
248                 pObject = aIter.Next();
249             }
250         }
251 
252         // #75299# all graphics objects must have names
253         GetViewData()->GetDocument()->EnsureGraphicNames();
254 
255         ScDocument* pDocument = GetViewData()->GetDocument();
256         ScDocShell* pDocShell = GetViewData()->GetDocShell();
257         ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : NULL );
258         ScDrawTransferObj* pTransferObj = ScDrawTransferObj::GetOwnClipboard( NULL );
259         if ( pDocument && pPage && pModelObj && ( pTransferObj || pDrawTrans ) )
260         {
261             const ScRangeListVector& rProtectedChartRangesVector(
262                 pTransferObj ? pTransferObj->GetProtectedChartRangesVector() : pDrawTrans->GetProtectedChartRangesVector() );
263             ScChartHelper::CreateProtectedChartListenersAndNotify( pDocument, pPage, pModelObj, nTab,
264                 rProtectedChartRangesVector, aExcludedChartNames, bSameDocClipboard );
265         }
266     }
267 
268     if (bGroup)
269     {
270         pScDrawView->GroupMarked();
271         pScDrawView->EndUndo();
272     }
273 
274     if (pRef)
275         pRef->SetMapMode( aOldMapMode );
276 
277     // GetViewData()->GetViewShell()->SetDrawShell( sal_True );
278     // #99759# It is not sufficient to just set the DrawShell if we pasted, for
279     // example, a chart. SetDrawShellOrSub() would only work for D&D in the
280     // same document but not if inserting from the clipboard, therefore
281     // MarkListHasChanged() is what we need.
282     pScDrawView->MarkListHasChanged();
283 
284 }
285 
PasteObject(const Point & rPos,const uno::Reference<embed::XEmbeddedObject> & xObj,const Size * pDescSize,const Graphic * pReplGraph,const::rtl::OUString & aMediaType,sal_Int64 nAspect)286 sal_Bool ScViewFunc::PasteObject( const Point& rPos, const uno::Reference < embed::XEmbeddedObject >& xObj,
287                                 const Size* pDescSize, const Graphic* pReplGraph, const ::rtl::OUString& aMediaType, sal_Int64 nAspect )
288 {
289     MakeDrawLayer();
290     if ( xObj.is() )
291     {
292         ::rtl::OUString aName;
293         //TODO/MBA: is that OK?
294         comphelper::EmbeddedObjectContainer& aCnt = GetViewData()->GetViewShell()->GetObjectShell()->GetEmbeddedObjectContainer();
295         if ( !aCnt.HasEmbeddedObject( xObj ) )
296             aCnt.InsertEmbeddedObject( xObj, aName );
297         else
298             aName = aCnt.GetEmbeddedObjectName( xObj );
299 
300         svt::EmbeddedObjectRef aObjRef( xObj, nAspect );
301         if ( pReplGraph )
302             aObjRef.SetGraphic( *pReplGraph, aMediaType );
303 
304         Size aSize;
305         if ( nAspect == embed::Aspects::MSOLE_ICON )
306         {
307             MapMode aMapMode( MAP_100TH_MM );
308             aSize = aObjRef.GetSize( &aMapMode );
309         }
310         else
311         {
312             // working with visual area can switch object to running state
313             MapUnit aMapObj = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
314             MapUnit aMap100 = MAP_100TH_MM;
315 
316             if ( pDescSize && pDescSize->Width() && pDescSize->Height() )
317             {
318                 // use size from object descriptor if given
319                 aSize = OutputDevice::LogicToLogic( *pDescSize, aMap100, aMapObj );
320                 awt::Size aSz;
321                 aSz.Width = aSize.Width();
322                 aSz.Height = aSize.Height();
323                 xObj->setVisualAreaSize( nAspect, aSz );
324             }
325 
326             awt::Size aSz;
327             try
328             {
329                 aSz = xObj->getVisualAreaSize( nAspect );
330             }
331             catch ( embed::NoVisualAreaSizeException& )
332             {
333                 // the default size will be set later
334             }
335 
336             aSize = Size( aSz.Width, aSz.Height );
337             aSize = OutputDevice::LogicToLogic( aSize, aMapObj, aMap100 );  // fuer SdrOle2Obj
338 
339             if( aSize.Height() == 0 || aSize.Width() == 0 )
340             {
341                 DBG_ERROR("SvObjectDescriptor::GetSize == 0");
342                 aSize.Width() = 5000;
343                 aSize.Height() = 5000;
344                 aSize = OutputDevice::LogicToLogic( aSize, aMap100, aMapObj );
345                 aSz.Width = aSize.Width();
346                 aSz.Height = aSize.Height();
347                 xObj->setVisualAreaSize( nAspect, aSz );
348             }
349         }
350 
351         // don't call AdjustInsertPos
352         Point aInsPos = rPos;
353         if ( GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ) )
354             aInsPos.X() -= aSize.Width();
355         Rectangle aRect( aInsPos, aSize );
356 
357         ScDrawView* pDrView = GetScDrawView();
358         SdrOle2Obj* pSdrObj = new SdrOle2Obj( aObjRef, aName, aRect );
359 
360         SdrPageView* pPV = pDrView->GetSdrPageView();
361         pDrView->InsertObjectSafe( pSdrObj, *pPV );             // nicht markieren wenn Ole
362         GetViewData()->GetViewShell()->SetDrawShell( sal_True );
363         return sal_True;
364     }
365     else
366         return sal_False;
367 }
368 
PasteBitmapEx(const Point & rPos,const BitmapEx & rBmpEx)369 sal_Bool ScViewFunc::PasteBitmapEx( const Point& rPos, const BitmapEx& rBmpEx )
370 {
371     String aEmpty;
372     Graphic aGraphic(rBmpEx);
373     return PasteGraphic( rPos, aGraphic, aEmpty, aEmpty );
374 }
375 
PasteMetaFile(const Point & rPos,const GDIMetaFile & rMtf)376 sal_Bool ScViewFunc::PasteMetaFile( const Point& rPos, const GDIMetaFile& rMtf )
377 {
378     String aEmpty;
379     Graphic aGraphic(rMtf);
380     return PasteGraphic( rPos, aGraphic, aEmpty, aEmpty );
381 }
382 
PasteGraphic(const Point & rPos,const Graphic & rGraphic,const String & rFile,const String & rFilter)383 sal_Bool ScViewFunc::PasteGraphic( const Point& rPos, const Graphic& rGraphic,
384                                 const String& rFile, const String& rFilter )
385 {
386     MakeDrawLayer();
387     ScDrawView* pScDrawView = GetScDrawView();
388 
389     // #123922# check if the drop was over an existing object; if yes, evtl. replace
390     // the graphic for a SdrGraphObj (including link state updates) or adapt the fill
391     // style for other objects
392     if(pScDrawView)
393     {
394         SdrObject* pPickObj = 0;
395         SdrPageView* pPageView = pScDrawView->GetSdrPageView();
396 
397         if(pPageView)
398         {
399             pScDrawView->PickObj(rPos, pScDrawView->getHitTolLog(), pPickObj, pPageView);
400         }
401 
402         if(pPickObj)
403         {
404             const String aBeginUndo(ScGlobal::GetRscString(STR_UNDO_DRAGDROP));
405             SdrObject* pResult = pScDrawView->ApplyGraphicToObject(
406                 *pPickObj,
407                 rGraphic,
408                 aBeginUndo,
409                 rFile,
410                 rFilter);
411 
412             if(pResult)
413             {
414                 // we are done; mark the modified/new object
415                 pScDrawView->MarkObj(pResult, pScDrawView->GetSdrPageView());
416                 return sal_True;
417             }
418         }
419     }
420 
421     Point aPos( rPos );
422     Window* pWin = GetActiveWin();
423     MapMode aSourceMap = rGraphic.GetPrefMapMode();
424     MapMode aDestMap( MAP_100TH_MM );
425 
426     if (aSourceMap.GetMapUnit() == MAP_PIXEL)
427     {
428             //  Pixel-Korrektur berücksichtigen, damit Bitmap auf dem Bildschirm stimmt
429 
430         Fraction aScaleX, aScaleY;
431         pScDrawView->CalcNormScale( aScaleX, aScaleY );
432         aDestMap.SetScaleX(aScaleX);
433         aDestMap.SetScaleY(aScaleY);
434     }
435 
436     Size aSize = pWin->LogicToLogic( rGraphic.GetPrefSize(), &aSourceMap, &aDestMap );
437 //  lcl_AdjustInsertPos( GetViewData(), aPos, aSize );
438     if ( GetViewData()->GetDocument()->IsNegativePage( GetViewData()->GetTabNo() ) )
439         aPos.X() -= aSize.Width();
440 
441     GetViewData()->GetViewShell()->SetDrawShell( sal_True );
442     Rectangle aRect(aPos, aSize);
443     SdrGrafObj* pGrafObj = new SdrGrafObj(rGraphic, aRect);
444 
445     // #118522# calling SetGraphicLink here doesn't work
446 
447     // #49961# Pfad wird nicht mehr als Name der Grafik gesetzt
448 
449     ScDrawLayer* pLayer = (ScDrawLayer*) pScDrawView->GetModel();
450     String aName = pLayer->GetNewGraphicName();                 // "Grafik x"
451     pGrafObj->SetName(aName);
452 
453     // nicht markieren wenn Ole
454     pScDrawView->InsertObjectSafe(pGrafObj, *pScDrawView->GetSdrPageView());
455 
456     // #118522# SetGraphicLink has to be used after inserting the object,
457     // otherwise an empty graphic is swapped in and the contact stuff crashes.
458     // See #i37444#.
459     if (rFile.Len())
460         pGrafObj->SetGraphicLink( rFile, rFilter );
461 
462     return sal_True;
463 }
464 
465 /* vim: set noet sw=4 ts=4: */
466