xref: /AOO41X/main/accessibility/source/standard/accessiblemenuitemcomponent.cxx (revision 8809db7a87f97847b57a57f4cd2b0104b2b83182)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_accessibility.hxx"
26 #include <accessibility/standard/accessiblemenuitemcomponent.hxx>
27 
28 
29 #include <accessibility/helper/accresmgr.hxx>
30 #include <accessibility/helper/accessiblestrings.hrc>
31 #include <toolkit/awt/vclxwindows.hxx>
32 #include <toolkit/helper/externallock.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 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
39 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
40 
41 #include <unotools/accessiblestatesethelper.hxx>
42 #include <unotools/accessiblerelationsethelper.hxx>
43 #include <cppuhelper/typeprovider.hxx>
44 #include <comphelper/sequence.hxx>
45 #include <comphelper/accessibletexthelper.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vcl/window.hxx>
48 #include <vcl/menu.hxx>
49 #include <vcl/unohelp2.hxx>
50 
51 
52 using namespace ::com::sun::star::accessibility;
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::beans;
55 using namespace ::com::sun::star::lang;
56 using namespace ::com::sun::star;
57 using namespace ::comphelper;
58 
59 
60 // -----------------------------------------------------------------------------
61 // class OAccessibleMenuItemComponent
62 // -----------------------------------------------------------------------------
63 
64 OAccessibleMenuItemComponent::OAccessibleMenuItemComponent( Menu* pParent, sal_uInt16 nItemPos, Menu* pMenu )
65     :OAccessibleMenuBaseComponent( pMenu )
66     ,m_pParent( pParent )
67     ,m_nItemPos( nItemPos )
68 {
69     m_sAccessibleName = GetAccessibleName();
70     m_sItemText = GetItemText();
71 }
72 
73 // -----------------------------------------------------------------------------
74 
75 OAccessibleMenuItemComponent::~OAccessibleMenuItemComponent()
76 {
77 }
78 
79 // -----------------------------------------------------------------------------
80 
81 sal_Bool OAccessibleMenuItemComponent::IsEnabled()
82 {
83     OExternalLockGuard aGuard( this );
84 
85     sal_Bool bEnabled = sal_False;
86     if ( m_pParent )
87         bEnabled = m_pParent->IsItemEnabled( m_pParent->GetItemId( m_nItemPos ) );
88 
89     return bEnabled;
90 }
91 
92 // -----------------------------------------------------------------------------
93 
94 sal_Bool OAccessibleMenuItemComponent::IsVisible()
95 {
96     sal_Bool bVisible = sal_False;
97 
98     if ( m_pParent )
99         bVisible = m_pParent->IsItemPosVisible( m_nItemPos );
100 
101     return bVisible;
102 }
103 
104 // -----------------------------------------------------------------------------
105 
106 void OAccessibleMenuItemComponent::Select()
107 {
108     // open the parent menu
109     Reference< XAccessible > xParent( getAccessibleParent() );
110     if ( xParent.is() )
111     {
112         OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xParent.get() );
113         if ( pComp && pComp->getAccessibleRole() == AccessibleRole::MENU && !pComp->IsPopupMenuOpen() )
114             pComp->Click();
115     }
116 
117     // highlight the menu item
118     if ( m_pParent )
119         m_pParent->HighlightItem( m_nItemPos );
120 }
121 
122 // -----------------------------------------------------------------------------
123 
124 void OAccessibleMenuItemComponent::DeSelect()
125 {
126     if ( m_pParent && IsSelected() )
127         m_pParent->DeHighlight();
128 }
129 
130 // -----------------------------------------------------------------------------
131 
132 void OAccessibleMenuItemComponent::Click()
133 {
134     // open the parent menu
135     Reference< XAccessible > xParent( getAccessibleParent() );
136     if ( xParent.is() )
137     {
138         OAccessibleMenuBaseComponent* pComp = static_cast< OAccessibleMenuBaseComponent* >( xParent.get() );
139         if ( pComp && pComp->getAccessibleRole() == AccessibleRole::MENU && !pComp->IsPopupMenuOpen() )
140             pComp->Click();
141     }
142 
143     // click the menu item
144     if ( m_pParent )
145     {
146         Window* pWindow = m_pParent->GetWindow();
147         if ( pWindow )
148         {
149             // #102438# Menu items are not selectable
150             // Popup menus are executed asynchronously, triggered by a timer.
151             // As Menu::SelectItem only works, if the corresponding menu window is
152             // already created, we have to set the menu delay to 0, so
153             // that the popup menus are executed synchronously.
154             AllSettings aSettings = pWindow->GetSettings();
155             MouseSettings aMouseSettings = aSettings.GetMouseSettings();
156             sal_uLong nDelay = aMouseSettings.GetMenuDelay();
157             aMouseSettings.SetMenuDelay( 0 );
158             aSettings.SetMouseSettings( aMouseSettings );
159             pWindow->SetSettings( aSettings );
160 
161             m_pParent->SelectItem( m_pParent->GetItemId( m_nItemPos ) );
162 
163             // meanwhile the window pointer may be invalid
164             pWindow = m_pParent->GetWindow();
165             if ( pWindow )
166             {
167                 // set the menu delay back to the old value
168                 aSettings = pWindow->GetSettings();
169                 aMouseSettings = aSettings.GetMouseSettings();
170                 aMouseSettings.SetMenuDelay( nDelay );
171                 aSettings.SetMouseSettings( aMouseSettings );
172                 pWindow->SetSettings( aSettings );
173             }
174         }
175     }
176 }
177 
178 // -----------------------------------------------------------------------------
179 
180 void OAccessibleMenuItemComponent::SetItemPos( sal_uInt16 nItemPos )
181 {
182     m_nItemPos = nItemPos;
183 }
184 
185 // -----------------------------------------------------------------------------
186 
187 void OAccessibleMenuItemComponent::SetAccessibleName( const ::rtl::OUString& sAccessibleName )
188 {
189     if ( !m_sAccessibleName.equals( sAccessibleName ) )
190     {
191         Any aOldValue, aNewValue;
192         aOldValue <<= m_sAccessibleName;
193         aNewValue <<= sAccessibleName;
194         m_sAccessibleName = sAccessibleName;
195         NotifyAccessibleEvent( AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
196     }
197 }
198 
199 // -----------------------------------------------------------------------------
200 
201 ::rtl::OUString OAccessibleMenuItemComponent::GetAccessibleName()
202 {
203     ::rtl::OUString sName;
204     if ( m_pParent )
205     {
206         sal_uInt16 nItemId = m_pParent->GetItemId( m_nItemPos );
207         sName = m_pParent->GetAccessibleName( nItemId );
208         if ( sName.getLength() == 0 )
209             sName = m_pParent->GetItemText( nItemId );
210         sName = OutputDevice::GetNonMnemonicString( sName );
211     }
212 
213     return sName;
214 }
215 
216 // -----------------------------------------------------------------------------
217 
218 void OAccessibleMenuItemComponent::SetItemText( const ::rtl::OUString& sItemText )
219 {
220     Any aOldValue, aNewValue;
221     if ( OCommonAccessibleText::implInitTextChangedEvent( m_sItemText, sItemText, aOldValue, aNewValue ) )
222     {
223         m_sItemText = sItemText;
224         NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
225     }
226 }
227 
228 // -----------------------------------------------------------------------------
229 
230 ::rtl::OUString OAccessibleMenuItemComponent::GetItemText()
231 {
232     ::rtl::OUString sText;
233     if ( m_pParent )
234         sText = OutputDevice::GetNonMnemonicString( m_pParent->GetItemText( m_pParent->GetItemId( m_nItemPos ) ) );
235 
236     return sText;
237 }
238 
239 // -----------------------------------------------------------------------------
240 
241 void OAccessibleMenuItemComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
242 {
243     if ( IsEnabled() )
244     {
245         rStateSet.AddState( AccessibleStateType::ENABLED );
246         rStateSet.AddState( AccessibleStateType::SENSITIVE );
247     }
248 
249     if ( IsVisible() )
250     {
251         rStateSet.AddState( AccessibleStateType::VISIBLE );
252         rStateSet.AddState( AccessibleStateType::SHOWING );
253     }
254 
255     rStateSet.AddState( AccessibleStateType::OPAQUE );
256 }
257 
258 // -----------------------------------------------------------------------------
259 // OCommonAccessibleComponent
260 // -----------------------------------------------------------------------------
261 
262 awt::Rectangle OAccessibleMenuItemComponent::implGetBounds() throw (RuntimeException)
263 {
264     awt::Rectangle aBounds( 0, 0, 0, 0 );
265 
266     if ( m_pParent )
267     {
268         // get bounding rectangle of the item relative to the containing window
269         aBounds = AWTRectangle( m_pParent->GetBoundingRectangle( m_nItemPos ) );
270 
271         // get position of containing window in screen coordinates
272         Window* pWindow = m_pParent->GetWindow();
273         if ( pWindow )
274         {
275             Rectangle aRect = pWindow->GetWindowExtentsRelative( NULL );
276             awt::Point aWindowScreenLoc = AWTPoint( aRect.TopLeft() );
277 
278             // get position of accessible parent in screen coordinates
279             Reference< XAccessible > xParent = getAccessibleParent();
280             if ( xParent.is() )
281             {
282                 Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), UNO_QUERY );
283                 if ( xParentComponent.is() )
284                 {
285                     awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
286 
287                     // calculate bounding rectangle of the item relative to the accessible parent
288                     aBounds.X += aWindowScreenLoc.X - aParentScreenLoc.X;
289                     aBounds.Y += aWindowScreenLoc.Y - aParentScreenLoc.Y;
290                 }
291             }
292         }
293     }
294 
295     return aBounds;
296 }
297 
298 // -----------------------------------------------------------------------------
299 // XComponent
300 // -----------------------------------------------------------------------------
301 
302 void SAL_CALL OAccessibleMenuItemComponent::disposing()
303 {
304     OAccessibleMenuBaseComponent::disposing();
305 
306     m_pParent = NULL;
307     m_sAccessibleName = ::rtl::OUString();
308     m_sItemText = ::rtl::OUString();
309 }
310 
311 // -----------------------------------------------------------------------------
312 // XAccessibleContext
313 // -----------------------------------------------------------------------------
314 
315 sal_Int32 OAccessibleMenuItemComponent::getAccessibleChildCount() throw (RuntimeException)
316 {
317     OExternalLockGuard aGuard( this );
318 
319     return 0;
320 }
321 
322 // -----------------------------------------------------------------------------
323 
324 Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
325 {
326     OExternalLockGuard aGuard( this );
327 
328     if ( i < 0 || i >= getAccessibleChildCount() )
329         throw IndexOutOfBoundsException();
330 
331     return Reference< XAccessible >();
332 }
333 
334 // -----------------------------------------------------------------------------
335 
336 Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleParent(  ) throw (RuntimeException)
337 {
338     OExternalLockGuard aGuard( this );
339 
340     return m_pParent->GetAccessible();
341 }
342 
343 // -----------------------------------------------------------------------------
344 
345 sal_Int32 OAccessibleMenuItemComponent::getAccessibleIndexInParent(  ) throw (RuntimeException)
346 {
347     OExternalLockGuard aGuard( this );
348 
349     return m_nItemPos;
350 }
351 
352 // -----------------------------------------------------------------------------
353 
354 sal_Int16 OAccessibleMenuItemComponent::getAccessibleRole(  ) throw (RuntimeException)
355 {
356     OExternalLockGuard aGuard( this );
357 
358     return AccessibleRole::UNKNOWN;
359 }
360 
361 // -----------------------------------------------------------------------------
362 
363 ::rtl::OUString OAccessibleMenuItemComponent::getAccessibleDescription( ) throw (RuntimeException)
364 {
365     OExternalLockGuard aGuard( this );
366 
367     ::rtl::OUString sDescription;
368     if ( m_pParent )
369         sDescription = m_pParent->GetHelpText( m_pParent->GetItemId( m_nItemPos ) );
370 
371     return sDescription;
372 }
373 
374 // -----------------------------------------------------------------------------
375 
376 ::rtl::OUString OAccessibleMenuItemComponent::getAccessibleName(  ) throw (RuntimeException)
377 {
378     OExternalLockGuard aGuard( this );
379 
380     return m_sAccessibleName;
381 }
382 
383 // -----------------------------------------------------------------------------
384 
385 Reference< XAccessibleRelationSet > OAccessibleMenuItemComponent::getAccessibleRelationSet(  ) throw (RuntimeException)
386 {
387     OExternalLockGuard aGuard( this );
388 
389     utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
390     Reference< XAccessibleRelationSet > xSet = pRelationSetHelper;
391     return xSet;
392 }
393 
394 // -----------------------------------------------------------------------------
395 
396 Locale OAccessibleMenuItemComponent::getLocale(  ) throw (IllegalAccessibleComponentStateException, RuntimeException)
397 {
398     OExternalLockGuard aGuard( this );
399 
400     return Application::GetSettings().GetLocale();
401 }
402 
403 // -----------------------------------------------------------------------------
404 // XAccessibleComponent
405 // -----------------------------------------------------------------------------
406 
407 Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleAtPoint( const awt::Point& ) throw (RuntimeException)
408 {
409     OExternalLockGuard aGuard( this );
410 
411     return Reference< XAccessible >();
412 }
413 
414 // -----------------------------------------------------------------------------
415 
416 void OAccessibleMenuItemComponent::grabFocus(  ) throw (RuntimeException)
417 {
418     // no focus for items
419 }
420 
421 // -----------------------------------------------------------------------------
422 
423 sal_Int32 OAccessibleMenuItemComponent::getForeground(  ) throw (RuntimeException)
424 {
425     OExternalLockGuard aGuard( this );
426 
427     sal_Int32 nColor = 0;
428     Reference< XAccessible > xParent = getAccessibleParent();
429     if ( xParent.is() )
430     {
431         Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
432         if ( xParentComp.is() )
433             nColor = xParentComp->getForeground();
434     }
435 
436     return nColor;
437 }
438 
439 // -----------------------------------------------------------------------------
440 
441 sal_Int32 OAccessibleMenuItemComponent::getBackground(  ) throw (RuntimeException)
442 {
443     OExternalLockGuard aGuard( this );
444 
445     sal_Int32 nColor = 0;
446     Reference< XAccessible > xParent = getAccessibleParent();
447     if ( xParent.is() )
448     {
449         Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
450         if ( xParentComp.is() )
451             nColor = xParentComp->getBackground();
452     }
453 
454     return nColor;
455 }
456 
457 // -----------------------------------------------------------------------------
458 // XAccessibleExtendedComponent
459 // -----------------------------------------------------------------------------
460 
461 Reference< awt::XFont > OAccessibleMenuItemComponent::getFont(  ) throw (RuntimeException)
462 {
463     OExternalLockGuard aGuard( this );
464 
465     Reference< awt::XFont > xFont;
466     Reference< XAccessible > xParent = getAccessibleParent();
467     if ( xParent.is() )
468     {
469         Reference< XAccessibleExtendedComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
470         if ( xParentComp.is() )
471             xFont = xParentComp->getFont();
472     }
473 
474     return xFont;
475 }
476 
477 // -----------------------------------------------------------------------------
478 
479 ::rtl::OUString OAccessibleMenuItemComponent::getTitledBorderText(  ) throw (RuntimeException)
480 {
481     OExternalLockGuard aGuard( this );
482 
483     return ::rtl::OUString();
484 }
485 
486 // -----------------------------------------------------------------------------
487 
488 ::rtl::OUString OAccessibleMenuItemComponent::getToolTipText(  ) throw (RuntimeException)
489 {
490     OExternalLockGuard aGuard( this );
491 
492     ::rtl::OUString sRet;
493     if ( m_pParent )
494         sRet = m_pParent->GetTipHelpText( m_pParent->GetItemId( m_nItemPos ) );
495 
496     return sRet;
497 }
498 
499 // -----------------------------------------------------------------------------
500