Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / ui / drawfunc / fuins1.cxx
blob11e2290d08ff793dd22696ee70f4499f024b521a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <config_features.h>
22 #include <sal/log.hxx>
23 #include <sfx2/opengrf.hxx>
24 #include <svx/svdograf.hxx>
25 #include <svx/svdomedia.hxx>
26 #include <svx/svdpage.hxx>
27 #include <svx/svdpagv.hxx>
28 #include <svx/svdview.hxx>
29 #include <svx/linkwarn.hxx>
30 #include <svx/svxids.hrc>
31 #include <vcl/graphicfilter.hxx>
32 #include <svl/stritem.hxx>
33 #include <svtools/miscopt.hxx>
34 #include <avmedia/mediawindow.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/weld.hxx>
37 #include <vcl/GraphicNativeTransform.hxx>
38 #include <vcl/GraphicNativeMetadata.hxx>
39 #include <fuinsert.hxx>
40 #include <tabvwsh.hxx>
41 #include <drwlayer.hxx>
42 #include <drawview.hxx>
43 #include <document.hxx>
44 #include <scresid.hxx>
45 #include <strings.hrc>
46 #include <globstr.hrc>
48 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
49 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
50 #include <com/sun/star/ui/dialogs/ListboxControlActions.hpp>
51 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
52 #include <com/sun/star/uno/Sequence.hxx>
54 using namespace css;
55 using namespace css::uno;
57 void ScLimitSizeOnDrawPage( Size& rSize, Point& rPos, const Size& rPage )
59 if ( !rPage.Width() || !rPage.Height() )
60 return;
62 Size aPageSize = rPage;
63 bool bNegative = aPageSize.Width() < 0;
64 if ( bNegative )
66 // make everything positive temporarily
67 aPageSize.setWidth( -aPageSize.Width() );
68 rPos.setX( -rPos.X() - rSize.Width() );
71 if ( rSize.Width() > aPageSize.Width() || rSize.Height() > aPageSize.Height() )
73 double fX = aPageSize.Width() / static_cast<double>(rSize.Width());
74 double fY = aPageSize.Height() / static_cast<double>(rSize.Height());
76 if ( fX < fY )
78 rSize.setWidth( aPageSize.Width() );
79 rSize.setHeight( static_cast<long>( rSize.Height() * fX ) );
81 else
83 rSize.setHeight( aPageSize.Height() );
84 rSize.setWidth( static_cast<long>( rSize.Width() * fY ) );
87 if (!rSize.Width())
88 rSize.setWidth( 1 );
89 if (!rSize.Height())
90 rSize.setHeight( 1 );
93 if ( rPos.X() + rSize.Width() > aPageSize.Width() )
94 rPos.setX( aPageSize.Width() - rSize.Width() );
95 if ( rPos.Y() + rSize.Height() > aPageSize.Height() )
96 rPos.setY( aPageSize.Height() - rSize.Height() );
98 if ( bNegative )
99 rPos.setX( -rPos.X() - rSize.Width() ); // back to real position
102 static void lcl_InsertGraphic( const Graphic& rGraphic,
103 const OUString& rFileName, const OUString& rFilterName, bool bAsLink, bool bApi,
104 ScTabViewShell& rViewSh, const vcl::Window* pWindow, SdrView* pView,
105 ScAnchorType aAnchorType = SCA_CELL )
107 Graphic& rGraphic1 = const_cast<Graphic &>(rGraphic);
108 GraphicNativeMetadata aMetadata;
109 if ( aMetadata.read(rGraphic1) )
111 const sal_uInt16 aRotation = aMetadata.getRotation();
112 if (aRotation != 0)
114 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr, VclMessageType::Question,VclButtonsType::YesNo,ScResId(STR_QUERYROTATION)));
115 if (xQueryBox->run() == RET_YES)
117 GraphicNativeTransform aTransform( rGraphic1 );
118 aTransform.rotate( aRotation );
122 ScDrawView* pDrawView = rViewSh.GetScDrawView();
124 // #i123922# check if an existing object is selected; if yes, evtl. replace
125 // the graphic for a SdrGraphObj (including link state updates) or adapt the fill
126 // style for other objects
127 if(pDrawView && 1 == pDrawView->GetMarkedObjectCount())
129 SdrObject* pPickObj = pDrawView->GetMarkedObjectByIndex(0);
131 if(pPickObj)
133 //sal_Int8 nAction(DND_ACTION_MOVE);
134 //Point aPos;
135 const OUString aBeginUndo(ScResId(STR_UNDO_DRAGDROP));
137 SdrObject* pResult = pDrawView->ApplyGraphicToObject(
138 *pPickObj,
139 rGraphic1,
140 aBeginUndo,
141 bAsLink ? rFileName : OUString(),
142 bAsLink ? rFilterName : OUString());
144 if(pResult)
146 // we are done; mark the modified/new object
147 pDrawView->MarkObj(pResult, pDrawView->GetSdrPageView());
148 return;
153 // set the size so the graphic has its original pixel size
154 // at 100% view scale (as in SetMarkedOriginalSize),
155 // instead of respecting the current view scale
156 MapMode aSourceMap = rGraphic.GetPrefMapMode();
157 MapMode aDestMap( MapUnit::Map100thMM );
158 if ( aSourceMap.GetMapUnit() == MapUnit::MapPixel && pDrawView )
160 Fraction aScaleX, aScaleY;
161 pDrawView->CalcNormScale( aScaleX, aScaleY );
162 aDestMap.SetScaleX(aScaleX);
163 aDestMap.SetScaleY(aScaleY);
165 Size aLogicSize = pWindow->LogicToLogic(
166 rGraphic.GetPrefSize(), &aSourceMap, &aDestMap );
168 // Limit size
170 SdrPageView* pPV = pView->GetSdrPageView();
171 SdrPage* pPage = pPV->GetPage();
172 Point aInsertPos = rViewSh.GetInsertPos();
174 ScViewData& rData = rViewSh.GetViewData();
175 if ( rData.GetDocument()->IsNegativePage( rData.GetTabNo() ) )
176 aInsertPos.AdjustX( -(aLogicSize.Width()) ); // move position to left edge
178 ScLimitSizeOnDrawPage( aLogicSize, aInsertPos, pPage->GetSize() );
180 tools::Rectangle aRect ( aInsertPos, aLogicSize );
182 SdrGrafObj* pObj = new SdrGrafObj(
183 pView->getSdrModelFromSdrView(), // TTTT pView should be reference
184 rGraphic1,
185 aRect);
187 // calling SetGraphicLink here doesn't work
188 // Yes, due to the SdrObject had no SdrModel
189 // Path is no longer used as name for the graphics object
191 ScDrawLayer* pLayer = static_cast<ScDrawLayer*>(pView->GetModel());
192 OUString aName = pLayer->GetNewGraphicName(); // "Graphics"
193 pObj->SetName(aName);
195 if (aAnchorType == SCA_CELL || aAnchorType == SCA_CELL_RESIZE)
196 ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *(rData.GetDocument()), rData.GetTabNo(),
197 aAnchorType == SCA_CELL_RESIZE);
199 // don't select if from (dispatch) API, to allow subsequent cell operations
200 SdrInsertFlags nInsOptions = bApi ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE;
201 bool bSuccess = pView->InsertObjectAtView( pObj, *pPV, nInsOptions );
203 // SetGraphicLink has to be used after inserting the object,
204 // otherwise an empty graphic is swapped in and the contact stuff crashes.
205 // See #i37444#.
206 if (bSuccess && bAsLink)
207 pObj->SetGraphicLink( rFileName, ""/*TODO?*/, rFilterName );
210 static void lcl_InsertMedia( const OUString& rMediaURL, bool bApi,
211 ScTabViewShell* pViewSh, const vcl::Window* pWindow, SdrView* pView,
212 const Size& rPrefSize, bool const bLink )
214 SdrPageView* pPV = pView->GetSdrPageView();
215 SdrPage* pPage = pPV->GetPage();
216 ScViewData& rData = pViewSh->GetViewData();
217 Point aInsertPos( pViewSh->GetInsertPos() );
218 Size aSize;
220 if( rPrefSize.Width() && rPrefSize.Height() )
222 if( pWindow )
223 aSize = pWindow->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM));
224 else
225 aSize = Application::GetDefaultDevice()->PixelToLogic(rPrefSize, MapMode(MapUnit::Map100thMM));
227 else
228 aSize = Size( 5000, 5000 );
230 ScLimitSizeOnDrawPage( aSize, aInsertPos, pPage->GetSize() );
232 if( rData.GetDocument()->IsNegativePage( rData.GetTabNo() ) )
233 aInsertPos.AdjustX( -(aSize.Width()) );
235 OUString realURL;
236 if (bLink)
238 realURL = rMediaURL;
240 else
242 uno::Reference<frame::XModel> const xModel(
243 rData.GetDocument()->GetDocumentShell()->GetModel());
244 #if HAVE_FEATURE_AVMEDIA
245 bool const bRet = ::avmedia::EmbedMedia(xModel, rMediaURL, realURL);
246 if (!bRet) { return; }
247 #else
248 return;
249 #endif
252 SdrMediaObj* pObj = new SdrMediaObj(
253 *rData.GetDocument()->GetDrawLayer(),
254 tools::Rectangle(aInsertPos, aSize));
256 pObj->setURL( realURL, ""/*TODO?*/ );
257 pView->InsertObjectAtView( pObj, *pPV, bApi ? SdrInsertFlags::DONTMARK : SdrInsertFlags::NONE );
260 FuInsertGraphic::FuInsertGraphic( ScTabViewShell& rViewSh,
261 vcl::Window* pWin,
262 ScDrawView* pViewP,
263 SdrModel* pDoc,
264 SfxRequest& rReq )
265 : FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
267 const SfxItemSet* pReqArgs = rReq.GetArgs();
268 const SfxPoolItem* pItem;
269 if ( pReqArgs &&
270 pReqArgs->GetItemState( SID_INSERT_GRAPHIC, true, &pItem ) == SfxItemState::SET )
272 OUString aFileName = static_cast<const SfxStringItem*>(pItem)->GetValue();
274 OUString aFilterName;
275 if ( pReqArgs->GetItemState( FN_PARAM_FILTER, true, &pItem ) == SfxItemState::SET )
276 aFilterName = static_cast<const SfxStringItem*>(pItem)->GetValue();
278 bool bAsLink = false;
279 if ( pReqArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET )
280 bAsLink = static_cast<const SfxBoolItem*>(pItem)->GetValue();
282 Graphic aGraphic;
283 ErrCode nError = GraphicFilter::LoadGraphic( aFileName, aFilterName, aGraphic, &GraphicFilter::GetGraphicFilter() );
284 if ( nError == ERRCODE_NONE )
286 lcl_InsertGraphic( aGraphic, aFileName, aFilterName, bAsLink, true, rViewSh, pWindow, pView );
289 else
291 SvxOpenGraphicDialog aDlg(ScResId(STR_INSERTGRAPHIC), pWin ? pWin->GetFrameWeld() : nullptr,
292 ui::dialogs::TemplateDescription::FILEOPEN_LINK_PREVIEW_IMAGE_ANCHOR);
294 Reference<ui::dialogs::XFilePickerControlAccess> xCtrlAcc = aDlg.GetFilePickerControlAccess();
295 sal_Int16 nSelect = 0;
296 Sequence<OUString> aListBoxEntries {
297 ScResId(STR_ANCHOR_TO_CELL),
298 ScResId(STR_ANCHOR_TO_CELL_RESIZE),
299 ScResId(STR_ANCHOR_TO_PAGE)
303 Any aTemplates(&aListBoxEntries, cppu::UnoType<decltype(aListBoxEntries)>::get());
305 xCtrlAcc->setValue(ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
306 ui::dialogs::ListboxControlActions::ADD_ITEMS, aTemplates);
308 Any aSelectPos(&nSelect, cppu::UnoType<decltype(nSelect)>::get());
309 xCtrlAcc->setValue(ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
310 ui::dialogs::ListboxControlActions::SET_SELECT_ITEM, aSelectPos);
312 catch (const Exception&)
314 SAL_WARN("sc", "control access failed");
317 if( aDlg.Execute() == ERRCODE_NONE )
319 Graphic aGraphic;
320 ErrCode nError = aDlg.GetGraphic(aGraphic);
321 if( nError == ERRCODE_NONE )
323 OUString aFileName = aDlg.GetPath();
324 const OUString& aFilterName = aDlg.GetDetectedFilter();
325 bool bAsLink = aDlg.IsAsLink();
327 // really store as link only?
328 if( bAsLink && SvtMiscOptions().ShowLinkWarningDialog() )
330 SvxLinkWarningDialog aWarnDlg(pWin ? pWin->GetFrameWeld() : nullptr, aFileName);
331 if (aWarnDlg.run() != RET_OK)
332 bAsLink = false; // don't store as link
335 // Anchor to cell or to page?
336 Any aAnchorValue = xCtrlAcc->getValue(
337 ui::dialogs::ExtendedFilePickerElementIds::LISTBOX_IMAGE_ANCHOR,
338 ui::dialogs::ListboxControlActions::GET_SELECTED_ITEM );
339 OUString sAnchor;
340 aAnchorValue >>= sAnchor;
342 ScAnchorType aAnchorType;
343 if (sAnchor == ScResId(STR_ANCHOR_TO_CELL))
344 aAnchorType = SCA_CELL;
345 else if (sAnchor == ScResId(STR_ANCHOR_TO_CELL_RESIZE))
346 aAnchorType = SCA_CELL_RESIZE;
347 else if (sAnchor == ScResId(STR_ANCHOR_TO_PAGE))
348 aAnchorType = SCA_PAGE;
349 else
350 aAnchorType = SCA_DONTKNOW;
352 lcl_InsertGraphic( aGraphic, aFileName, aFilterName, bAsLink, false, rViewSh, pWindow, pView, aAnchorType );
354 // append items for recording
355 rReq.AppendItem( SfxStringItem( SID_INSERT_GRAPHIC, aFileName ) );
356 rReq.AppendItem( SfxStringItem( FN_PARAM_FILTER, aFilterName ) );
357 rReq.AppendItem( SfxBoolItem( FN_PARAM_1, bAsLink ) );
358 rReq.Done();
360 else
362 // error is handled in SvxOpenGraphicDialog::GetGraphic
368 FuInsertGraphic::~FuInsertGraphic()
372 FuInsertMedia::FuInsertMedia( ScTabViewShell& rViewSh,
373 vcl::Window* pWin,
374 ScDrawView* pViewP,
375 SdrModel* pDoc,
376 const SfxRequest& rReq ) :
377 FuPoor(rViewSh, pWin, pViewP, pDoc, rReq)
379 OUString aURL;
380 const SfxItemSet* pReqArgs = rReq.GetArgs();
381 bool bAPI = false;
383 if( pReqArgs )
385 const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>( &pReqArgs->Get( rReq.GetSlot() ) );
387 if( pStringItem )
389 aURL = pStringItem->GetValue();
390 bAPI = aURL.getLength();
394 bool bLink(true);
395 if (bAPI
396 #if HAVE_FEATURE_AVMEDIA
397 || ::avmedia::MediaWindow::executeMediaURLDialog(pWin ? pWin->GetFrameWeld() : nullptr, aURL, &bLink)
398 #endif
401 Size aPrefSize;
403 if( pWin )
404 pWin->EnterWait();
406 #if HAVE_FEATURE_AVMEDIA
407 if( !::avmedia::MediaWindow::isMediaURL( aURL, ""/*TODO?*/, true, &aPrefSize ) )
409 if( pWin )
410 pWin->LeaveWait();
412 if( !bAPI )
413 ::avmedia::MediaWindow::executeFormatErrorBox(pWindow ? pWindow->GetFrameWeld() : nullptr);
415 else
416 #endif
418 lcl_InsertMedia( aURL, bAPI, &rViewSh, pWindow, pView, aPrefSize,
419 bLink );
421 if( pWin )
422 pWin->LeaveWait();
427 FuInsertMedia::~FuInsertMedia()
431 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */