1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_accessibility.hxx"
30 #include <accessibility/standard/accessiblemenucomponent.hxx>
31 
32 #include <toolkit/awt/vclxfont.hxx>
33 #include <toolkit/helper/convert.hxx>
34 
35 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
36 #include <com/sun/star/accessibility/AccessibleRole.hpp>
37 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
38 
39 #include <unotools/accessiblestatesethelper.hxx>
40 #include <unotools/accessiblerelationsethelper.hxx>
41 #include <cppuhelper/typeprovider.hxx>
42 #include <comphelper/sequence.hxx>
43 #include <vcl/svapp.hxx>
44 #include <vcl/window.hxx>
45 #include <vcl/menu.hxx>
46 #include <vcl/unohelp2.hxx>
47 
48 
49 using namespace ::com::sun::star::accessibility;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::lang;
52 using namespace ::com::sun::star;
53 using namespace ::comphelper;
54 
55 
56 // -----------------------------------------------------------------------------
57 // class OAccessibleMenuComponent
58 // -----------------------------------------------------------------------------
59 
60 OAccessibleMenuComponent::OAccessibleMenuComponent( Menu* pMenu )
61 	:OAccessibleMenuBaseComponent( pMenu )
62 {
63 }
64 
65 // -----------------------------------------------------------------------------
66 
67 OAccessibleMenuComponent::~OAccessibleMenuComponent()
68 {
69 }
70 
71 // -----------------------------------------------------------------------------
72 
73 sal_Bool OAccessibleMenuComponent::IsEnabled()
74 {
75 	return sal_True;
76 }
77 
78 // -----------------------------------------------------------------------------
79 
80 sal_Bool OAccessibleMenuComponent::IsVisible()
81 {
82     sal_Bool bVisible = sal_False;
83 
84 	if ( m_pMenu )
85         bVisible = m_pMenu->IsMenuVisible();
86 
87     return bVisible;
88 }
89 
90 // -----------------------------------------------------------------------------
91 
92 void OAccessibleMenuComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
93 {
94 	if ( IsEnabled() )
95     {
96         rStateSet.AddState( AccessibleStateType::ENABLED );
97         rStateSet.AddState( AccessibleStateType::SENSITIVE );
98     }
99 
100 	rStateSet.AddState( AccessibleStateType::FOCUSABLE );
101 
102 	if ( IsFocused() )
103 		rStateSet.AddState( AccessibleStateType::FOCUSED );
104 
105     if ( IsVisible() )
106     {
107         rStateSet.AddState( AccessibleStateType::VISIBLE );
108         rStateSet.AddState( AccessibleStateType::SHOWING );
109     }
110 
111     rStateSet.AddState( AccessibleStateType::OPAQUE );
112 }
113 
114 // -----------------------------------------------------------------------------
115 // OCommonAccessibleComponent
116 // -----------------------------------------------------------------------------
117 
118 awt::Rectangle OAccessibleMenuComponent::implGetBounds() throw (RuntimeException)
119 {
120 	awt::Rectangle aBounds( 0, 0, 0, 0 );
121 
122 	if ( m_pMenu )
123 	{
124 		Window* pWindow = m_pMenu->GetWindow();
125 		if ( pWindow )
126 		{
127 			// get bounding rectangle of the window in screen coordinates
128 			Rectangle aRect = pWindow->GetWindowExtentsRelative( NULL );
129 			aBounds = AWTRectangle( aRect );
130 
131 			// get position of the accessible parent in screen coordinates
132 			Reference< XAccessible > xParent = getAccessibleParent();
133 			if ( xParent.is() )
134 			{
135 				Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), UNO_QUERY );
136 				if ( xParentComponent.is() )
137 				{
138 					awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
139 
140 					// calculate position of the window relative to the accessible parent
141 					aBounds.X -= aParentScreenLoc.X;
142 					aBounds.Y -= aParentScreenLoc.Y;
143 				}
144 			}
145 		}
146 	}
147 
148 	return aBounds;
149 }
150 
151 // -----------------------------------------------------------------------------
152 // XInterface
153 // -----------------------------------------------------------------------------
154 
155 IMPLEMENT_FORWARD_XINTERFACE2( OAccessibleMenuComponent, OAccessibleMenuBaseComponent, OAccessibleMenuComponent_BASE )
156 
157 // -----------------------------------------------------------------------------
158 // XTypeProvider
159 // -----------------------------------------------------------------------------
160 
161 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OAccessibleMenuComponent, OAccessibleMenuBaseComponent, OAccessibleMenuComponent_BASE )
162 
163 // -----------------------------------------------------------------------------
164 // XAccessibleContext
165 // -----------------------------------------------------------------------------
166 
167 sal_Int32 OAccessibleMenuComponent::getAccessibleChildCount() throw (RuntimeException)
168 {
169 	OExternalLockGuard aGuard( this );
170 
171 	return GetChildCount();
172 }
173 
174 // -----------------------------------------------------------------------------
175 
176 Reference< XAccessible > OAccessibleMenuComponent::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
177 {
178 	OExternalLockGuard aGuard( this );
179 
180 	if ( i < 0 || i >= GetChildCount() )
181 		throw IndexOutOfBoundsException();
182 
183 	return GetChild( i );
184 }
185 
186 // -----------------------------------------------------------------------------
187 
188 Reference< XAccessible > OAccessibleMenuComponent::getAccessibleParent(  ) throw (RuntimeException)
189 {
190 	OExternalLockGuard aGuard( this );
191 
192 	Reference< XAccessible > xParent;
193 
194 	if ( m_pMenu )
195 	{
196 		Window* pWindow = m_pMenu->GetWindow();
197 		if ( pWindow )
198 		{
199 			Window* pParent = pWindow->GetAccessibleParentWindow();
200 			if ( pParent )
201 				xParent = pParent->GetAccessible();
202 		}
203 	}
204 
205 	return xParent;
206 }
207 
208 // -----------------------------------------------------------------------------
209 
210 sal_Int16 OAccessibleMenuComponent::getAccessibleRole(  ) throw (RuntimeException)
211 {
212 	OExternalLockGuard aGuard( this );
213 
214 	return AccessibleRole::UNKNOWN;
215 }
216 
217 // -----------------------------------------------------------------------------
218 
219 ::rtl::OUString OAccessibleMenuComponent::getAccessibleDescription(	) throw (RuntimeException)
220 {
221 	OExternalLockGuard aGuard( this );
222 
223 	::rtl::OUString sDescription;
224 	if ( m_pMenu )
225 	{
226 		Window* pWindow = m_pMenu->GetWindow();
227 		if ( pWindow )
228 			sDescription = pWindow->GetAccessibleDescription();
229 	}
230 
231 	return sDescription;
232 }
233 
234 // -----------------------------------------------------------------------------
235 
236 ::rtl::OUString OAccessibleMenuComponent::getAccessibleName(  ) throw (RuntimeException)
237 {
238 	OExternalLockGuard aGuard( this );
239 
240 	return ::rtl::OUString();
241 }
242 
243 // -----------------------------------------------------------------------------
244 
245 Reference< XAccessibleRelationSet > OAccessibleMenuComponent::getAccessibleRelationSet(  ) throw (RuntimeException)
246 {
247 	OExternalLockGuard aGuard( this );
248 
249     utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
250 	Reference< XAccessibleRelationSet > xSet = pRelationSetHelper;
251     return xSet;
252 }
253 
254 // -----------------------------------------------------------------------------
255 
256 Locale OAccessibleMenuComponent::getLocale(  ) throw (IllegalAccessibleComponentStateException, RuntimeException)
257 {
258 	OExternalLockGuard aGuard( this );
259 
260 	return Application::GetSettings().GetLocale();
261 }
262 
263 // -----------------------------------------------------------------------------
264 // XAccessibleComponent
265 // -----------------------------------------------------------------------------
266 
267 Reference< XAccessible > OAccessibleMenuComponent::getAccessibleAtPoint( const awt::Point& rPoint ) throw (RuntimeException)
268 {
269 	OExternalLockGuard aGuard( this );
270 
271 	return GetChildAt( rPoint );
272 }
273 
274 // -----------------------------------------------------------------------------
275 
276 awt::Point OAccessibleMenuComponent::getLocationOnScreen(  ) throw (RuntimeException)
277 {
278 	OExternalLockGuard aGuard( this );
279 
280 	awt::Point aPos;
281 
282 	if ( m_pMenu )
283 	{
284 		Window* pWindow = m_pMenu->GetWindow();
285 		if ( pWindow )
286 		{
287 			Rectangle aRect = pWindow->GetWindowExtentsRelative( NULL );
288 			aPos = AWTPoint( aRect.TopLeft() );
289 		}
290 	}
291 
292 	return aPos;
293 }
294 
295 // -----------------------------------------------------------------------------
296 
297 void OAccessibleMenuComponent::grabFocus(  ) throw (RuntimeException)
298 {
299 	OExternalLockGuard aGuard( this );
300 
301 	if ( m_pMenu )
302 	{
303 		Window* pWindow = m_pMenu->GetWindow();
304 		if ( pWindow )
305 			pWindow->GrabFocus();
306 	}
307 }
308 
309 // -----------------------------------------------------------------------------
310 
311 sal_Int32 OAccessibleMenuComponent::getForeground(	) throw (RuntimeException)
312 {
313 	OExternalLockGuard aGuard( this );
314 
315     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
316 	sal_Int32 nColor = rStyleSettings.GetMenuTextColor().GetColor();
317 
318 	return nColor;
319 }
320 
321 // -----------------------------------------------------------------------------
322 
323 sal_Int32 OAccessibleMenuComponent::getBackground(  ) throw (RuntimeException)
324 {
325 	OExternalLockGuard aGuard( this );
326 
327 	return 0;
328 }
329 
330 // -----------------------------------------------------------------------------
331 // XAccessibleExtendedComponent
332 // -----------------------------------------------------------------------------
333 
334 Reference< awt::XFont > OAccessibleMenuComponent::getFont(  ) throw (RuntimeException)
335 {
336 	OExternalLockGuard aGuard( this );
337 
338 	Reference< awt::XFont > xFont;
339 
340 	if ( m_pMenu )
341 	{
342 		Window* pWindow = m_pMenu->GetWindow();
343 		if ( pWindow )
344 		{
345 			Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), UNO_QUERY );
346 			if ( xDev.is() )
347 			{
348 				const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
349 				VCLXFont* pVCLXFont = new VCLXFont;
350 				pVCLXFont->Init( *xDev.get(), rStyleSettings.GetMenuFont() );
351 				xFont = pVCLXFont;
352 			}
353 		}
354 	}
355 
356 	return xFont;
357 }
358 
359 // -----------------------------------------------------------------------------
360 
361 ::rtl::OUString OAccessibleMenuComponent::getTitledBorderText(  ) throw (RuntimeException)
362 {
363 	OExternalLockGuard aGuard( this );
364 
365 	return ::rtl::OUString();
366 }
367 
368 // -----------------------------------------------------------------------------
369 
370 ::rtl::OUString OAccessibleMenuComponent::getToolTipText(  ) throw (RuntimeException)
371 {
372 	OExternalLockGuard aGuard( this );
373 
374 	return ::rtl::OUString();
375 }
376 
377 // -----------------------------------------------------------------------------
378 // XAccessibleSelection
379 // -----------------------------------------------------------------------------
380 
381 void OAccessibleMenuComponent::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
382 {
383 	OExternalLockGuard aGuard( this );
384 
385 	if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
386 		throw IndexOutOfBoundsException();
387 
388 	SelectChild( nChildIndex );
389 }
390 
391 // -----------------------------------------------------------------------------
392 
393 sal_Bool OAccessibleMenuComponent::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
394 {
395 	OExternalLockGuard aGuard( this );
396 
397 	if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
398 		throw IndexOutOfBoundsException();
399 
400 	return IsChildSelected( nChildIndex );
401 }
402 
403 // -----------------------------------------------------------------------------
404 
405 void OAccessibleMenuComponent::clearAccessibleSelection(  ) throw (RuntimeException)
406 {
407 	OExternalLockGuard aGuard( this );
408 
409 	DeSelectAll();
410 }
411 
412 // -----------------------------------------------------------------------------
413 
414 void OAccessibleMenuComponent::selectAllAccessibleChildren(  ) throw (RuntimeException)
415 {
416 	// This method makes no sense in a menu, and so does nothing.
417 }
418 
419 // -----------------------------------------------------------------------------
420 
421 sal_Int32 OAccessibleMenuComponent::getSelectedAccessibleChildCount(  ) throw (RuntimeException)
422 {
423 	OExternalLockGuard aGuard( this );
424 
425 	sal_Int32 nRet = 0;
426 
427 	for ( sal_Int32 i = 0, nCount = GetChildCount(); i < nCount; i++ )
428 	{
429 		if ( IsChildSelected( i ) )
430 			++nRet;
431 	}
432 
433 	return nRet;
434 }
435 
436 // -----------------------------------------------------------------------------
437 
438 Reference< XAccessible > OAccessibleMenuComponent::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
439 {
440 	OExternalLockGuard aGuard( this );
441 
442 	if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
443 		throw IndexOutOfBoundsException();
444 
445 	Reference< XAccessible > xChild;
446 
447 	for ( sal_Int32 i = 0, j = 0, nCount = GetChildCount(); i < nCount; i++ )
448 	{
449 		if ( IsChildSelected( i ) && ( j++ == nSelectedChildIndex ) )
450 		{
451 			xChild = GetChild( i );
452 			break;
453 		}
454 	}
455 
456 	return xChild;
457 }
458 
459 // -----------------------------------------------------------------------------
460 
461 void OAccessibleMenuComponent::deselectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
462 {
463 	OExternalLockGuard aGuard( this );
464 
465 	if ( nChildIndex < 0 || nChildIndex >= GetChildCount() )
466 		throw IndexOutOfBoundsException();
467 
468 	DeSelectAll();
469 }
470 
471 // -----------------------------------------------------------------------------
472