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 <standard/accessiblemenucomponent.hxx>
21 
22 #include <toolkit/awt/vclxfont.hxx>
23 #include <toolkit/helper/convert.hxx>
24 
25 #include <com/sun/star/accessibility/AccessibleRole.hpp>
26 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
27 #include <com/sun/star/awt/XDevice.hpp>
28 #include <com/sun/star/awt/XWindowPeer.hpp>
29 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30 #include <unotools/accessiblestatesethelper.hxx>
31 #include <unotools/accessiblerelationsethelper.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/window.hxx>
34 #include <vcl/menu.hxx>
35 #include <vcl/settings.hxx>
36 #include <i18nlangtag/languagetag.hxx>
37 
38 using namespace ::com::sun::star::accessibility;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::lang;
41 using namespace ::com::sun::star;
42 using namespace ::comphelper;
43 
44 
45 
46 
IsEnabled()47 bool OAccessibleMenuComponent::IsEnabled()
48 {
49     return true;
50 }
51 
52 
IsVisible()53 bool OAccessibleMenuComponent::IsVisible()
54 {
55     bool bVisible = false;
56 
57     if ( m_pMenu )
58         bVisible = m_pMenu->IsMenuVisible();
59 
60     return bVisible;
61 }
62 
63 
FillAccessibleStateSet(utl::AccessibleStateSetHelper & rStateSet)64 void OAccessibleMenuComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
65 {
66     if ( IsEnabled() )
67     {
68         rStateSet.AddState( AccessibleStateType::ENABLED );
69         rStateSet.AddState( AccessibleStateType::SENSITIVE );
70     }
71 
72     rStateSet.AddState( AccessibleStateType::FOCUSABLE );
73 
74     if ( IsFocused() )
75         rStateSet.AddState( AccessibleStateType::FOCUSED );
76 
77     if ( IsVisible() )
78     {
79         rStateSet.AddState( AccessibleStateType::VISIBLE );
80         rStateSet.AddState( AccessibleStateType::SHOWING );
81     }
82 
83     rStateSet.AddState( AccessibleStateType::OPAQUE );
84 }
85 
86 
87 // OCommonAccessibleComponent
88 
89 
implGetBounds()90 awt::Rectangle OAccessibleMenuComponent::implGetBounds()
91 {
92     awt::Rectangle aBounds( 0, 0, 0, 0 );
93 
94     if ( m_pMenu )
95     {
96         vcl::Window* pWindow = m_pMenu->GetWindow();
97         if ( pWindow )
98         {
99             // get bounding rectangle of the window in screen coordinates
100             tools::Rectangle aRect = pWindow->GetWindowExtentsRelative( nullptr );
101             aBounds = AWTRectangle( aRect );
102 
103             // get position of the accessible parent in screen coordinates
104             Reference< XAccessible > xParent = getAccessibleParent();
105             if ( xParent.is() )
106             {
107                 Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), UNO_QUERY );
108                 if ( xParentComponent.is() )
109                 {
110                     awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
111 
112                     // calculate position of the window relative to the accessible parent
113                     aBounds.X -= aParentScreenLoc.X;
114                     aBounds.Y -= aParentScreenLoc.Y;
115                 }
116             }
117         }
118     }
119 
120     return aBounds;
121 }
122 
123 
124 // XInterface
125 
126 
IMPLEMENT_FORWARD_XINTERFACE2(OAccessibleMenuComponent,OAccessibleMenuBaseComponent,OAccessibleMenuComponent_BASE)127 IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleMenuComponent, OAccessibleMenuBaseComponent, OAccessibleMenuComponent_BASE )
128 
129 
130 // XTypeProvider
131 
132 
133 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleMenuComponent, OAccessibleMenuBaseComponent, OAccessibleMenuComponent_BASE )
134 
135 
136 // XAccessibleContext
137 
138 
139 sal_Int32 OAccessibleMenuComponent::getAccessibleChildCount()
140 {
141     OExternalLockGuard aGuard( this );
142 
143     return GetChildCount();
144 }
145 
146 
getAccessibleChild(sal_Int32 i)147 Reference< XAccessible > OAccessibleMenuComponent::getAccessibleChild( sal_Int32 i )
148 {
149     OExternalLockGuard aGuard( this );
150 
151     if ( i < 0 || i >= GetChildCount() )
152         throw IndexOutOfBoundsException();
153 
154     return GetChild( i );
155 }
156 
157 
getAccessibleParent()158 Reference< XAccessible > OAccessibleMenuComponent::getAccessibleParent(  )
159 {
160     OExternalLockGuard aGuard( this );
161 
162     Reference< XAccessible > xParent;
163 
164     if ( m_pMenu )
165     {
166         vcl::Window* pWindow = m_pMenu->GetWindow();
167         if ( pWindow )
168         {
169             vcl::Window* pParent = pWindow->GetAccessibleParentWindow();
170             if ( pParent )
171                 xParent = pParent->GetAccessible();
172         }
173     }
174 
175     return xParent;
176 }
177 
178 
getAccessibleRole()179 sal_Int16 OAccessibleMenuComponent::getAccessibleRole(  )
180 {
181     OExternalLockGuard aGuard( this );
182 
183     return AccessibleRole::UNKNOWN;
184 }
185 
186 
getAccessibleDescription()187 OUString OAccessibleMenuComponent::getAccessibleDescription( )
188 {
189     OExternalLockGuard aGuard( this );
190 
191     OUString sDescription;
192     if ( m_pMenu )
193     {
194         vcl::Window* pWindow = m_pMenu->GetWindow();
195         if ( pWindow )
196             sDescription = pWindow->GetAccessibleDescription();
197     }
198 
199     return sDescription;
200 }
201 
202 
getAccessibleName()203 OUString OAccessibleMenuComponent::getAccessibleName(  )
204 {
205     OExternalLockGuard aGuard( this );
206 
207     return OUString();
208 }
209 
210 
getAccessibleRelationSet()211 Reference< XAccessibleRelationSet > OAccessibleMenuComponent::getAccessibleRelationSet(  )
212 {
213     OExternalLockGuard aGuard( this );
214 
215     return new utl::AccessibleRelationSetHelper;
216 }
217 
218 
getLocale()219 Locale OAccessibleMenuComponent::getLocale(  )
220 {
221     OExternalLockGuard aGuard( this );
222 
223     return Application::GetSettings().GetLanguageTag().getLocale();
224 }
225 
226 
227 // XAccessibleComponent
228 
229 
getAccessibleAtPoint(const awt::Point & rPoint)230 Reference< XAccessible > OAccessibleMenuComponent::getAccessibleAtPoint( const awt::Point& rPoint )
231 {
232     OExternalLockGuard aGuard( this );
233 
234     return GetChildAt( rPoint );
235 }
236 
237 
getLocationOnScreen()238 awt::Point OAccessibleMenuComponent::getLocationOnScreen(  )
239 {
240     OExternalLockGuard aGuard( this );
241 
242     awt::Point aPos;
243 
244     if ( m_pMenu )
245     {
246         vcl::Window* pWindow = m_pMenu->GetWindow();
247         if ( pWindow )
248         {
249             tools::Rectangle aRect = pWindow->GetWindowExtentsRelative( nullptr );
250             aPos = AWTPoint( aRect.TopLeft() );
251         }
252     }
253 
254     return aPos;
255 }
256 
257 
grabFocus()258 void OAccessibleMenuComponent::grabFocus(  )
259 {
260     OExternalLockGuard aGuard( this );
261 
262     if ( m_pMenu )
263     {
264         vcl::Window* pWindow = m_pMenu->GetWindow();
265         if ( pWindow )
266             pWindow->GrabFocus();
267     }
268 }
269 
270 
getForeground()271 sal_Int32 OAccessibleMenuComponent::getForeground(  )
272 {
273     OExternalLockGuard aGuard( this );
274 
275     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
276     Color nColor = rStyleSettings.GetMenuTextColor();
277 
278     return sal_Int32(nColor);
279 }
280 
281 
getBackground()282 sal_Int32 OAccessibleMenuComponent::getBackground(  )
283 {
284     OExternalLockGuard aGuard( this );
285 
286     return 0;
287 }
288 
289 
290 // XAccessibleExtendedComponent
291 
292 
getFont()293 Reference< awt::XFont > OAccessibleMenuComponent::getFont(  )
294 {
295     OExternalLockGuard aGuard( this );
296 
297     Reference< awt::XFont > xFont;
298 
299     if ( m_pMenu )
300     {
301         vcl::Window* pWindow = m_pMenu->GetWindow();
302         if ( pWindow )
303         {
304             Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), UNO_QUERY );
305             if ( xDev.is() )
306             {
307                 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
308                 rtl::Reference<VCLXFont> pVCLXFont = new VCLXFont;
309                 pVCLXFont->Init( *xDev, rStyleSettings.GetMenuFont() );
310                 xFont = pVCLXFont;
311             }
312         }
313     }
314 
315     return xFont;
316 }
317 
318 
getTitledBorderText()319 OUString OAccessibleMenuComponent::getTitledBorderText(  )
320 {
321     OExternalLockGuard aGuard( this );
322 
323     return OUString();
324 }
325 
326 
getToolTipText()327 OUString OAccessibleMenuComponent::getToolTipText(  )
328 {
329     OExternalLockGuard aGuard( this );
330 
331     return OUString();
332 }
333 
334 
335 // XAccessibleSelection
336 
337 
selectAccessibleChild(sal_Int32 nChildIndex)338 void OAccessibleMenuComponent::selectAccessibleChild( sal_Int32 nChildIndex )
339 {
340     OExternalLockGuard aGuard( this );
341 
342     if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
343         throw IndexOutOfBoundsException();
344 
345     SelectChild( nChildIndex );
346 }
347 
348 
isAccessibleChildSelected(sal_Int32 nChildIndex)349 sal_Bool OAccessibleMenuComponent::isAccessibleChildSelected( sal_Int32 nChildIndex )
350 {
351     OExternalLockGuard aGuard( this );
352 
353     if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
354         throw IndexOutOfBoundsException();
355 
356     return IsChildSelected( nChildIndex );
357 }
358 
359 
clearAccessibleSelection()360 void OAccessibleMenuComponent::clearAccessibleSelection(  )
361 {
362     OExternalLockGuard aGuard( this );
363 
364     DeSelectAll();
365 }
366 
367 
selectAllAccessibleChildren()368 void OAccessibleMenuComponent::selectAllAccessibleChildren(  )
369 {
370     // This method makes no sense in a menu, and so does nothing.
371 }
372 
373 
getSelectedAccessibleChildCount()374 sal_Int32 OAccessibleMenuComponent::getSelectedAccessibleChildCount(  )
375 {
376     OExternalLockGuard aGuard( this );
377 
378     sal_Int32 nRet = 0;
379 
380     for ( sal_Int32 i = 0, nCount = GetChildCount(); i < nCount; i++ )
381     {
382         if ( IsChildSelected( i ) )
383             ++nRet;
384     }
385 
386     return nRet;
387 }
388 
389 
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)390 Reference< XAccessible > OAccessibleMenuComponent::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
391 {
392     OExternalLockGuard aGuard( this );
393 
394     if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
395         throw IndexOutOfBoundsException();
396 
397     Reference< XAccessible > xChild;
398 
399     for ( sal_Int32 i = 0, j = 0, nCount = GetChildCount(); i < nCount; i++ )
400     {
401         if ( IsChildSelected( i ) && ( j++ == nSelectedChildIndex ) )
402         {
403             xChild = GetChild( i );
404             break;
405         }
406     }
407 
408     return xChild;
409 }
410 
411 
deselectAccessibleChild(sal_Int32 nChildIndex)412 void OAccessibleMenuComponent::deselectAccessibleChild( sal_Int32 nChildIndex )
413 {
414     OExternalLockGuard aGuard( this );
415 
416     if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
417         throw IndexOutOfBoundsException();
418 
419     DeSelectAll();
420 }
421 
422 
423 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
424