xref: /AOO41X/main/accessibility/source/standard/accessiblemenuitemcomponent.cxx (revision 144e4e6270fa3bc429c7c0bbb90998a8c234dfbf)
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 
OAccessibleMenuItemComponent(Menu * pParent,sal_uInt16 nItemPos,Menu * pMenu)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 
~OAccessibleMenuItemComponent()75 OAccessibleMenuItemComponent::~OAccessibleMenuItemComponent()
76 {
77 }
78 
79 // -----------------------------------------------------------------------------
80 
IsEnabled()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 
IsVisible()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 
Select()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 
DeSelect()124 void OAccessibleMenuItemComponent::DeSelect()
125 {
126     if ( m_pParent && IsSelected() )
127         m_pParent->DeHighlight();
128 }
129 
130 // -----------------------------------------------------------------------------
131 
Click()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 
SetItemPos(sal_uInt16 nItemPos)180 void OAccessibleMenuItemComponent::SetItemPos( sal_uInt16 nItemPos )
181 {
182     m_nItemPos = nItemPos;
183 }
184 
185 // -----------------------------------------------------------------------------
186 
SetAccessibleName(const::rtl::OUString & sAccessibleName)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 
GetAccessibleName()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.isEmpty() )
209             sName = m_pParent->GetItemText( nItemId );
210         sName = OutputDevice::GetNonMnemonicString( sName );
211 
212         // IA2 CWS, MT: Is adding 5 blanks really before the accelname reasonable? And which Platform / Accessibility API does need it this way? ATK has API for this...
213         // Also, IAccessible2 has IAccessibleAction::keyBinding, so I doubt that this is needed.
214         // But if so, it needs to move to the IA2 bridge.
215         /*
216         ::rtl::OUString sAccName = m_pParent->GetAccelKey( nItemId ).GetName();
217         if ( sAccName.getLength() )
218         {
219             sName += ::rtl::OUString::createFromAscii("     ");
220             sName += aAccelName;
221         }
222         */
223     }
224 
225     return sName;
226 }
227 
228 // -----------------------------------------------------------------------------
229 
SetItemText(const::rtl::OUString & sItemText)230 void OAccessibleMenuItemComponent::SetItemText( const ::rtl::OUString& sItemText )
231 {
232     Any aOldValue, aNewValue;
233     if ( OCommonAccessibleText::implInitTextChangedEvent( m_sItemText, sItemText, aOldValue, aNewValue ) )
234     {
235         m_sItemText = sItemText;
236         NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
237     }
238 }
239 
240 // -----------------------------------------------------------------------------
241 
GetItemText()242 ::rtl::OUString OAccessibleMenuItemComponent::GetItemText()
243 {
244     ::rtl::OUString sText;
245     if ( m_pParent )
246         sText = OutputDevice::GetNonMnemonicString( m_pParent->GetItemText( m_pParent->GetItemId( m_nItemPos ) ) );
247 
248     return sText;
249 }
250 
251 // -----------------------------------------------------------------------------
252 
FillAccessibleStateSet(utl::AccessibleStateSetHelper & rStateSet)253 void OAccessibleMenuItemComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
254 {
255     sal_Bool bEnabled = IsEnabled();
256     if ( bEnabled )
257     {
258         rStateSet.AddState( AccessibleStateType::ENABLED );
259         rStateSet.AddState( AccessibleStateType::SENSITIVE );
260     }
261 
262     if ( IsVisible() )
263     {
264         rStateSet.AddState( AccessibleStateType::SHOWING );
265         if( !IsMenuHideDisabledEntries() || bEnabled )
266             rStateSet.AddState( AccessibleStateType::VISIBLE );
267     }
268     rStateSet.AddState( AccessibleStateType::OPAQUE );
269 }
270 
271 // -----------------------------------------------------------------------------
272 // OCommonAccessibleComponent
273 // -----------------------------------------------------------------------------
274 
implGetBounds()275 awt::Rectangle OAccessibleMenuItemComponent::implGetBounds() throw (RuntimeException)
276 {
277     awt::Rectangle aBounds( 0, 0, 0, 0 );
278 
279     if ( m_pParent )
280     {
281         // get bounding rectangle of the item relative to the containing window
282         aBounds = AWTRectangle( m_pParent->GetBoundingRectangle( m_nItemPos ) );
283 
284         // get position of containing window in screen coordinates
285         Window* pWindow = m_pParent->GetWindow();
286         if ( pWindow )
287         {
288             Rectangle aRect = pWindow->GetWindowExtentsRelative( NULL );
289             awt::Point aWindowScreenLoc = AWTPoint( aRect.TopLeft() );
290 
291             // get position of accessible parent in screen coordinates
292             Reference< XAccessible > xParent = getAccessibleParent();
293             if ( xParent.is() )
294             {
295                 Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), UNO_QUERY );
296                 if ( xParentComponent.is() )
297                 {
298                     awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
299 
300                     // calculate bounding rectangle of the item relative to the accessible parent
301                     aBounds.X += aWindowScreenLoc.X - aParentScreenLoc.X;
302                     aBounds.Y += aWindowScreenLoc.Y - aParentScreenLoc.Y;
303                 }
304             }
305         }
306     }
307 
308     return aBounds;
309 }
310 
311 // -----------------------------------------------------------------------------
312 // XComponent
313 // -----------------------------------------------------------------------------
314 
disposing()315 void SAL_CALL OAccessibleMenuItemComponent::disposing()
316 {
317     OAccessibleMenuBaseComponent::disposing();
318 
319     m_pParent = NULL;
320     m_sAccessibleName = ::rtl::OUString();
321     m_sItemText = ::rtl::OUString();
322 }
323 
324 // -----------------------------------------------------------------------------
325 // XAccessibleContext
326 // -----------------------------------------------------------------------------
327 
getAccessibleChildCount()328 sal_Int32 OAccessibleMenuItemComponent::getAccessibleChildCount() throw (RuntimeException)
329 {
330     OExternalLockGuard aGuard( this );
331 
332     return 0;
333 }
334 
335 // -----------------------------------------------------------------------------
336 
getAccessibleChild(sal_Int32 i)337 Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
338 {
339     OExternalLockGuard aGuard( this );
340 
341     if ( i < 0 || i >= getAccessibleChildCount() )
342         throw IndexOutOfBoundsException();
343 
344     return Reference< XAccessible >();
345 }
346 
347 // -----------------------------------------------------------------------------
348 
getAccessibleParent()349 Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleParent(  ) throw (RuntimeException)
350 {
351     OExternalLockGuard aGuard( this );
352 
353     return m_pParent->GetAccessible();
354 }
355 
356 // -----------------------------------------------------------------------------
357 
getAccessibleIndexInParent()358 sal_Int32 OAccessibleMenuItemComponent::getAccessibleIndexInParent(  ) throw (RuntimeException)
359 {
360     OExternalLockGuard aGuard( this );
361 
362     return m_nItemPos;
363 }
364 
365 // -----------------------------------------------------------------------------
366 
getAccessibleRole()367 sal_Int16 OAccessibleMenuItemComponent::getAccessibleRole(  ) throw (RuntimeException)
368 {
369     OExternalLockGuard aGuard( this );
370 
371     return AccessibleRole::UNKNOWN;
372 }
373 
374 // -----------------------------------------------------------------------------
375 
getAccessibleDescription()376 ::rtl::OUString OAccessibleMenuItemComponent::getAccessibleDescription( ) throw (RuntimeException)
377 {
378     OExternalLockGuard aGuard( this );
379 
380     ::rtl::OUString sDescription;
381     if ( m_pParent )
382         sDescription = m_pParent->GetHelpText( m_pParent->GetItemId( m_nItemPos ) );
383 
384     return sDescription;
385 }
386 
387 // -----------------------------------------------------------------------------
388 
getAccessibleName()389 ::rtl::OUString OAccessibleMenuItemComponent::getAccessibleName(  ) throw (RuntimeException)
390 {
391     OExternalLockGuard aGuard( this );
392 
393     return m_sAccessibleName;
394 }
395 
396 // -----------------------------------------------------------------------------
397 
getAccessibleRelationSet()398 Reference< XAccessibleRelationSet > OAccessibleMenuItemComponent::getAccessibleRelationSet(  ) throw (RuntimeException)
399 {
400     OExternalLockGuard aGuard( this );
401 
402     utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
403     Reference< XAccessibleRelationSet > xSet = pRelationSetHelper;
404     return xSet;
405 }
406 
407 // -----------------------------------------------------------------------------
408 
getLocale()409 Locale OAccessibleMenuItemComponent::getLocale(  ) throw (IllegalAccessibleComponentStateException, RuntimeException)
410 {
411     OExternalLockGuard aGuard( this );
412 
413     return Application::GetSettings().GetLocale();
414 }
415 
416 // -----------------------------------------------------------------------------
417 // XAccessibleComponent
418 // -----------------------------------------------------------------------------
419 
getAccessibleAtPoint(const awt::Point &)420 Reference< XAccessible > OAccessibleMenuItemComponent::getAccessibleAtPoint( const awt::Point& ) throw (RuntimeException)
421 {
422     OExternalLockGuard aGuard( this );
423 
424     return Reference< XAccessible >();
425 }
426 
427 // -----------------------------------------------------------------------------
428 
grabFocus()429 void OAccessibleMenuItemComponent::grabFocus(  ) throw (RuntimeException)
430 {
431     // no focus for items
432 }
433 
434 // -----------------------------------------------------------------------------
435 
getForeground()436 sal_Int32 OAccessibleMenuItemComponent::getForeground(  ) throw (RuntimeException)
437 {
438     OExternalLockGuard aGuard( this );
439 
440     sal_Int32 nColor = 0;
441     Reference< XAccessible > xParent = getAccessibleParent();
442     if ( xParent.is() )
443     {
444         Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
445         if ( xParentComp.is() )
446             nColor = xParentComp->getForeground();
447     }
448 
449     return nColor;
450 }
451 
452 // -----------------------------------------------------------------------------
453 
getBackground()454 sal_Int32 OAccessibleMenuItemComponent::getBackground(  ) throw (RuntimeException)
455 {
456     OExternalLockGuard aGuard( this );
457 
458     sal_Int32 nColor = 0;
459     Reference< XAccessible > xParent = getAccessibleParent();
460     if ( xParent.is() )
461     {
462         Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
463         if ( xParentComp.is() )
464             nColor = xParentComp->getBackground();
465     }
466 
467     return nColor;
468 }
469 
470 // -----------------------------------------------------------------------------
471 // XAccessibleExtendedComponent
472 // -----------------------------------------------------------------------------
473 
getFont()474 Reference< awt::XFont > OAccessibleMenuItemComponent::getFont(  ) throw (RuntimeException)
475 {
476     OExternalLockGuard aGuard( this );
477 
478     Reference< awt::XFont > xFont;
479     Reference< XAccessible > xParent = getAccessibleParent();
480     if ( xParent.is() )
481     {
482         Reference< XAccessibleExtendedComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
483         if ( xParentComp.is() )
484             xFont = xParentComp->getFont();
485     }
486 
487     return xFont;
488 }
489 
490 // -----------------------------------------------------------------------------
491 
getTitledBorderText()492 ::rtl::OUString OAccessibleMenuItemComponent::getTitledBorderText(  ) throw (RuntimeException)
493 {
494     OExternalLockGuard aGuard( this );
495 
496     return ::rtl::OUString();
497 }
498 
499 // -----------------------------------------------------------------------------
500 
getToolTipText()501 ::rtl::OUString OAccessibleMenuItemComponent::getToolTipText(  ) throw (RuntimeException)
502 {
503     OExternalLockGuard aGuard( this );
504 
505     ::rtl::OUString sRet;
506     if ( m_pParent )
507         sRet = m_pParent->GetTipHelpText( m_pParent->GetItemId( m_nItemPos ) );
508 
509     return sRet;
510 }
511 
512 // -----------------------------------------------------------------------------
513 
IsMenuHideDisabledEntries()514 sal_Bool OAccessibleMenuItemComponent::IsMenuHideDisabledEntries()
515 {
516     if (m_pParent )
517     {
518         if( m_pParent->GetMenuFlags() & MENU_FLAG_HIDEDISABLEDENTRIES)
519         {
520             return sal_True;
521         }
522         // IA2 CWS, but the menus shouldn't have different flags, and even if so, the GetStartedFromMenu shouldn't matter
523         /*
524         else if (m_pParent->GetStartedFromMenu() &&
525                 m_pParent->GetStartedFromMenu()->GetMenuFlags() & MENU_FLAG_HIDEDISABLEDENTRIES)
526         {
527             return sal_True;
528         }
529         */
530     }
531     return sal_False;
532 }
533