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 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <extended/AccessibleBrowseBox.hxx>
21 #include <extended/AccessibleBrowseBoxTable.hxx>
22 #include <extended/AccessibleBrowseBoxHeaderBar.hxx>
23 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
24 #include <vcl/accessibletableprovider.hxx>
25 #include <toolkit/helper/convert.hxx>
26 #include <toolkit/helper/vclunohelper.hxx>
27 #include <sal/types.h>
28
29
30 namespace accessibility
31 {
32
33 using namespace ::com::sun::star::uno;
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::lang;
36 using namespace ::com::sun::star::accessibility;
37
38 // Ctor/Dtor/disposing
39
AccessibleBrowseBox(const css::uno::Reference<css::accessibility::XAccessible> & _rxParent,const css::uno::Reference<css::accessibility::XAccessible> & _rxCreator,::vcl::IAccessibleTableProvider & _rBrowseBox)40 AccessibleBrowseBox::AccessibleBrowseBox(
41 const css::uno::Reference< css::accessibility::XAccessible >& _rxParent, const css::uno::Reference< css::accessibility::XAccessible >& _rxCreator,
42 ::vcl::IAccessibleTableProvider& _rBrowseBox )
43 : AccessibleBrowseBoxBase( _rxParent, _rBrowseBox,nullptr, vcl::BBTYPE_BROWSEBOX ),
44 m_aCreator(_rxCreator)
45 {
46 m_xFocusWindow = VCLUnoHelper::GetInterface(mpBrowseBox->GetWindowInstance());
47 }
48
setCreator(const css::uno::Reference<css::accessibility::XAccessible> & _rxCreator)49 void AccessibleBrowseBox::setCreator( const css::uno::Reference< css::accessibility::XAccessible >& _rxCreator )
50 {
51 #if OSL_DEBUG_LEVEL > 0
52 css::uno::Reference< css::accessibility::XAccessible > xCreator(m_aCreator);
53 OSL_ENSURE( !xCreator.is(), "extended/AccessibleBrowseBox::setCreator: creator already set!" );
54 #endif
55 m_aCreator = _rxCreator;
56 }
57
58
~AccessibleBrowseBox()59 AccessibleBrowseBox::~AccessibleBrowseBox()
60 {
61 }
62
63
disposing()64 void SAL_CALL AccessibleBrowseBox::disposing()
65 {
66 ::osl::MutexGuard aGuard( getMutex() );
67
68 m_aCreator.clear();
69
70 if ( mxTable.is() )
71 {
72 mxTable->dispose();
73 mxTable.clear();
74 }
75 if ( mxRowHeaderBar.is() )
76 {
77 mxRowHeaderBar->dispose();
78 mxRowHeaderBar.clear();
79 }
80 if ( mxColumnHeaderBar.is() )
81 {
82 mxColumnHeaderBar->dispose();
83 mxColumnHeaderBar.clear();
84 }
85
86 AccessibleBrowseBoxBase::disposing();
87 }
88
89
90 // css::accessibility::XAccessibleContext
91
getAccessibleChildCount()92 sal_Int32 SAL_CALL AccessibleBrowseBox::getAccessibleChildCount()
93 {
94 SolarMethodGuard aGuard(getMutex());
95 ensureIsAlive();
96
97 return vcl::BBINDEX_FIRSTCONTROL + mpBrowseBox->GetAccessibleControlCount();
98 }
99
100
101 css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
getAccessibleChild(sal_Int32 nChildIndex)102 AccessibleBrowseBox::getAccessibleChild( sal_Int32 nChildIndex )
103 {
104 SolarMethodGuard aGuard(getMutex());
105 ensureIsAlive();
106
107 css::uno::Reference< css::accessibility::XAccessible > xRet;
108 if( nChildIndex >= 0 )
109 {
110 if( nChildIndex < vcl::BBINDEX_FIRSTCONTROL )
111 xRet = implGetFixedChild( nChildIndex );
112 else
113 {
114 // additional controls
115 nChildIndex -= vcl::BBINDEX_FIRSTCONTROL;
116 if( nChildIndex < mpBrowseBox->GetAccessibleControlCount() )
117 xRet = mpBrowseBox->CreateAccessibleControl( nChildIndex );
118 }
119 }
120
121 if( !xRet.is() )
122 throw lang::IndexOutOfBoundsException();
123 return xRet;
124 }
125
126 // css::accessibility::XAccessibleComponent
127
128 css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
getAccessibleAtPoint(const awt::Point & rPoint)129 AccessibleBrowseBox::getAccessibleAtPoint( const awt::Point& rPoint )
130 {
131 SolarMethodGuard aGuard(getMutex());
132 ensureIsAlive();
133
134 css::uno::Reference< css::accessibility::XAccessible > xChild;
135 sal_Int32 nIndex = 0;
136 if( mpBrowseBox->ConvertPointToControlIndex( nIndex, VCLPoint( rPoint ) ) )
137 xChild = mpBrowseBox->CreateAccessibleControl( nIndex );
138 else
139 {
140 // try whether point is in one of the fixed children
141 // (table, header bars, corner control)
142 Point aPoint( VCLPoint( rPoint ) );
143 for( nIndex = 0; (nIndex < vcl::BBINDEX_FIRSTCONTROL) && !xChild.is(); ++nIndex )
144 {
145 css::uno::Reference< css::accessibility::XAccessible > xCurrChild( implGetFixedChild( nIndex ) );
146 css::uno::Reference< css::accessibility::XAccessibleComponent >
147 xCurrChildComp( xCurrChild, uno::UNO_QUERY );
148
149 if( xCurrChildComp.is() &&
150 VCLRectangle( xCurrChildComp->getBounds() ).IsInside( aPoint ) )
151 xChild = xCurrChild;
152 }
153 }
154 return xChild;
155 }
156
157
grabFocus()158 void SAL_CALL AccessibleBrowseBox::grabFocus()
159 {
160 SolarMethodGuard aGuard(getMutex());
161 ensureIsAlive();
162
163 mpBrowseBox->GrabFocus();
164 }
165
166 // XServiceInfo
167
getImplementationName()168 OUString SAL_CALL AccessibleBrowseBox::getImplementationName()
169 {
170 return "com.sun.star.comp.svtools.AccessibleBrowseBox";
171 }
172
173
174 // internal virtual methods
175
implGetBoundingBox()176 tools::Rectangle AccessibleBrowseBox::implGetBoundingBox()
177 {
178 vcl::Window* pParent = mpBrowseBox->GetAccessibleParentWindow();
179 OSL_ENSURE( pParent, "implGetBoundingBox - missing parent window" );
180 return mpBrowseBox->GetWindowExtentsRelative( pParent );
181 }
182
183
implGetBoundingBoxOnScreen()184 tools::Rectangle AccessibleBrowseBox::implGetBoundingBoxOnScreen()
185 {
186 return mpBrowseBox->GetWindowExtentsRelative( nullptr );
187 }
188
189 // internal helper methods
implGetTable()190 css::uno::Reference< css::accessibility::XAccessible > AccessibleBrowseBox::implGetTable()
191 {
192 if( !mxTable.is() )
193 {
194 mxTable = createAccessibleTable();
195
196 }
197 return mxTable;
198 }
199
200 css::uno::Reference< css::accessibility::XAccessible >
implGetHeaderBar(vcl::AccessibleBrowseBoxObjType eObjType)201 AccessibleBrowseBox::implGetHeaderBar(vcl::AccessibleBrowseBoxObjType eObjType)
202 {
203 css::uno::Reference< css::accessibility::XAccessible > xRet;
204 rtl::Reference< AccessibleBrowseBoxHeaderBar >* pxMember = nullptr;
205
206 if( eObjType == vcl::BBTYPE_ROWHEADERBAR )
207 pxMember = &mxRowHeaderBar;
208 else if( eObjType == vcl::BBTYPE_COLUMNHEADERBAR )
209 pxMember = &mxColumnHeaderBar;
210
211 if( pxMember )
212 {
213 if( !pxMember->is() )
214 {
215 rtl::Reference<AccessibleBrowseBoxHeaderBar> pHeaderBar = new AccessibleBrowseBoxHeaderBar(
216 m_aCreator, *mpBrowseBox, eObjType );
217 *pxMember = pHeaderBar;
218 }
219 xRet = pxMember->get();
220 }
221 return xRet;
222 }
223
224 css::uno::Reference< css::accessibility::XAccessible >
implGetFixedChild(sal_Int32 nChildIndex)225 AccessibleBrowseBox::implGetFixedChild( sal_Int32 nChildIndex )
226 {
227 css::uno::Reference< css::accessibility::XAccessible > xRet;
228 switch( nChildIndex )
229 {
230 case vcl::BBINDEX_COLUMNHEADERBAR:
231 xRet = implGetHeaderBar( vcl::BBTYPE_COLUMNHEADERBAR );
232 break;
233 case vcl::BBINDEX_ROWHEADERBAR:
234 xRet = implGetHeaderBar( vcl::BBTYPE_ROWHEADERBAR );
235 break;
236 case vcl::BBINDEX_TABLE:
237 xRet = implGetTable();
238 break;
239 }
240 return xRet;
241 }
242
createAccessibleTable()243 rtl::Reference<AccessibleBrowseBoxTable> AccessibleBrowseBox::createAccessibleTable()
244 {
245 css::uno::Reference< css::accessibility::XAccessible > xCreator(m_aCreator);
246 OSL_ENSURE( xCreator.is(), "extended/AccessibleBrowseBox::createAccessibleTable: my creator died - how this?" );
247 return new AccessibleBrowseBoxTable( xCreator, *mpBrowseBox );
248 }
249
commitTableEvent(sal_Int16 _nEventId,const Any & _rNewValue,const Any & _rOldValue)250 void AccessibleBrowseBox::commitTableEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue)
251 {
252 if ( mxTable.is() )
253 {
254 mxTable->commitEvent(_nEventId,_rNewValue,_rOldValue);
255 }
256 }
257
commitHeaderBarEvent(sal_Int16 _nEventId,const Any & _rNewValue,const Any & _rOldValue,bool _bColumnHeaderBar)258 void AccessibleBrowseBox::commitHeaderBarEvent( sal_Int16 _nEventId,
259 const Any& _rNewValue,
260 const Any& _rOldValue,bool _bColumnHeaderBar)
261 {
262 rtl::Reference< AccessibleBrowseBoxHeaderBar >& xHeaderBar = _bColumnHeaderBar ? mxColumnHeaderBar : mxRowHeaderBar;
263 if ( xHeaderBar.is() )
264 xHeaderBar->commitEvent(_nEventId,_rNewValue,_rOldValue);
265 }
266
267
268 // = AccessibleBrowseBoxAccess
269
AccessibleBrowseBoxAccess(const css::uno::Reference<css::accessibility::XAccessible> & _rxParent,::vcl::IAccessibleTableProvider & _rBrowseBox)270 AccessibleBrowseBoxAccess::AccessibleBrowseBoxAccess( const css::uno::Reference< css::accessibility::XAccessible >& _rxParent, ::vcl::IAccessibleTableProvider& _rBrowseBox )
271 :m_xParent( _rxParent )
272 ,m_rBrowseBox( _rBrowseBox )
273 {
274 }
275
276
~AccessibleBrowseBoxAccess()277 AccessibleBrowseBoxAccess::~AccessibleBrowseBoxAccess()
278 {
279 }
280
281
dispose()282 void AccessibleBrowseBoxAccess::dispose()
283 {
284 ::osl::MutexGuard aGuard( m_aMutex );
285
286 if (m_xContext.is())
287 {
288 m_xContext->dispose();
289 m_xContext.clear();
290 }
291 }
292
293
getAccessibleContext()294 css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL AccessibleBrowseBoxAccess::getAccessibleContext()
295 {
296 ::osl::MutexGuard aGuard( m_aMutex );
297
298 // if the context died meanwhile (there is no listener, so it won't tell us explicitly when this happens),
299 // then reset and re-create.
300 if ( m_xContext.is() && !m_xContext->isAlive() )
301 m_xContext = nullptr;
302
303 if ( !m_xContext.is() )
304 m_xContext = new AccessibleBrowseBox( m_xParent, this, m_rBrowseBox );
305
306 return m_xContext;
307 }
308
309
310
311 } // namespace accessibility
312
313 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
314