1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/svditer.hxx>
21 #include <svx/svdograf.hxx>
22 #include <svx/svdogrp.hxx>
23 #include <svx/svdoole2.hxx>
24 #include <svx/svdpage.hxx>
25 #include <svx/svdundo.hxx>
26 #include <sfx2/docfile.hxx>
27 #include <tools/urlobj.hxx>
28 #include <toolkit/helper/vclunohelper.hxx>
30 #include "drawview.hxx"
32 #include "drwlayer.hxx"
33 #include "viewdata.hxx"
34 #include "document.hxx"
36 #include "drwtrans.hxx"
37 #include "transobj.hxx"
38 #include "drawutil.hxx"
40 #include "globstr.hrc"
41 #include "chartarr.hxx"
42 #include <gridwin.hxx>
44 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
45 #include <com/sun/star/embed/Aspects.hpp>
46 #include <com/sun/star/embed/XEmbeddedObject.hpp>
47 #include <com/sun/star/embed/XComponentSupplier.hpp>
48 #include <com/sun/star/chart2/XChartTypeContainer.hpp>
49 #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp>
50 #include <com/sun/star/chart2/XDataSeriesContainer.hpp>
52 using namespace com::sun::star
;
54 // STATIC DATA -----------------------------------------------------------
58 void ScDrawView::CheckOle( const SdrMarkList
& rMarkList
, bool& rAnyOle
, bool& rOneOle
)
60 rAnyOle
= rOneOle
= false;
61 const size_t nCount
= rMarkList
.GetMarkCount();
62 for (size_t i
=0; i
<nCount
; ++i
)
64 SdrMark
* pMark
= rMarkList
.GetMark(i
);
65 SdrObject
* pObj
= pMark
->GetMarkedSdrObj();
66 sal_uInt16 nSdrObjKind
= pObj
->GetObjIdentifier();
67 if (nSdrObjKind
== OBJ_OLE2
)
70 rOneOle
= (nCount
== 1);
73 else if ( pObj
->ISA(SdrObjGroup
) )
75 SdrObjListIter
aIter( *pObj
, IM_DEEPNOGROUPS
);
76 SdrObject
* pSubObj
= aIter
.Next();
79 if ( pSubObj
->GetObjIdentifier() == OBJ_OLE2
)
82 // rOneOle remains sal_False - a group isn't treated like a single OLE object
85 pSubObj
= aIter
.Next();
91 bool ScDrawView::BeginDrag( vcl::Window
* pWindow
, const Point
& rStartPos
)
95 if ( AreObjectsMarked() )
99 Rectangle aMarkedRect
= GetAllMarkedRect();
100 vcl::Region
aRegion( aMarkedRect
);
102 aDragStartDiff
= rStartPos
- aMarkedRect
.TopLeft();
104 bool bAnyOle
, bOneOle
;
105 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
106 CheckOle( rMarkList
, bAnyOle
, bOneOle
);
108 ScDocShellRef aDragShellRef
;
111 aDragShellRef
= new ScDocShell
; // DocShell needs a Ref immediately
112 aDragShellRef
->DoInitNew(NULL
);
114 ScDrawLayer::SetGlobalDrawPersist(aDragShellRef
);
115 SdrModel
* pModel
= GetMarkedObjModel();
116 ScDrawLayer::SetGlobalDrawPersist(NULL
);
118 // Charts now always copy their data in addition to the source reference, so
119 // there's no need to call SchDLL::Update for the charts in the clipboard doc.
120 // Update with the data (including NumberFormatter) from the live document would
121 // also store the NumberFormatter in the clipboard chart (#88749#)
122 // lcl_RefreshChartData( pModel, pViewData->GetDocument() );
124 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
126 TransferableObjectDescriptor aObjDesc
;
127 pDocSh
->FillTransferableObjectDescriptor( aObjDesc
);
128 aObjDesc
.maDisplayName
= pDocSh
->GetMedium()->GetURLObject().GetURLNoPass();
129 // maSize is set in ScDrawTransferObj ctor
131 ScDrawTransferObj
* pTransferObj
= new ScDrawTransferObj( pModel
, pDocSh
, aObjDesc
);
132 uno::Reference
<datatransfer::XTransferable
> xTransferable( pTransferObj
);
134 pTransferObj
->SetDrawPersist( &aDragShellRef
); // keep persist for ole objects alive
135 pTransferObj
->SetDragSource( this ); // copies selection
137 SC_MOD()->SetDragObject( NULL
, pTransferObj
); // for internal D&D
138 pTransferObj
->StartDrag( pWindow
, DND_ACTION_COPYMOVE
| DND_ACTION_LINK
);
146 void getRangeFromDataSource( uno::Reference
< chart2::data::XDataSource
> xDataSource
, std::vector
<OUString
>& rRangeRep
)
148 uno::Sequence
<uno::Reference
<chart2::data::XLabeledDataSequence
> > xSeqs
= xDataSource
->getDataSequences();
149 for (sal_Int32 i
= 0, n
= xSeqs
.getLength(); i
< n
; ++i
)
151 uno::Reference
<chart2::data::XLabeledDataSequence
> xLS
= xSeqs
[i
];
152 uno::Reference
<chart2::data::XDataSequence
> xSeq
= xLS
->getValues();
155 OUString aRep
= xSeq
->getSourceRangeRepresentation();
156 rRangeRep
.push_back(aRep
);
158 xSeq
= xLS
->getLabel();
161 OUString aRep
= xSeq
->getSourceRangeRepresentation();
162 rRangeRep
.push_back(aRep
);
167 void getRangeFromErrorBar(const uno::Reference
< chart2::XChartDocument
>& rChartDoc
, std::vector
<OUString
>& rRangeRep
)
169 uno::Reference
<chart2::XDiagram
> xDiagram
= rChartDoc
->getFirstDiagram();
173 uno::Reference
< chart2::XCoordinateSystemContainer
> xCooSysContainer( xDiagram
, uno::UNO_QUERY
);
174 if(!xCooSysContainer
.is())
177 uno::Sequence
< uno::Reference
< chart2::XCoordinateSystem
> > xCooSysSequence( xCooSysContainer
->getCoordinateSystems());
178 for(sal_Int32 i
= 0; i
< xCooSysSequence
.getLength(); ++i
)
180 uno::Reference
< chart2::XChartTypeContainer
> xChartTypeContainer( xCooSysSequence
[i
], uno::UNO_QUERY
);
181 if(!xChartTypeContainer
.is())
184 uno::Sequence
< uno::Reference
< chart2::XChartType
> > xChartTypeSequence( xChartTypeContainer
->getChartTypes() );
185 for(sal_Int32 nChartType
= 0; nChartType
< xChartTypeSequence
.getLength(); ++nChartType
)
187 uno::Reference
< chart2::XDataSeriesContainer
> xDataSequenceContainer( xChartTypeSequence
[nChartType
], uno::UNO_QUERY
);
188 if(!xDataSequenceContainer
.is())
191 uno::Sequence
< uno::Reference
< chart2::XDataSeries
> > xSeriesSequence( xDataSequenceContainer
->getDataSeries() );
192 for(sal_Int32 nDataSeries
= 0; nDataSeries
< xSeriesSequence
.getLength(); ++nDataSeries
)
194 uno::Reference
< chart2::XDataSeries
> xSeries
= xSeriesSequence
[nDataSeries
];
195 uno::Reference
< beans::XPropertySet
> xPropSet( xSeries
, uno::UNO_QUERY
);
196 uno::Reference
< chart2::data::XDataSource
> xErrorBarY
;
197 xPropSet
->getPropertyValue("ErrorBarY") >>= xErrorBarY
;
199 getRangeFromDataSource(xErrorBarY
, rRangeRep
);
200 uno::Reference
< chart2::data::XDataSource
> xErrorBarX
;
201 xPropSet
->getPropertyValue("ErrorBarX") >>= xErrorBarX
;
203 getRangeFromDataSource(xErrorBarX
, rRangeRep
);
209 void getRangeFromOle2Object(const SdrOle2Obj
& rObj
, std::vector
<OUString
>& rRangeRep
)
212 // not a chart object.
215 uno::Reference
<embed::XEmbeddedObject
> xObj
= rObj
.GetObjRef();
219 uno::Reference
<embed::XComponentSupplier
> xCompSupp(xObj
, uno::UNO_QUERY
);
223 uno::Reference
<chart2::XChartDocument
> xChartDoc(xCompSupp
->getComponent(), uno::UNO_QUERY
);
227 if(xChartDoc
->hasInternalDataProvider())
230 getRangeFromErrorBar(xChartDoc
, rRangeRep
);
232 uno::Reference
<chart2::data::XDataSource
> xDataSource(xChartDoc
, uno::UNO_QUERY
);
233 if (!xDataSource
.is())
236 // Get all data sources used in this chart.
237 getRangeFromDataSource(xDataSource
, rRangeRep
);
241 * Get all cell ranges that are referenced by the selected chart objects.
243 void getChartSourceRanges(ScDocument
* pDoc
, const SdrMarkList
& rObjs
, std::vector
<ScRange
>& rRanges
)
245 std::vector
<OUString
> aRangeReps
;
246 for (size_t i
= 0, n
= rObjs
.GetMarkCount(); i
< n
; ++i
)
248 const SdrMark
* pMark
= rObjs
.GetMark(i
);
252 const SdrObject
* pObj
= pMark
->GetMarkedSdrObj();
256 switch (pObj
->GetObjIdentifier())
259 getRangeFromOle2Object(static_cast<const SdrOle2Obj
&>(*pObj
), aRangeReps
);
263 SdrObjListIter
aIter(*pObj
, IM_DEEPNOGROUPS
);
264 for (SdrObject
* pSubObj
= aIter
.Next(); pSubObj
; pSubObj
= aIter
.Next())
266 if (pSubObj
->GetObjIdentifier() != OBJ_OLE2
)
269 getRangeFromOle2Object(static_cast<const SdrOle2Obj
&>(*pSubObj
), aRangeReps
);
279 // Compile all range representation strings into ranges.
280 std::vector
<OUString
>::const_iterator it
= aRangeReps
.begin(), itEnd
= aRangeReps
.end();
281 for (; it
!= itEnd
; ++it
)
285 if (aRange
.Parse(*it
, pDoc
, pDoc
->GetAddressConvention()) & SCA_VALID
)
287 for(size_t i
= 0; i
< aRange
.size(); ++i
)
288 rRanges
.push_back(*aRange
[i
]);
290 else if (aAddr
.Parse(*it
, pDoc
, pDoc
->GetAddressConvention()) & SCA_VALID
)
291 rRanges
.push_back(aAddr
);
295 class InsertTabIndex
: std::unary_function
<ScRange
, void>
297 std::vector
<SCTAB
>& mrTabs
;
299 InsertTabIndex(std::vector
<SCTAB
>& rTabs
) : mrTabs(rTabs
) {}
300 void operator() (const ScRange
& rRange
)
302 mrTabs
.push_back(rRange
.aStart
.Tab());
306 class CopyRangeData
: std::unary_function
<ScRange
, void>
311 CopyRangeData(ScDocument
* pSrc
, ScDocument
* pDest
) : mpSrc(pSrc
), mpDest(pDest
) {}
313 void operator() (const ScRange
& rRange
)
316 mpSrc
->GetName(rRange
.aStart
.Tab(), aTabName
);
319 if (!mpDest
->GetTable(aTabName
, nTab
))
320 // Sheet by this name doesn't exist.
323 mpSrc
->CopyStaticToDocument(rRange
, nTab
, mpDest
);
327 void copyChartRefDataToClipDoc(ScDocument
* pSrcDoc
, ScDocument
* pClipDoc
, const std::vector
<ScRange
>& rRanges
)
329 // Get a list of referenced table indices.
330 std::vector
<SCTAB
> aTabs
;
331 std::for_each(rRanges
.begin(), rRanges
.end(), InsertTabIndex(aTabs
));
332 std::sort(aTabs
.begin(), aTabs
.end());
333 aTabs
.erase(std::unique(aTabs
.begin(), aTabs
.end()), aTabs
.end());
339 // Create sheets only for referenced source sheets.
341 std::vector
<SCTAB
>::const_iterator it
= aTabs
.begin(), itEnd
= aTabs
.end();
342 if (!pSrcDoc
->GetName(*it
, aName
))
345 pClipDoc
->SetTabNameOnLoad(0, aName
); // document initially has one sheet.
347 for (++it
; it
!= itEnd
; ++it
)
349 if (!pSrcDoc
->GetName(*it
, aName
))
352 pClipDoc
->AppendTabOnLoad(aName
);
355 std::for_each(rRanges
.begin(), rRanges
.end(), CopyRangeData(pSrcDoc
, pClipDoc
));
360 void ScDrawView::DoCopy()
362 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
363 std::vector
<ScRange
> aRanges
;
364 getChartSourceRanges(pDoc
, rMarkList
, aRanges
);
366 // update ScGlobal::pDrawClipDocShellRef
367 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc(!aRanges
.empty()) );
368 if (ScGlobal::pDrawClipDocShellRef
)
370 // Copy data referenced by the chart objects to the draw clip
371 // document. We need to do this before GetMarkedObjModel() below.
372 ScDocShellRef xDocSh
= *ScGlobal::pDrawClipDocShellRef
;
373 ScDocument
& rClipDoc
= xDocSh
->GetDocument();
374 copyChartRefDataToClipDoc(pDoc
, &rClipDoc
, aRanges
);
376 SdrModel
* pModel
= GetMarkedObjModel();
377 ScDrawLayer::SetGlobalDrawPersist(NULL
);
379 // Charts now always copy their data in addition to the source reference, so
380 // there's no need to call SchDLL::Update for the charts in the clipboard doc.
381 // Update with the data (including NumberFormatter) from the live document would
382 // also store the NumberFormatter in the clipboard chart (#88749#)
384 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
386 TransferableObjectDescriptor aObjDesc
;
387 pDocSh
->FillTransferableObjectDescriptor( aObjDesc
);
388 aObjDesc
.maDisplayName
= pDocSh
->GetMedium()->GetURLObject().GetURLNoPass();
389 // maSize is set in ScDrawTransferObj ctor
391 ScDrawTransferObj
* pTransferObj
= new ScDrawTransferObj( pModel
, pDocSh
, aObjDesc
);
392 uno::Reference
<datatransfer::XTransferable
> xTransferable( pTransferObj
);
394 if ( ScGlobal::pDrawClipDocShellRef
)
396 pTransferObj
->SetDrawPersist( &(*ScGlobal::pDrawClipDocShellRef
) ); // keep persist for ole objects alive
399 pTransferObj
->CopyToClipboard( pViewData
->GetActiveWin() ); // system clipboard
400 SC_MOD()->SetClipObject( NULL
, pTransferObj
); // internal clipboard
403 uno::Reference
<datatransfer::XTransferable
> ScDrawView::CopyToTransferable()
405 bool bAnyOle
, bOneOle
;
406 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
407 CheckOle( rMarkList
, bAnyOle
, bOneOle
);
409 // update ScGlobal::pDrawClipDocShellRef
410 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle
) );
411 SdrModel
* pModel
= GetMarkedObjModel();
412 ScDrawLayer::SetGlobalDrawPersist(NULL
);
414 // Charts now always copy their data in addition to the source reference, so
415 // there's no need to call SchDLL::Update for the charts in the clipboard doc.
416 // Update with the data (including NumberFormatter) from the live document would
417 // also store the NumberFormatter in the clipboard chart (#88749#)
418 // lcl_RefreshChartData( pModel, pViewData->GetDocument() );
420 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
422 TransferableObjectDescriptor aObjDesc
;
423 pDocSh
->FillTransferableObjectDescriptor( aObjDesc
);
424 aObjDesc
.maDisplayName
= pDocSh
->GetMedium()->GetURLObject().GetURLNoPass();
425 // maSize is set in ScDrawTransferObj ctor
427 ScDrawTransferObj
* pTransferObj
= new ScDrawTransferObj( pModel
, pDocSh
, aObjDesc
);
428 uno::Reference
<datatransfer::XTransferable
> xTransferable( pTransferObj
);
430 if ( ScGlobal::pDrawClipDocShellRef
)
432 pTransferObj
->SetDrawPersist( &(*ScGlobal::pDrawClipDocShellRef
) ); // keep persist for ole objects alive
435 return xTransferable
;
438 // Korrektur fuer 100% berechnen, unabhaengig von momentanen Einstellungen
440 void ScDrawView::CalcNormScale( Fraction
& rFractX
, Fraction
& rFractY
) const
442 double nPPTX
= ScGlobal::nScreenPPTX
;
443 double nPPTY
= ScGlobal::nScreenPPTY
;
446 nPPTX
/= pViewData
->GetDocShell()->GetOutputFactor();
450 pDoc
->GetTableArea( nTab
, nEndCol
, nEndRow
);
457 ScDrawUtil::CalcScale( pDoc
, nTab
, 0,0, nEndCol
,nEndRow
, pDev
, aZoom
,aZoom
,
458 nPPTX
, nPPTY
, rFractX
,rFractY
);
461 void ScDrawView::SetMarkedOriginalSize()
463 SdrUndoGroup
* pUndoGroup
= new SdrUndoGroup(*GetModel());
465 const SdrMarkList
& rMarkList
= GetMarkedObjectList();
467 const size_t nCount
= rMarkList
.GetMarkCount();
468 for (size_t i
=0; i
<nCount
; ++i
)
470 SdrObject
* pObj
= rMarkList
.GetMark(i
)->GetMarkedSdrObj();
471 sal_uInt16 nIdent
= pObj
->GetObjIdentifier();
474 if (nIdent
== OBJ_OLE2
)
476 // TODO/LEAN: working with visual area can switch object to running state
477 uno::Reference
< embed::XEmbeddedObject
> xObj( static_cast<SdrOle2Obj
*>(pObj
)->GetObjRef(), uno::UNO_QUERY
);
478 if ( xObj
.is() ) // NULL for an invalid object that couldn't be loaded
480 sal_Int64 nAspect
= static_cast<SdrOle2Obj
*>(pObj
)->GetAspect();
482 if ( nAspect
== embed::Aspects::MSOLE_ICON
)
484 MapMode
aMapMode( MAP_100TH_MM
);
485 aOriginalSize
= static_cast<SdrOle2Obj
*>(pObj
)->GetOrigObjSize( &aMapMode
);
490 MapUnit aUnit
= VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj
->getMapUnit( static_cast<SdrOle2Obj
*>(pObj
)->GetAspect() ) );
494 aSz
= xObj
->getVisualAreaSize( static_cast<SdrOle2Obj
*>(pObj
)->GetAspect() );
495 aOriginalSize
= OutputDevice::LogicToLogic(
496 Size( aSz
.Width
, aSz
.Height
),
497 aUnit
, MAP_100TH_MM
);
499 } catch( embed::NoVisualAreaSizeException
& )
501 OSL_ENSURE( false, "Can't get the original size of the object!" );
506 else if (nIdent
== OBJ_GRAF
)
508 const Graphic
& rGraphic
= static_cast<SdrGrafObj
*>(pObj
)->GetGraphic();
510 MapMode aSourceMap
= rGraphic
.GetPrefMapMode();
511 MapMode
aDestMap( MAP_100TH_MM
);
512 if (aSourceMap
.GetMapUnit() == MAP_PIXEL
)
514 // Pixel-Korrektur beruecksichtigen, damit Bitmap auf dem Bildschirm stimmt
516 Fraction aNormScaleX
, aNormScaleY
;
517 CalcNormScale( aNormScaleX
, aNormScaleY
);
518 aDestMap
.SetScaleX(aNormScaleX
);
519 aDestMap
.SetScaleY(aNormScaleY
);
523 vcl::Window
* pActWin
= pViewData
->GetActiveWin();
526 aOriginalSize
= pActWin
->LogicToLogic(
527 rGraphic
.GetPrefSize(), &aSourceMap
, &aDestMap
);
535 Rectangle aDrawRect
= pObj
->GetLogicRect();
537 pUndoGroup
->AddAction( new SdrUndoGeoObj( *pObj
) );
538 pObj
->Resize( aDrawRect
.TopLeft(), Fraction( aOriginalSize
.Width(), aDrawRect
.GetWidth() ),
539 Fraction( aOriginalSize
.Height(), aDrawRect
.GetHeight() ) );
544 if (nDone
&& pViewData
)
546 pUndoGroup
->SetComment(ScGlobal::GetRscString( STR_UNDO_ORIGINALSIZE
));
547 ScDocShell
* pDocSh
= pViewData
->GetDocShell();
548 pDocSh
->GetUndoManager()->AddUndoAction(pUndoGroup
);
549 pDocSh
->SetDrawModified();
555 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */