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/.
10 #include <swmodeltestbase.hxx>
12 #include <com/sun/star/text/XTextDocument.hpp>
14 #include <vcl/event.hxx>
19 #include <frameformats.hxx>
25 /// Covers sw/source/uibase/docvw/ fixes.
26 class Test
: public SwModelTestBase
31 CPPUNIT_TEST_FIXTURE(Test
, testShiftClickOnImage
)
33 // Given a document with a fly frame:
35 SwDoc
* pDoc
= getSwDoc();
36 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
37 uno::Reference
<lang::XMultiServiceFactory
> xMSF(mxComponent
, uno::UNO_QUERY
);
38 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
39 uno::Reference
<text::XText
> xText
= xTextDocument
->getText();
40 uno::Reference
<text::XTextCursor
> xCursor
= xText
->createTextCursor();
41 uno::Reference
<beans::XPropertySet
> xTextGraphic(
42 xMSF
->createInstance(u
"com.sun.star.text.TextGraphicObject"_ustr
), uno::UNO_QUERY
);
43 xTextGraphic
->setPropertyValue(u
"AnchorType"_ustr
,
44 uno::Any(text::TextContentAnchorType_AS_CHARACTER
));
45 xTextGraphic
->setPropertyValue(u
"Size"_ustr
, uno::Any(awt::Size(5000, 5000)));
46 uno::Reference
<text::XTextContent
> xTextContent(xTextGraphic
, uno::UNO_QUERY
);
47 xText
->insertTextContent(xCursor
, xTextContent
, false);
48 pWrtShell
->SttEndDoc(/*bStt=*/false);
50 // When shift-clicking on that fly frame:
51 auto& rSpzFormats
= *pDoc
->GetSpzFrameFormats();
52 auto pFrameFormat
= dynamic_cast<SwFlyFrameFormat
*>(rSpzFormats
[0]);
53 CPPUNIT_ASSERT(pFrameFormat
);
54 SwFlyFrame
* pFlyFrame
= pFrameFormat
->GetFrame();
55 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
56 Point aFlyCenter
= rEditWin
.LogicToPixel(pFlyFrame
->getFrameArea().Center());
57 MouseEvent
aClickEvent(aFlyCenter
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
, KEY_SHIFT
);
58 rEditWin
.MouseButtonDown(aClickEvent
);
59 rEditWin
.MouseButtonUp(aClickEvent
);
61 // Then make sure that the fly frame is selected:
62 SelectionType eType
= pWrtShell
->GetSelectionType();
63 // Without the accompanying fix in place, this test would have failed with:
64 // - Expected: 2 (SelectionType::Graphic)
65 // - Actual : 1 (SelectionType::Text)
66 // i.e. the fly frame was not selected, while a plain click or ctrl-click selected it.
67 CPPUNIT_ASSERT_EQUAL(SelectionType::Graphic
, eType
);
72 /// Interception implementation that catches the graphic dialog.
73 class GraphicDialogInterceptor
: public cppu::WeakImplHelper
<frame::XDispatchProviderInterceptor
>
75 uno::Reference
<frame::XDispatchProvider
> m_xMaster
;
76 uno::Reference
<frame::XDispatchProvider
> m_xSlave
;
77 int m_nGraphicDialogs
= 0;
80 // XDispatchProviderInterceptor
81 uno::Reference
<frame::XDispatchProvider
> SAL_CALL
getMasterDispatchProvider() override
;
82 uno::Reference
<frame::XDispatchProvider
> SAL_CALL
getSlaveDispatchProvider() override
;
83 void SAL_CALL
setMasterDispatchProvider(
84 const uno::Reference
<frame::XDispatchProvider
>& xNewSupplier
) override
;
86 setSlaveDispatchProvider(const uno::Reference
<frame::XDispatchProvider
>& xNewSupplier
) override
;
89 uno::Reference
<frame::XDispatch
> SAL_CALL
queryDispatch(const util::URL
& rURL
,
90 const OUString
& rTargetFrameName
,
91 sal_Int32 SearchFlags
) override
;
92 uno::Sequence
<uno::Reference
<frame::XDispatch
>> SAL_CALL
93 queryDispatches(const uno::Sequence
<frame::DispatchDescriptor
>& rRequests
) override
;
95 int GetGraphicDialogs() const;
99 uno::Reference
<frame::XDispatchProvider
> GraphicDialogInterceptor::getMasterDispatchProvider()
104 uno::Reference
<frame::XDispatchProvider
> GraphicDialogInterceptor::getSlaveDispatchProvider()
109 void GraphicDialogInterceptor::setMasterDispatchProvider(
110 const uno::Reference
<frame::XDispatchProvider
>& xNewSupplier
)
112 m_xMaster
= xNewSupplier
;
115 void GraphicDialogInterceptor::setSlaveDispatchProvider(
116 const uno::Reference
<frame::XDispatchProvider
>& xNewSupplier
)
118 m_xSlave
= xNewSupplier
;
121 uno::Reference
<frame::XDispatch
>
122 GraphicDialogInterceptor::queryDispatch(const util::URL
& rURL
, const OUString
& rTargetFrameName
,
123 sal_Int32 nSearchFlags
)
125 if (rURL
.Complete
== ".uno:GraphicDialog")
130 return m_xSlave
->queryDispatch(rURL
, rTargetFrameName
, nSearchFlags
);
133 uno::Sequence
<uno::Reference
<frame::XDispatch
>> GraphicDialogInterceptor::queryDispatches(
134 const uno::Sequence
<frame::DispatchDescriptor
>& /*rRequests*/)
139 int GraphicDialogInterceptor::GetGraphicDialogs() const { return m_nGraphicDialogs
; }
141 CPPUNIT_TEST_FIXTURE(Test
, testShiftDoubleClickOnImage
)
143 // Given a document with a fly frame, and an interceptor to catch the graphic dialog:
145 SwDoc
* pDoc
= getSwDoc();
146 SwWrtShell
* pWrtShell
= getSwDocShell()->GetWrtShell();
147 uno::Reference
<lang::XMultiServiceFactory
> xMSF(mxComponent
, uno::UNO_QUERY
);
148 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
149 uno::Reference
<text::XText
> xText
= xTextDocument
->getText();
150 uno::Reference
<text::XTextCursor
> xCursor
= xText
->createTextCursor();
151 uno::Reference
<beans::XPropertySet
> xTextGraphic(
152 xMSF
->createInstance(u
"com.sun.star.text.TextGraphicObject"_ustr
), uno::UNO_QUERY
);
153 xTextGraphic
->setPropertyValue(u
"AnchorType"_ustr
,
154 uno::Any(text::TextContentAnchorType_AS_CHARACTER
));
155 xTextGraphic
->setPropertyValue(u
"Size"_ustr
, uno::Any(awt::Size(5000, 5000)));
156 uno::Reference
<text::XTextContent
> xTextContent(xTextGraphic
, uno::UNO_QUERY
);
157 xText
->insertTextContent(xCursor
, xTextContent
, false);
158 pWrtShell
->SttEndDoc(/*bStt=*/false);
159 uno::Reference
<frame::XModel
> xModel(mxComponent
, uno::UNO_QUERY
);
160 uno::Reference
<frame::XDispatchProviderInterception
> xRegistration(
161 xModel
->getCurrentController()->getFrame(), uno::UNO_QUERY
);
162 rtl::Reference
pInterceptor(new GraphicDialogInterceptor
);
163 xRegistration
->registerDispatchProviderInterceptor(pInterceptor
);
165 // When shift-double-clicking on that fly frame:
166 auto& rSpzFormats
= *pDoc
->GetSpzFrameFormats();
167 auto pFrameFormat
= dynamic_cast<SwFlyFrameFormat
*>(rSpzFormats
[0]);
168 CPPUNIT_ASSERT(pFrameFormat
);
169 SwFlyFrame
* pFlyFrame
= pFrameFormat
->GetFrame();
170 vcl::Window
& rEditWin
= getSwDocShell()->GetView()->GetEditWin();
171 Point aFlyCenter
= rEditWin
.LogicToPixel(pFlyFrame
->getFrameArea().Center());
172 MouseEvent
aClickEvent(aFlyCenter
, 1, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
, KEY_SHIFT
);
173 rEditWin
.MouseButtonDown(aClickEvent
);
174 rEditWin
.MouseButtonUp(aClickEvent
);
176 = MouseEvent(aFlyCenter
, 2, MouseEventModifiers::SIMPLECLICK
, MOUSE_LEFT
, KEY_SHIFT
);
177 rEditWin
.MouseButtonDown(aClickEvent
);
178 rEditWin
.MouseButtonUp(aClickEvent
);
180 // Then make sure that the fly frame's dialog is dispatched:
181 int nGraphicDialogs
= pInterceptor
->GetGraphicDialogs();
182 // Without the accompanying fix in place, this test would have failed with:
183 // - Expected greater than: 0 (2)
185 // i.e. the fly frame's dialog was not dispatched, while a plain click or ctrl-click dispatched
187 CPPUNIT_ASSERT_GREATER(0, nGraphicDialogs
);
190 CPPUNIT_PLUGIN_IMPLEMENT();
192 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */