1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 */
9
10 #include <memory>
11 #include "uiobject_uno.hxx"
12 #include <utility>
13 #include <cppuhelper/supportsservice.hxx>
14 #include <vcl/svapp.hxx>
15 #include <vcl/idle.hxx>
16
17 #include <set>
18
UIObjectUnoObj(std::unique_ptr<UIObject> pObj)19 UIObjectUnoObj::UIObjectUnoObj(std::unique_ptr<UIObject> pObj):
20 UIObjectBase(m_aMutex),
21 mpObj(std::move(pObj)),
22 mReady(true)
23 {
24 }
25
~UIObjectUnoObj()26 UIObjectUnoObj::~UIObjectUnoObj()
27 {
28 {
29 std::scoped_lock<std::mutex> lk3(mMutex);
30 }
31 SolarMutexGuard aGuard;
32 mpObj.reset();
33 }
34
getChild(const OUString & rID)35 css::uno::Reference<css::ui::test::XUIObject> SAL_CALL UIObjectUnoObj::getChild(const OUString& rID)
36 {
37 if (!mpObj)
38 throw css::uno::RuntimeException();
39
40 SolarMutexGuard aGuard;
41 std::unique_ptr<UIObject> pObj = mpObj->get_child(rID);
42 return new UIObjectUnoObj(std::move(pObj));
43 }
44
IMPL_LINK_NOARG(UIObjectUnoObj,NotifyHdl,Timer *,void)45 IMPL_LINK_NOARG(UIObjectUnoObj, NotifyHdl, Timer*, void)
46 {
47 std::scoped_lock<std::mutex> lk(mMutex);
48 mReady = true;
49 cv.notify_all();
50 }
51
52 namespace {
53
54 class ExecuteWrapper
55 {
56 std::function<void()> const mFunc;
57 Link<Timer*, void> const mHandler;
58 volatile bool mbSignal;
59
60 public:
61
ExecuteWrapper(std::function<void ()> func,Link<Timer *,void> handler)62 ExecuteWrapper(std::function<void()> func, Link<Timer*, void> handler):
63 mFunc(std::move(func)),
64 mHandler(handler),
65 mbSignal(false)
66 {
67 }
68
setSignal()69 void setSignal()
70 {
71 mbSignal = true;
72 }
73
74 DECL_LINK( ExecuteActionHdl, Timer*, void );
75 };
76
77
IMPL_LINK_NOARG(ExecuteWrapper,ExecuteActionHdl,Timer *,void)78 IMPL_LINK_NOARG(ExecuteWrapper, ExecuteActionHdl, Timer*, void)
79 {
80 {
81 Idle aIdle;
82 {
83 mFunc();
84 aIdle.SetDebugName("UI Test Idle Handler2");
85 aIdle.SetPriority(TaskPriority::LOWEST);
86 aIdle.SetInvokeHandler(mHandler);
87 aIdle.Start();
88 }
89
90 while (!mbSignal) {
91 Application::Reschedule();
92 }
93 }
94 delete this;
95 }
96
97 }
98
executeAction(const OUString & rAction,const css::uno::Sequence<css::beans::PropertyValue> & rPropValues)99 void SAL_CALL UIObjectUnoObj::executeAction(const OUString& rAction, const css::uno::Sequence<css::beans::PropertyValue>& rPropValues)
100 {
101 if (!mpObj)
102 throw css::uno::RuntimeException();
103
104 std::unique_lock<std::mutex> lk(mMutex);
105 mAction = rAction;
106 mPropValues = rPropValues;
107 mReady = false;
108 auto aIdle = std::make_unique<Idle>();
109 aIdle->SetDebugName("UI Test Idle Handler");
110 aIdle->SetPriority(TaskPriority::HIGHEST);
111
112 std::function<void()> func = [this](){
113
114 SolarMutexGuard aGuard;
115 StringMap aMap;
116 for (const auto& rPropVal : std::as_const(mPropValues))
117 {
118 OUString aVal;
119 if (!(rPropVal.Value >>= aVal))
120 continue;
121
122 aMap[rPropVal.Name] = aVal;
123 }
124 mpObj->execute(mAction, aMap);
125 };
126
127 ExecuteWrapper* pWrapper = new ExecuteWrapper(func, LINK(this, UIObjectUnoObj, NotifyHdl));
128 aIdle->SetInvokeHandler(LINK(pWrapper, ExecuteWrapper, ExecuteActionHdl));
129 {
130 SolarMutexGuard aGuard;
131 aIdle->Start();
132 }
133
134 cv.wait(lk, [this]{return mReady;});
135 pWrapper->setSignal();
136
137 SolarMutexGuard aGuard;
138 aIdle.reset();
139 }
140
getState()141 css::uno::Sequence<css::beans::PropertyValue> UIObjectUnoObj::getState()
142 {
143 if (!mpObj)
144 throw css::uno::RuntimeException();
145
146 SolarMutexGuard aGuard;
147 StringMap aMap = mpObj->get_state();
148 css::uno::Sequence<css::beans::PropertyValue> aProps(aMap.size());
149 sal_Int32 i = 0;
150 for (auto const& elem : aMap)
151 {
152 aProps[i].Name = elem.first;
153 aProps[i].Value <<= elem.second;
154 ++i;
155 }
156
157 return aProps;
158 }
159
getChildren()160 css::uno::Sequence<OUString> UIObjectUnoObj::getChildren()
161 {
162 if (!mpObj)
163 throw css::uno::RuntimeException();
164
165 std::set<OUString> aChildren = mpObj->get_children();
166
167 css::uno::Sequence<OUString> aRet(aChildren.size());
168 sal_Int32 i = 0;
169 for (auto const& child : aChildren)
170 {
171 aRet[i] = child;
172 ++i;
173 }
174
175 return aRet;
176 }
177
getType()178 OUString SAL_CALL UIObjectUnoObj::getType()
179 {
180 if (!mpObj)
181 throw css::uno::RuntimeException();
182
183 return mpObj->get_type();
184 }
185
getImplementationName()186 OUString SAL_CALL UIObjectUnoObj::getImplementationName()
187 {
188 return "org.libreoffice.uitest.UIObject";
189 }
190
supportsService(OUString const & ServiceName)191 sal_Bool UIObjectUnoObj::supportsService(OUString const & ServiceName)
192 {
193 return cppu::supportsService(this, ServiceName);
194 }
195
getSupportedServiceNames()196 css::uno::Sequence<OUString> UIObjectUnoObj::getSupportedServiceNames()
197 {
198 return { "com.sun.star.ui.test.UIObject" };
199 }
200
getHierarchy()201 OUString SAL_CALL UIObjectUnoObj::getHierarchy()
202 {
203 if (!mpObj)
204 throw css::uno::RuntimeException();
205
206 SolarMutexGuard aGuard;
207 return mpObj->dumpHierarchy();
208 }
209
210 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
211