xref: /AOO41X/main/svx/source/svdraw/svdxcgv.cxx (revision 707fc0d4d52eb4f69d89a98ffec6918ca5de6326)
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_svx.hxx"
26 
27 #include <vector>
28 #include <editeng/editeng.hxx>
29 #include "svx/xexch.hxx"
30 #include <svx/xflclit.hxx>
31 #include <svx/svdxcgv.hxx>
32 #include <svx/svdoutl.hxx>
33 #include "svx/svditext.hxx"
34 #include <svx/svdetc.hxx>
35 #include <svx/svdundo.hxx>
36 #include <svx/svdograf.hxx>
37 #include <svx/svdoole2.hxx> // fuer kein OLE im SdrClipboardFormat
38 #include <svx/svdorect.hxx>
39 #include <svx/svdoedge.hxx> // fuer Konnektoren uebers Clipboard
40 #include <svx/svdopage.hxx> // fuer Konnektoren uebers Clipboard
41 #include <svx/svdpage.hxx>
42 #include <svx/svdpagv.hxx>
43 #include <svx/svdtrans.hxx> // Fuer GetMapFactor zum umskalieren bei PasteModel
44 #include "svx/svdstr.hrc"   // Namen aus der Resource
45 #include "svx/svdglob.hxx"  // StringCache
46 #include "svx/xoutbmp.hxx"
47 #include <vcl/metaact.hxx>
48 #include <svl/poolitem.hxx>
49 #include <svl/itempool.hxx>
50 #include <tools/bigint.hxx>
51 #include <sot/formats.hxx>
52 
53 // #i13033#
54 #include <clonelist.hxx>
55 #include <vcl/virdev.hxx>
56 
57 // b4967543
58 #include <svl/style.hxx>
59 
60 // #i72535#
61 #include "fmobj.hxx"
62 
63 ////////////////////////////////////////////////////////////////////////////////////////////////////
64 
65 SdrExchangeView::SdrExchangeView(SdrModel* pModel1, OutputDevice* pOut):
66     SdrObjEditView(pModel1,pOut)
67 {
68 }
69 
70 ////////////////////////////////////////////////////////////////////////////////////////////////////
71 
72 Point SdrExchangeView::GetViewCenter(const OutputDevice* pOut) const
73 {
74     Point aCenter;
75     if (pOut==NULL)
76     {
77         pOut = GetFirstOutputDevice();
78     }
79     if (pOut!=NULL) {
80         Point aOfs=pOut->GetMapMode().GetOrigin();
81         Size aOutSiz=pOut->GetOutputSize();
82         aOutSiz.Width()/=2;
83         aOutSiz.Height()/=2;
84         aCenter.X()=aOutSiz.Width() -aOfs.X();
85         aCenter.Y()=aOutSiz.Height()-aOfs.Y();
86     }
87     return aCenter;
88 }
89 
90 Point SdrExchangeView::GetPastePos(SdrObjList* pLst, OutputDevice* pOut)
91 {
92     Point aP(GetViewCenter(pOut));
93     SdrPage* pPg=NULL;
94     if (pLst!=NULL) pPg=pLst->GetPage();
95     if (pPg!=NULL) {
96         Size aSiz(pPg->GetSize());
97         aP.X()=aSiz.Width()/2;
98         aP.Y()=aSiz.Height()/2;
99     }
100     return aP;
101 }
102 
103 sal_Bool SdrExchangeView::ImpLimitToWorkArea(Point& rPt) const
104 {
105     sal_Bool bRet(sal_False);
106 
107     if(!aMaxWorkArea.IsEmpty())
108     {
109         if(rPt.X()<aMaxWorkArea.Left())
110         {
111             rPt.X() = aMaxWorkArea.Left();
112             bRet = sal_True;
113         }
114 
115         if(rPt.X()>aMaxWorkArea.Right())
116         {
117             rPt.X() = aMaxWorkArea.Right();
118             bRet = sal_True;
119         }
120 
121         if(rPt.Y()<aMaxWorkArea.Top())
122         {
123             rPt.Y() = aMaxWorkArea.Top();
124             bRet = sal_True;
125         }
126 
127         if(rPt.Y()>aMaxWorkArea.Bottom())
128         {
129             rPt.Y() = aMaxWorkArea.Bottom();
130             bRet = sal_True;
131         }
132     }
133     return bRet;
134 }
135 
136 void SdrExchangeView::ImpGetPasteObjList(Point& /*rPos*/, SdrObjList*& rpLst)
137 {
138     if (rpLst==NULL)
139     {
140         SdrPageView* pPV = GetSdrPageView();
141 
142         if (pPV!=NULL) {
143             rpLst=pPV->GetObjList();
144         }
145     }
146 }
147 
148 sal_Bool SdrExchangeView::ImpGetPasteLayer(const SdrObjList* pObjList, SdrLayerID& rLayer) const
149 {
150     sal_Bool bRet=sal_False;
151     rLayer=0;
152     if (pObjList!=NULL) {
153         const SdrPage* pPg=pObjList->GetPage();
154         if (pPg!=NULL) {
155             rLayer=pPg->GetLayerAdmin().GetLayerID(aAktLayer,sal_True);
156             if (rLayer==SDRLAYER_NOTFOUND) rLayer=0;
157             SdrPageView* pPV = GetSdrPageView();
158             if (pPV!=NULL) {
159                 bRet=!pPV->GetLockedLayers().IsSet(rLayer) && pPV->GetVisibleLayers().IsSet(rLayer);
160             }
161         }
162     }
163     return bRet;
164 }
165 
166 ////////////////////////////////////////////////////////////////////////////////////////////////////
167 
168 sal_Bool SdrExchangeView::Paste(const GDIMetaFile& rMtf, const Point& rPos, SdrObjList* pLst, sal_uInt32 nOptions)
169 {
170     Point aPos(rPos);
171     ImpGetPasteObjList(aPos,pLst);
172     ImpLimitToWorkArea( aPos );
173     if (pLst==NULL) return sal_False;
174     SdrLayerID nLayer;
175     if (!ImpGetPasteLayer(pLst,nLayer)) return sal_False;
176     sal_Bool bUnmark=(nOptions&(SDRINSERT_DONTMARK|SDRINSERT_ADDMARK))==0 && !IsTextEdit();
177     if (bUnmark) UnmarkAllObj();
178     SdrGrafObj* pObj=new SdrGrafObj(Graphic(rMtf));
179     pObj->SetLayer(nLayer);
180     ImpPasteObject(pObj,*pLst,aPos,rMtf.GetPrefSize(),rMtf.GetPrefMapMode(),nOptions);
181     return sal_True;
182 }
183 
184 sal_Bool SdrExchangeView::Paste(const Bitmap& rBmp, const Point& rPos, SdrObjList* pLst, sal_uInt32 nOptions)
185 {
186     Point aPos(rPos);
187     ImpGetPasteObjList(aPos,pLst);
188     ImpLimitToWorkArea( aPos );
189     if (pLst==NULL) return sal_False;
190     SdrLayerID nLayer;
191     if (!ImpGetPasteLayer(pLst,nLayer)) return sal_False;
192     sal_Bool bUnmark=(nOptions&(SDRINSERT_DONTMARK|SDRINSERT_ADDMARK))==0 && !IsTextEdit();
193     if (bUnmark) UnmarkAllObj();
194     SdrGrafObj* pObj=new SdrGrafObj(Graphic(rBmp));
195     pObj->SetLayer(nLayer);
196     ImpPasteObject(pObj,*pLst,aPos,rBmp.GetSizePixel(),MapMode(MAP_PIXEL),nOptions);
197     return sal_True;
198 }
199 
200 sal_Bool SdrExchangeView::Paste(const XubString& rStr, const Point& rPos, SdrObjList* pLst, sal_uInt32 nOptions)
201 {
202     if(!rStr.Len())
203         return sal_False;
204 
205     Point aPos(rPos);
206     ImpGetPasteObjList(aPos,pLst);
207     ImpLimitToWorkArea( aPos );
208     if (pLst==NULL) return sal_False;
209     SdrLayerID nLayer;
210     if (!ImpGetPasteLayer(pLst,nLayer)) return sal_False;
211     sal_Bool bUnmark=(nOptions&(SDRINSERT_DONTMARK|SDRINSERT_ADDMARK))==0 && !IsTextEdit();
212     if (bUnmark) UnmarkAllObj();
213     Rectangle aTextRect(0,0,500,500);
214     SdrPage* pPage=pLst->GetPage();
215     if (pPage!=NULL) {
216         aTextRect.SetSize(pPage->GetSize());
217     }
218     SdrRectObj* pObj=new SdrRectObj(OBJ_TEXT,aTextRect);
219     pObj->SetModel(pMod);
220     pObj->SetLayer(nLayer);
221     pObj->NbcSetText(rStr); // #32424# SetText vor SetAttr, weil SetAttr sonst unwirksam!
222     if (pDefaultStyleSheet!=NULL) pObj->NbcSetStyleSheet(pDefaultStyleSheet, sal_False);
223 
224     pObj->SetMergedItemSet(aDefaultAttr);
225 
226     SfxItemSet aTempAttr(pMod->GetItemPool());  // Keine Fuellung oder Linie
227     aTempAttr.Put(XLineStyleItem(XLINE_NONE));
228     aTempAttr.Put(XFillStyleItem(XFILL_NONE));
229 
230     pObj->SetMergedItemSet(aTempAttr);
231 
232     pObj->FitFrameToTextSize();
233     Size aSiz(pObj->GetLogicRect().GetSize());
234     MapUnit eMap=pMod->GetScaleUnit();
235     Fraction aMap=pMod->GetScaleFraction();
236     ImpPasteObject(pObj,*pLst,aPos,aSiz,MapMode(eMap,Point(0,0),aMap,aMap),nOptions);
237     return sal_True;
238 }
239 
240 sal_Bool SdrExchangeView::Paste(SvStream& rInput, const String& rBaseURL, sal_uInt16 eFormat, const Point& rPos, SdrObjList* pLst, sal_uInt32 nOptions)
241 {
242     Point aPos(rPos);
243     ImpGetPasteObjList(aPos,pLst);
244     ImpLimitToWorkArea( aPos );
245     if (pLst==NULL) return sal_False;
246     SdrLayerID nLayer;
247     if (!ImpGetPasteLayer(pLst,nLayer)) return sal_False;
248     sal_Bool bUnmark=(nOptions&(SDRINSERT_DONTMARK|SDRINSERT_ADDMARK))==0 && !IsTextEdit();
249     if (bUnmark) UnmarkAllObj();
250     Rectangle aTextRect(0,0,500,500);
251     SdrPage* pPage=pLst->GetPage();
252     if (pPage!=NULL) {
253         aTextRect.SetSize(pPage->GetSize());
254     }
255     SdrRectObj* pObj=new SdrRectObj(OBJ_TEXT,aTextRect);
256     pObj->SetModel(pMod);
257     pObj->SetLayer(nLayer);
258     if (pDefaultStyleSheet!=NULL) pObj->NbcSetStyleSheet(pDefaultStyleSheet, sal_False);
259 
260     pObj->SetMergedItemSet(aDefaultAttr);
261 
262     SfxItemSet aTempAttr(pMod->GetItemPool());  // Keine Fuellung oder Linie
263     aTempAttr.Put(XLineStyleItem(XLINE_NONE));
264     aTempAttr.Put(XFillStyleItem(XFILL_NONE));
265 
266     pObj->SetMergedItemSet(aTempAttr);
267 
268     pObj->NbcSetText(rInput,rBaseURL,eFormat);
269     pObj->FitFrameToTextSize();
270     Size aSiz(pObj->GetLogicRect().GetSize());
271     MapUnit eMap=pMod->GetScaleUnit();
272     Fraction aMap=pMod->GetScaleFraction();
273     ImpPasteObject(pObj,*pLst,aPos,aSiz,MapMode(eMap,Point(0,0),aMap,aMap),nOptions);
274 
275     // b4967543
276     if(pObj && pObj->GetModel() && pObj->GetOutlinerParaObject())
277     {
278         SdrOutliner& rOutliner = pObj->GetModel()->GetHitTestOutliner();
279         rOutliner.SetText(*pObj->GetOutlinerParaObject());
280 
281         if(1L == rOutliner.GetParagraphCount())
282         {
283             SfxStyleSheet* pCandidate = rOutliner.GetStyleSheet(0L);
284 
285             if(pCandidate)
286             {
287                 if(pObj->GetModel()->GetStyleSheetPool() == &pCandidate->GetPool())
288                 {
289                     pObj->NbcSetStyleSheet(pCandidate, sal_True);
290                 }
291             }
292         }
293     }
294 
295     return sal_True;
296 }
297 
298 sal_Bool SdrExchangeView::Paste(const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, sal_uInt32 nOptions)
299 {
300     const SdrModel* pSrcMod=&rMod;
301     if (pSrcMod==pMod)
302         return sal_False; // na so geht's ja nun nicht
303 
304     const bool bUndo = IsUndoEnabled();
305 
306     if( bUndo )
307         BegUndo(ImpGetResStr(STR_ExchangePaste));
308 
309     if( mxSelectionController.is() && mxSelectionController->PasteObjModel( rMod ) )
310     {
311         if( bUndo )
312             EndUndo();
313         return sal_True;
314     }
315 
316     Point aPos(rPos);
317     ImpGetPasteObjList(aPos,pLst);
318     SdrPageView* pMarkPV=NULL;
319     SdrPageView* pPV = GetSdrPageView();
320 
321     if(pPV)
322     {
323         if ( pPV->GetObjList() == pLst )
324             pMarkPV=pPV;
325     }
326 
327     ImpLimitToWorkArea( aPos );
328     if (pLst==NULL)
329         return sal_False;
330 
331     sal_Bool bUnmark=(nOptions&(SDRINSERT_DONTMARK|SDRINSERT_ADDMARK))==0 && !IsTextEdit();
332     if (bUnmark)
333         UnmarkAllObj();
334 
335     // evtl. umskalieren bei unterschiedlicher MapUnit am Model
336     // Dafuer erstmal die Faktoren berechnen
337     MapUnit eSrcUnit=pSrcMod->GetScaleUnit();
338     MapUnit eDstUnit=pMod->GetScaleUnit();
339     sal_Bool bResize=eSrcUnit!=eDstUnit;
340     Fraction xResize,yResize;
341     Point aPt0;
342     if (bResize)
343     {
344         FrPair aResize(GetMapFactor(eSrcUnit,eDstUnit));
345         xResize=aResize.X();
346         yResize=aResize.Y();
347     }
348     SdrObjList*  pDstLst=pLst;
349     sal_uInt16 nPg,nPgAnz=pSrcMod->GetPageCount();
350     for (nPg=0; nPg<nPgAnz; nPg++)
351     {
352         const SdrPage* pSrcPg=pSrcMod->GetPage(nPg);
353 
354         // #104148# Use SnapRect, not BoundRect here
355         Rectangle aR=pSrcPg->GetAllObjSnapRect();
356 
357         if (bResize)
358             ResizeRect(aR,aPt0,xResize,yResize);
359         Point aDist(aPos-aR.Center());
360         Size  aSiz(aDist.X(),aDist.Y());
361         //sal_uIntPtr nDstObjAnz0=pDstLst->GetObjCount();
362         sal_uIntPtr nCloneErrCnt=0;
363         sal_uIntPtr nOb,nObAnz=pSrcPg->GetObjCount();
364         sal_Bool bMark=pMarkPV!=NULL && !IsTextEdit() && (nOptions&SDRINSERT_DONTMARK)==0;
365 
366         // #i13033#
367         // New mechanism to re-create the connections of cloned connectors
368         CloneList aCloneList;
369 
370         for (nOb=0; nOb<nObAnz; nOb++)
371         {
372             const SdrObject* pSrcOb=pSrcPg->GetObj(nOb);
373 
374             // #116235#
375             SdrObject* pNeuObj = pSrcOb->Clone();
376 
377             if (pNeuObj!=NULL)
378             {
379                 if(bResize)
380                 {
381                     pNeuObj->GetModel()->SetPasteResize(sal_True); // #51139#
382                     pNeuObj->NbcResize(aPt0,xResize,yResize);
383                     pNeuObj->GetModel()->SetPasteResize(sal_False); // #51139#
384                 }
385 
386                 // #i39861#
387                 pNeuObj->SetModel(pDstLst->GetModel());
388                 pNeuObj->SetPage(pDstLst->GetPage());
389 
390                 pNeuObj->NbcMove(aSiz);
391 
392                 const SdrPage* pPg = pDstLst->GetPage();
393 
394                 if(pPg)
395                 {
396                     // #i72535#
397                     const SdrLayerAdmin& rAd = pPg->GetLayerAdmin();
398                     SdrLayerID nLayer(0);
399 
400                     if(pNeuObj->ISA(FmFormObj))
401                     {
402                         // for FormControls, force to form layer
403                         nLayer = rAd.GetLayerID(rAd.GetControlLayerName(), true);
404                     }
405                     else
406                     {
407                         nLayer = rAd.GetLayerID(aAktLayer, sal_True);
408                     }
409 
410                     if(SDRLAYER_NOTFOUND == nLayer)
411                     {
412                         nLayer = 0;
413                     }
414 
415                     pNeuObj->SetLayer(nLayer);
416                 }
417 
418                 SdrInsertReason aReason(SDRREASON_VIEWCALL);
419                 pDstLst->InsertObject(pNeuObj,CONTAINER_APPEND,&aReason);
420 
421                 if( bUndo )
422                     AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNeuObj));
423 
424                 if (bMark) {
425                     // Markhandles noch nicht sofort setzen!
426                     // Das erledigt das ModelHasChanged der MarkView.
427                     MarkObj(pNeuObj,pMarkPV,sal_False,sal_True);
428                 }
429 
430                 // #i13033#
431                 aCloneList.AddPair(pSrcOb, pNeuObj);
432             }
433             else
434             {
435                 nCloneErrCnt++;
436             }
437         }
438 
439         // #i13033#
440         // New mechanism to re-create the connections of cloned connectors
441         aCloneList.CopyConnections();
442 
443         if(0L != nCloneErrCnt)
444         {
445 #ifdef DBG_UTIL
446             ByteString aStr("SdrExchangeView::Paste(): Fehler beim Clonen ");
447 
448             if(nCloneErrCnt == 1)
449             {
450                 aStr += "eines Zeichenobjekts.";
451             }
452             else
453             {
454                 aStr += "von ";
455                 aStr += ByteString::CreateFromInt32( nCloneErrCnt );
456                 aStr += " Zeichenobjekten.";
457             }
458 
459             aStr += " Objektverbindungen werden nicht mitkopiert.";
460 
461             DBG_ERROR(aStr.GetBuffer());
462 #endif
463         }
464     }
465 
466     if( bUndo )
467         EndUndo();
468 
469     return sal_True;
470 }
471 
472 sal_Bool SdrExchangeView::IsExchangeFormatSupported(sal_uIntPtr nFormat) const
473 {
474     return( FORMAT_PRIVATE == nFormat ||
475             FORMAT_GDIMETAFILE == nFormat ||
476             FORMAT_BITMAP == nFormat ||
477             FORMAT_RTF == nFormat ||
478             FORMAT_STRING == nFormat ||
479             SOT_FORMATSTR_ID_DRAWING == nFormat ||
480             SOT_FORMATSTR_ID_EDITENGINE == nFormat );
481 }
482 
483 void SdrExchangeView::ImpPasteObject(SdrObject* pObj, SdrObjList& rLst, const Point& rCenter, const Size& rSiz, const MapMode& rMap, sal_uInt32 nOptions)
484 {
485     BigInt nSizX(rSiz.Width());
486     BigInt nSizY(rSiz.Height());
487     MapUnit eSrcMU=rMap.GetMapUnit();
488     MapUnit eDstMU=pMod->GetScaleUnit();
489     FrPair aMapFact(GetMapFactor(eSrcMU,eDstMU));
490     Fraction aDstFr(pMod->GetScaleFraction());
491     nSizX*=aMapFact.X().GetNumerator();
492     nSizX*=rMap.GetScaleX().GetNumerator();
493     nSizX*=aDstFr.GetDenominator();
494     nSizX/=aMapFact.X().GetDenominator();
495     nSizX/=rMap.GetScaleX().GetDenominator();
496     nSizX/=aDstFr.GetNumerator();
497     nSizY*=aMapFact.Y().GetNumerator();
498     nSizY*=rMap.GetScaleY().GetNumerator();
499     nSizX*=aDstFr.GetDenominator();
500     nSizY/=aMapFact.Y().GetDenominator();
501     nSizY/=rMap.GetScaleY().GetDenominator();
502     nSizY/=aDstFr.GetNumerator();
503     long xs=nSizX;
504     long ys=nSizY;
505     Point aPos(rCenter.X()-xs/2,rCenter.Y()-ys/2);
506     Rectangle aR(aPos.X(),aPos.Y(),aPos.X()+xs,aPos.Y()+ys);
507     pObj->SetLogicRect(aR);
508     SdrInsertReason aReason(SDRREASON_VIEWCALL);
509     rLst.InsertObject(pObj,CONTAINER_APPEND,&aReason);
510 
511     if( IsUndoEnabled() )
512         AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pObj));
513 
514     SdrPageView* pMarkPV=NULL;
515     SdrPageView* pPV = GetSdrPageView();
516 
517     if(pPV)
518     {
519         if (pPV->GetObjList()==&rLst)
520             pMarkPV=pPV;
521     }
522 
523     sal_Bool bMark=pMarkPV!=NULL && !IsTextEdit() && (nOptions&SDRINSERT_DONTMARK)==0;
524     if (bMark)
525     { // Obj in der ersten gefundenen PageView markieren
526         MarkObj(pObj,pMarkPV);
527     }
528 }
529 
530 ////////////////////////////////////////////////////////////////////////////////////////////////////
531 
532 BitmapEx SdrExchangeView::GetMarkedObjBitmap( bool bNoVDevIfOneBmpMarked ) const
533 {
534     BitmapEx aBmp;
535 
536     if( AreObjectsMarked() )
537     {
538         if(1 == GetMarkedObjectCount())
539         {
540             if(bNoVDevIfOneBmpMarked)
541             {
542                 SdrObject*  pGrafObjTmp = GetMarkedObjectByIndex( 0 );
543                 SdrGrafObj* pGrafObj = ( GetMarkedObjectCount() == 1 ) ? PTR_CAST( SdrGrafObj, pGrafObjTmp ) : NULL;
544 
545                 if( pGrafObj && ( pGrafObj->GetGraphicType() == GRAPHIC_BITMAP ) )
546                 {
547                     aBmp = pGrafObj->GetTransformedGraphic().GetBitmapEx();
548                 }
549             }
550             else
551             {
552                 const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(GetMarkedObjectByIndex(0));
553 
554                 if(pSdrGrafObj && pSdrGrafObj->isEmbeddedSvg())
555                 {
556                     aBmp = pSdrGrafObj->GetGraphic().getSvgData()->getReplacement();
557                 }
558             }
559         }
560 
561         if( !aBmp )
562         {
563             const Graphic aGraphic( GetMarkedObjMetaFile( bNoVDevIfOneBmpMarked ) );
564 
565             // #i102089# support user's settings of AA and LineSnap when the MetaFile gets
566             // rasterconverted to a bitmap
567             const SvtOptionsDrawinglayer aDrawinglayerOpt;
568             const GraphicConversionParameters aParameters(
569                 Size(),
570                 false,
571                 aDrawinglayerOpt.IsAntiAliasing(),
572                 aDrawinglayerOpt.IsSnapHorVerLinesToDiscrete());
573 
574             aBmp = aGraphic.GetBitmapEx(aParameters);
575         }
576     }
577 
578     return aBmp;
579 }
580 
581 // -----------------------------------------------------------------------------
582 
583 GDIMetaFile SdrExchangeView::GetMarkedObjMetaFile( sal_Bool bNoVDevIfOneMtfMarked ) const
584 {
585     GDIMetaFile aMtf;
586 
587     if( AreObjectsMarked() )
588     {
589         Rectangle   aBound( GetMarkedObjBoundRect() );
590         Size        aBoundSize( aBound.GetWidth(), aBound.GetHeight() );
591         MapMode     aMap( pMod->GetScaleUnit(), Point(), pMod->GetScaleFraction(), pMod->GetScaleFraction() );
592 
593         if( bNoVDevIfOneMtfMarked )
594         {
595             SdrObject*  pGrafObjTmp = GetMarkedObjectByIndex( 0 );
596             SdrGrafObj* pGrafObj = ( GetMarkedObjectCount() ==1 ) ? PTR_CAST( SdrGrafObj, pGrafObjTmp ) : NULL;
597 
598             if( pGrafObj )
599             {
600                 Graphic aGraphic( pGrafObj->GetTransformedGraphic() );
601 
602                 if( aGraphic.GetType() == GRAPHIC_BITMAP )
603                 {
604                     const Point aPos;
605 
606                     aMtf.AddAction( new MetaBmpExScaleAction( aPos, aBoundSize, aGraphic.GetBitmapEx() ) );
607                     aMtf.SetPrefMapMode( aMap );
608                     aMtf.SetPrefSize( aBoundSize );
609                 }
610                 else
611                     aMtf = aGraphic.GetGDIMetaFile();
612             }
613         }
614 
615         if( !aMtf.GetActionCount() )
616         {
617             VirtualDevice   aOut;
618             Size            aDummySize( 2, 2 );
619 
620             aOut.SetOutputSizePixel( aDummySize );
621             aOut.EnableOutput( sal_False );
622             aOut.SetMapMode( aMap );
623 
624             aMtf.Clear();
625             aMtf.Record( &aOut );
626 
627             // Replace offset given formally to DrawMarkedObj and used at XOutDev with relative
628             // MapMode (which was also used in XOutDev in that case). Goal is to paint the object
629             // as if TopLeft point is (0,0)
630             const Fraction aNeutralFraction(1, 1);
631             const MapMode aRelativeMapMode(MAP_RELATIVE, Point(-aBound.Left(), -aBound.Top()), aNeutralFraction, aNeutralFraction);
632             aOut.SetMapMode(aRelativeMapMode);
633 
634             DrawMarkedObj(aOut);
635 
636             aMtf.Stop();
637             aMtf.WindStart();
638             aMtf.SetPrefMapMode( aMap );
639 
640             // removed PrefSize extension. It is principially wrong to set a reduced size at
641             // the created MetaFile. The mentioned errors occurr at output time since the integer
642             // MapModes from VCL lead to errors. It is now corrected in the VCLRenderer for
643             // primitives (and may later be done in breaking up a MetaFile to primitives)
644             aMtf.SetPrefSize(aBoundSize);
645         }
646     }
647 
648     return aMtf;
649 }
650 
651 // -----------------------------------------------------------------------------
652 
653 Graphic SdrExchangeView::GetAllMarkedGraphic() const
654 {
655     Graphic aRet;
656 
657     if( AreObjectsMarked() )
658     {
659         if( ( 1 == GetMarkedObjectCount() ) && GetSdrMarkByIndex( 0 ) )
660             aRet = SdrExchangeView::GetObjGraphic( pMod, GetMarkedObjectByIndex( 0 ) );
661         else
662             aRet = GetMarkedObjMetaFile( sal_False );
663     }
664 
665     return aRet;
666 }
667 
668 // -----------------------------------------------------------------------------
669 
670 Graphic SdrExchangeView::GetObjGraphic( const SdrModel* pModel, const SdrObject* pObj )
671 {
672     Graphic aRet;
673 
674     if( pModel && pObj )
675     {
676         // try to get a graphic from the object first
677         const SdrGrafObj* pSdrGrafObj = dynamic_cast< const SdrGrafObj* >(pObj);
678         const SdrOle2Obj* pSdrOle2Obj = dynamic_cast< const SdrOle2Obj* >(pObj);
679 
680         if(pSdrGrafObj)
681         {
682             if(pSdrGrafObj->isEmbeddedSvg())
683             {
684                 // get Metafile for Svg content
685                 aRet = pSdrGrafObj->getMetafileFromEmbeddedSvg();
686             }
687             else
688             {
689                 // #110981# Make behaviour coherent with metafile
690                 // recording below (which of course also takes
691                 // view-transformed objects)
692                 aRet = pSdrGrafObj->GetTransformedGraphic();
693             }
694         }
695         else if(pSdrOle2Obj)
696         {
697             if ( pSdrOle2Obj->GetGraphic() )
698                 aRet = *pSdrOle2Obj->GetGraphic();
699         }
700 
701         // if graphic could not be retrieved => go the hard way and create a MetaFile
702         if( ( GRAPHIC_NONE == aRet.GetType() ) || ( GRAPHIC_DEFAULT == aRet.GetType() ) )
703         {
704             VirtualDevice   aOut;
705             GDIMetaFile     aMtf;
706             const Rectangle aBoundRect( pObj->GetCurrentBoundRect() );
707             const MapMode   aMap( pModel->GetScaleUnit(),
708                                   Point(),
709                                   pModel->GetScaleFraction(),
710                                   pModel->GetScaleFraction() );
711 
712             aOut.EnableOutput( sal_False );
713             aOut.SetMapMode( aMap );
714             aMtf.Record( &aOut );
715             pObj->SingleObjectPainter( aOut ); // #110094#-17
716             aMtf.Stop();
717             aMtf.WindStart();
718 
719             // #i99268# replace the original offset from using XOutDev's SetOffset
720             // NOT (as tried with #i92760#) with another MapMode which gets recorded
721             // by the Metafile itself (what always leads to problems), but by hardly
722             // moving the result
723             aMtf.Move(-aBoundRect.Left(), -aBoundRect.Top());
724 
725             aMtf.SetPrefMapMode( aMap );
726             aMtf.SetPrefSize( aBoundRect.GetSize() );
727 
728             if( aMtf.GetActionCount() )
729                 aRet = aMtf;
730         }
731      }
732 
733      return aRet;
734 }
735 
736 // -----------------------------------------------------------------------------
737 
738 void SdrExchangeView::DrawMarkedObj(OutputDevice& rOut) const
739 {
740     SortMarkedObjects();
741 
742     ::std::vector< ::std::vector< SdrMark* > >  aObjVectors( 2 );
743     ::std::vector< SdrMark* >&                  rObjVector1 = aObjVectors[ 0 ];
744     ::std::vector< SdrMark* >&                  rObjVector2 = aObjVectors[ 1 ];
745     const SdrLayerAdmin&                        rLayerAdmin = pMod->GetLayerAdmin();
746     const sal_uInt32                            nControlLayerId = rLayerAdmin.GetLayerID( rLayerAdmin.GetControlLayerName(), sal_False );
747     sal_uInt32                                  n, nCount;
748 
749     for( n = 0, nCount = GetMarkedObjectCount(); n < nCount; n++ )
750     {
751         SdrMark* pMark = GetSdrMarkByIndex( n );
752 
753         // paint objects on control layer on top of all otherobjects
754         if( nControlLayerId == pMark->GetMarkedSdrObj()->GetLayer() )
755             rObjVector2.push_back( pMark );
756         else
757             rObjVector1.push_back( pMark );
758     }
759 
760     for( n = 0, nCount = aObjVectors.size(); n < nCount; n++ )
761     {
762         ::std::vector< SdrMark* >& rObjVector = aObjVectors[ n ];
763 
764         for( sal_uInt32 i = 0; i < rObjVector.size(); i++ )
765         {
766             SdrMark*    pMark = rObjVector[ i ];
767             pMark->GetMarkedSdrObj()->SingleObjectPainter( rOut ); // #110094#-17
768         }
769     }
770 }
771 
772 // -----------------------------------------------------------------------------
773 
774 SdrModel* SdrExchangeView::GetMarkedObjModel() const
775 {
776     // Wenn das sortieren der MarkList mal stoeren sollte,
777     // werde ich sie mir wohl kopieren muessen.
778     SortMarkedObjects();
779     SdrModel* pNeuMod=pMod->AllocModel();
780     SdrPage* pNeuPag=pNeuMod->AllocPage(sal_False);
781     pNeuMod->InsertPage(pNeuPag);
782 
783     if( !mxSelectionController.is() || !mxSelectionController->GetMarkedObjModel( pNeuPag ) )
784     {
785         ::std::vector< ::std::vector< SdrMark* > >  aObjVectors( 2 );
786         ::std::vector< SdrMark* >&                  rObjVector1 = aObjVectors[ 0 ];
787         ::std::vector< SdrMark* >&                  rObjVector2 = aObjVectors[ 1 ];
788         const SdrLayerAdmin&                        rLayerAdmin = pMod->GetLayerAdmin();
789         const sal_uInt32                            nControlLayerId = rLayerAdmin.GetLayerID( rLayerAdmin.GetControlLayerName(), sal_False );
790         sal_uInt32                                  n, nCount, nCloneErrCnt = 0;
791 
792         for( n = 0, nCount = GetMarkedObjectCount(); n < nCount; n++ )
793         {
794             SdrMark* pMark = GetSdrMarkByIndex( n );
795 
796             // paint objects on control layer on top of all otherobjects
797             if( nControlLayerId == pMark->GetMarkedSdrObj()->GetLayer() )
798                 rObjVector2.push_back( pMark );
799             else
800                 rObjVector1.push_back( pMark );
801         }
802 
803         // #i13033#
804         // New mechanism to re-create the connections of cloned connectors
805         CloneList aCloneList;
806 
807         for( n = 0, nCount = aObjVectors.size(); n < nCount; n++ )
808         {
809             ::std::vector< SdrMark* >& rObjVector = aObjVectors[ n ];
810 
811             for( sal_uInt32 i = 0; i < rObjVector.size(); i++ )
812             {
813                 const SdrMark*      pMark = rObjVector[ i ];
814                 const SdrObject*    pObj = pMark->GetMarkedSdrObj();
815                 SdrObject*          pNeuObj;
816 
817                 if( pObj->ISA( SdrPageObj ) )
818                 {
819                     // convert SdrPageObj's to a graphic representation, because
820                     // virtual connection to referenced page gets lost in new model
821                     pNeuObj = new SdrGrafObj( GetObjGraphic( pMod, pObj ), pObj->GetLogicRect() );
822                     pNeuObj->SetPage( pNeuPag );
823                     pNeuObj->SetModel( pNeuMod );
824                 }
825                 else
826                 {
827                     // #116235#
828                     // pNeuObj = pObj->Clone( pNeuPag, pNeuMod );
829                     pNeuObj = pObj->Clone();
830                     pNeuObj->SetPage( pNeuPag );
831                     pNeuObj->SetModel( pNeuMod );
832                 }
833 
834                 if( pNeuObj )
835                 {
836                     SdrInsertReason aReason(SDRREASON_VIEWCALL);
837                     pNeuPag->InsertObject(pNeuObj,CONTAINER_APPEND,&aReason);
838 
839                     // #i13033#
840                     aCloneList.AddPair(pObj, pNeuObj);
841                 }
842                 else
843                     nCloneErrCnt++;
844             }
845         }
846 
847         // #i13033#
848         // New mechanism to re-create the connections of cloned connectors
849         aCloneList.CopyConnections();
850 
851         if(0L != nCloneErrCnt)
852         {
853 #ifdef DBG_UTIL
854             ByteString aStr("SdrExchangeView::GetMarkedObjModel(): Fehler beim Clonen ");
855 
856             if(nCloneErrCnt == 1)
857             {
858                 aStr += "eines Zeichenobjekts.";
859             }
860             else
861             {
862                 aStr += "von ";
863                 aStr += ByteString::CreateFromInt32( nCloneErrCnt );
864                 aStr += " Zeichenobjekten.";
865             }
866 
867             aStr += " Objektverbindungen werden nicht mitkopiert.";
868 
869             DBG_ERROR(aStr.GetBuffer());
870 #endif
871         }
872     }
873     return pNeuMod;
874 }
875 
876 // -----------------------------------------------------------------------------
877 
878 sal_Bool SdrExchangeView::Cut( sal_uIntPtr /*nFormat */)
879 {
880     DBG_ERROR( "SdrExchangeView::Cut: Not supported anymore" );
881     return sal_False;
882 }
883 
884 // -----------------------------------------------------------------------------
885 
886 void SdrExchangeView::CutMarked( sal_uIntPtr /*nFormat */)
887 {
888     DBG_ERROR( "SdrExchangeView::CutMarked: Not supported anymore" );
889 }
890 
891 // -----------------------------------------------------------------------------
892 
893 sal_Bool SdrExchangeView::Yank(sal_uIntPtr /*nFormat*/)
894 {
895     DBG_ERROR( "SdrExchangeView::Yank: Not supported anymore" );
896     return sal_False;
897 }
898 
899 // -----------------------------------------------------------------------------
900 
901 void SdrExchangeView::YankMarked(sal_uIntPtr /*nFormat*/)
902 {
903     DBG_ERROR( "YankMarked: Not supported anymore" );
904 }
905 
906 // -----------------------------------------------------------------------------
907 
908 sal_Bool SdrExchangeView::Paste(Window* /*pWin*/, sal_uIntPtr /*nFormat*/)
909 {
910     DBG_ERROR( "SdrExchangeView::Paste: Not supported anymore" );
911     return sal_False;
912 }
913