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_svtools.hxx"
26 
27 #define _SV_VALUESET_CXX
28 
29 #include <unotools/accessiblestatesethelper.hxx>
30 #include <vcl/svapp.hxx>
31 #include <svtools/valueset.hxx>
32 #include "valueimp.hxx"
33 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
34 #include <com/sun/star/accessibility/AccessibleRole.hpp>
35 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
36 
37 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
38 #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLERELATIONTYPE_HPP_
39 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
40 #endif
41 #ifndef _UTL_ACCESSIBLERELATIONSETHELPER_HXX_
42 #include <unotools/accessiblerelationsethelper.hxx>
43 #endif
44 using namespace ::com::sun::star;
45 
46 // ----------------
47 // - ValueSetItem -
48 // ----------------
49 
50 ValueSetItem::ValueSetItem( ValueSet& rParent ) :
51     mrParent( rParent ),
52     mnId( 0 ),
53 	mnBits( 0 ),
54 	mpData( NULL ),
55     mpxAcc( NULL )
56 {
57 }
58 
59 // -----------------------------------------------------------------------
60 
61 ValueSetItem::~ValueSetItem()
62 {
63     if( mpxAcc )
64     {
65         static_cast< ValueItemAcc* >( mpxAcc->get() )->ParentDestroyed();
66         delete mpxAcc;
67     }
68 }
69 
70 // -----------------------------------------------------------------------
71 
72 uno::Reference< accessibility::XAccessible > ValueSetItem::GetAccessible( bool bIsTransientChildrenDisabled )
73 {
74     if( !mpxAcc )
75         mpxAcc = new uno::Reference< accessibility::XAccessible >( new ValueItemAcc( this, bIsTransientChildrenDisabled ) );
76 
77     return *mpxAcc;
78 }
79 
80 // -----------------------------------------------------------------------
81 
82 void ValueSetItem::ClearAccessible()
83 {
84     if( mpxAcc )
85         delete mpxAcc, mpxAcc = NULL;
86 }
87 
88 
89 // ---------------
90 // - ValueSetAcc -
91 // ---------------
92 
93 ValueSetAcc::ValueSetAcc( ValueSet* pParent, bool bIsTransientChildrenDisabled ) :
94     ValueSetAccComponentBase (m_aMutex),
95     mpParent( pParent ),
96     mbIsTransientChildrenDisabled( bIsTransientChildrenDisabled ),
97     mbIsFocused(false)
98 {
99 }
100 
101 // -----------------------------------------------------------------------------
102 
103 ValueSetAcc::~ValueSetAcc()
104 {
105 }
106 
107 // -----------------------------------------------------------------------
108 
109 void ValueSetAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue )
110 {
111     if( nEventId )
112     {
113         ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >                  aTmpListeners( mxEventListeners );
114         ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator  aIter( aTmpListeners.begin() );
115         accessibility::AccessibleEventObject                                                        aEvtObject;
116 
117         aEvtObject.EventId = nEventId;
118         aEvtObject.Source = static_cast<uno::XWeak*>(this);
119         aEvtObject.NewValue = rNewValue;
120 	    aEvtObject.OldValue = rOldValue;
121 
122 		while( aIter != aTmpListeners.end() )
123         {
124 			try
125 			{
126 				(*aIter)->notifyEvent( aEvtObject );
127 			}
128 			catch( uno::Exception& )
129 			{
130 			}
131 
132             aIter++;
133         }
134     }
135 }
136 
137 // -----------------------------------------------------------------------------
138 
139 const uno::Sequence< sal_Int8 >& ValueSetAcc::getUnoTunnelId()
140 {
141     static uno::Sequence< sal_Int8 > aSeq;
142 
143 	if( !aSeq.getLength() )
144 	{
145 		static osl::Mutex           aCreateMutex;
146     	osl::Guard< osl::Mutex >    aGuard( aCreateMutex );
147 
148 		aSeq.realloc( 16 );
149     	rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
150 	}
151 
152     return aSeq;
153 }
154 
155 // -----------------------------------------------------------------------------
156 
157 ValueSetAcc* ValueSetAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData )
158     throw()
159 {
160     try
161     {
162 	    uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY );
163         return( xUnoTunnel.is() ? reinterpret_cast<ValueSetAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( ValueSetAcc::getUnoTunnelId() ))) : NULL );
164     }
165     catch( const ::com::sun::star::uno::Exception& )
166 	{
167         return NULL;
168 	}
169 }
170 
171 
172 // -----------------------------------------------------------------------------
173 
174 void ValueSetAcc::GetFocus (void)
175 {
176     mbIsFocused = true;
177 
178     // Boradcast the state change.
179     ::com::sun::star::uno::Any aOldState, aNewState;
180     aNewState <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED;
181     FireAccessibleEvent(
182         ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED,
183         aOldState, aNewState);
184 }
185 
186 // -----------------------------------------------------------------------------
187 
188 void ValueSetAcc::LoseFocus (void)
189 {
190     mbIsFocused = false;
191 
192     // Boradcast the state change.
193     ::com::sun::star::uno::Any aOldState, aNewState;
194     aOldState <<= ::com::sun::star::accessibility::AccessibleStateType::FOCUSED;
195     FireAccessibleEvent(
196         ::com::sun::star::accessibility::AccessibleEventId::STATE_CHANGED,
197         aOldState, aNewState);
198 }
199 
200 // -----------------------------------------------------------------------------
201 
202 uno::Reference< accessibility::XAccessibleContext > SAL_CALL ValueSetAcc::getAccessibleContext()
203     throw (uno::RuntimeException)
204 {
205     ThrowIfDisposed();
206     return this;
207 }
208 
209 // -----------------------------------------------------------------------------
210 
211 sal_Int32 SAL_CALL ValueSetAcc::getAccessibleChildCount()
212     throw (uno::RuntimeException)
213 {
214     const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
215     ThrowIfDisposed();
216 
217     sal_Int32 nCount = mpParent->ImplGetVisibleItemCount();
218     if (HasNoneField())
219         nCount += 1;
220     return nCount;
221 }
222 
223 // -----------------------------------------------------------------------------
224 
225 uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getAccessibleChild( sal_Int32 i )
226     throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
227 {
228     ThrowIfDisposed();
229     const vos::OGuard                               aSolarGuard( Application::GetSolarMutex() );
230     uno::Reference< accessibility::XAccessible >    xRet;
231     ValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(i));
232 
233     if( pItem )
234         xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled );
235     else
236         throw lang::IndexOutOfBoundsException();
237 
238     return xRet;
239 }
240 
241 // -----------------------------------------------------------------------------
242 
243 uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getAccessibleParent()
244     throw (uno::RuntimeException)
245 {
246     ThrowIfDisposed();
247     const vos::OGuard                               aSolarGuard( Application::GetSolarMutex() );
248     Window*                                         pParent = mpParent->GetParent();
249     uno::Reference< accessibility::XAccessible >    xRet;
250 
251     if( pParent )
252         xRet = pParent->GetAccessible();
253 
254     return xRet;
255 }
256 
257 // -----------------------------------------------------------------------------
258 
259 sal_Int32 SAL_CALL ValueSetAcc::getAccessibleIndexInParent()
260     throw (uno::RuntimeException)
261 {
262     ThrowIfDisposed();
263     const vos::OGuard       aSolarGuard( Application::GetSolarMutex() );
264     Window*                 pParent = mpParent->GetParent();
265     sal_Int32               nRet = 0;
266 
267     if( pParent )
268     {
269         sal_Bool bFound = sal_False;
270 
271         for( sal_uInt16 i = 0, nCount = pParent->GetChildCount(); ( i < nCount ) && !bFound; i++ )
272         {
273             if( pParent->GetChild( i ) == mpParent )
274             {
275                 nRet = i;
276                 bFound = sal_True;
277             }
278         }
279     }
280 
281     return nRet;
282 }
283 
284 // -----------------------------------------------------------------------------
285 
286 sal_Int16 SAL_CALL ValueSetAcc::getAccessibleRole()
287     throw (uno::RuntimeException)
288 {
289     ThrowIfDisposed();
290     // #i73746# As the Java Access Bridge (v 2.0.1) uses "managesDescendants"
291     // always if the role is LIST, we need a different role in this case
292     return (mbIsTransientChildrenDisabled
293             ? accessibility::AccessibleRole::PANEL
294             : accessibility::AccessibleRole::LIST );
295 }
296 
297 // -----------------------------------------------------------------------------
298 
299 ::rtl::OUString SAL_CALL ValueSetAcc::getAccessibleDescription()
300     throw (uno::RuntimeException)
301 {
302     ThrowIfDisposed();
303     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
304     String              aRet( RTL_CONSTASCII_USTRINGPARAM( "ValueSet" ) );
305 
306     return aRet;
307 }
308 
309 // -----------------------------------------------------------------------------
310 
311 ::rtl::OUString SAL_CALL ValueSetAcc::getAccessibleName()
312     throw (uno::RuntimeException)
313 {
314     ThrowIfDisposed();
315     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
316     String              aRet;
317 
318     if ( mpParent )
319         aRet = mpParent->GetAccessibleName();
320 
321     if ( !aRet.Len() )
322     {
323         Window* pLabel = mpParent->GetAccessibleRelationLabeledBy();
324         if ( pLabel && pLabel != mpParent )
325             aRet = OutputDevice::GetNonMnemonicString( pLabel->GetText() );
326 
327         if ( !aRet.Len() )
328          	aRet = mpParent->GetQuickHelpText();
329     }
330 
331     return aRet;
332 }
333 
334 // -----------------------------------------------------------------------------
335 
336 uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL ValueSetAcc::getAccessibleRelationSet()
337     throw (uno::RuntimeException)
338 {
339     ThrowIfDisposed();
340 	uno::Reference< accessibility::XAccessibleRelationSet > xRelSet;
341 	Window* pWindow = (Window*)mpParent;
342 	if ( pWindow )
343 	{
344 		utl::AccessibleRelationSetHelper* pRelationSet = new utl::AccessibleRelationSetHelper;
345 		xRelSet = pRelationSet;
346 
347 		Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
348 		if ( pLabeledBy && pLabeledBy != pWindow )
349 		{
350 			uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
351 			aSequence[0] = pLabeledBy->GetAccessible();
352 			pRelationSet->AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABELED_BY, aSequence ) );
353 		}
354 
355 		Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
356 		if ( pMemberOf && pMemberOf != pWindow )
357 		{
358 			uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
359 			aSequence[0] = pMemberOf->GetAccessible();
360 			pRelationSet->AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
361 		}
362 	}
363     return xRelSet;
364 }
365 
366 // -----------------------------------------------------------------------------
367 
368 uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL ValueSetAcc::getAccessibleStateSet()
369     throw (uno::RuntimeException)
370 {
371     ThrowIfDisposed();
372     ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper();
373 
374     // Set some states.
375     pStateSet->AddState (accessibility::AccessibleStateType::ENABLED);
376     pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE);
377     pStateSet->AddState (accessibility::AccessibleStateType::SHOWING);
378     pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE);
379     if ( !mbIsTransientChildrenDisabled )
380         pStateSet->AddState (accessibility::AccessibleStateType::MANAGES_DESCENDANTS);
381     pStateSet->AddState (accessibility::AccessibleStateType::FOCUSABLE);
382     if (mbIsFocused)
383         pStateSet->AddState (accessibility::AccessibleStateType::FOCUSED);
384 
385     return pStateSet;
386 }
387 
388 // -----------------------------------------------------------------------------
389 
390 lang::Locale SAL_CALL ValueSetAcc::getLocale()
391     throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException)
392 {
393     ThrowIfDisposed();
394     const vos::OGuard                               aSolarGuard( Application::GetSolarMutex() );
395     const ::rtl::OUString                           aEmptyStr;
396     uno::Reference< accessibility::XAccessible >    xParent( getAccessibleParent() );
397     lang::Locale                                    aRet( aEmptyStr, aEmptyStr, aEmptyStr );
398 
399     if( xParent.is() )
400     {
401         uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
402 
403         if( xParentContext.is() )
404             aRet = xParentContext->getLocale ();
405     }
406 
407     return aRet;
408 }
409 
410 // -----------------------------------------------------------------------------
411 
412 void SAL_CALL ValueSetAcc::addEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
413     throw (uno::RuntimeException)
414 {
415     ThrowIfDisposed();
416     ::osl::MutexGuard aGuard (m_aMutex);
417 
418 	if( rxListener.is() )
419     {
420        	::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter = mxEventListeners.begin();
421 		sal_Bool bFound = sal_False;
422 
423 		while( !bFound && ( aIter != mxEventListeners.end() ) )
424         {
425 			if( *aIter == rxListener )
426                 bFound = sal_True;
427             else
428                 aIter++;
429         }
430 
431 		if (!bFound)
432             mxEventListeners.push_back( rxListener );
433     }
434 }
435 
436 // -----------------------------------------------------------------------------
437 
438 void SAL_CALL ValueSetAcc::removeEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
439     throw (uno::RuntimeException)
440 {
441     ThrowIfDisposed();
442     ::osl::MutexGuard aGuard (m_aMutex);
443 
444 	if( rxListener.is() )
445     {
446        	::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter = mxEventListeners.begin();
447 		sal_Bool bFound = sal_False;
448 
449 		while( !bFound && ( aIter != mxEventListeners.end() ) )
450         {
451 			if( *aIter == rxListener )
452             {
453                 mxEventListeners.erase( aIter );
454                 bFound = sal_True;
455             }
456             else
457                 aIter++;
458         }
459     }
460 }
461 
462 // -----------------------------------------------------------------------------
463 
464 sal_Bool SAL_CALL ValueSetAcc::containsPoint( const awt::Point& aPoint )
465     throw (uno::RuntimeException)
466 {
467     ThrowIfDisposed();
468     const awt::Rectangle    aRect( getBounds() );
469     const Point             aSize( aRect.Width, aRect.Height );
470     const Point             aNullPoint, aTestPoint( aPoint.X, aPoint.Y );
471 
472     return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint );
473 }
474 
475 // -----------------------------------------------------------------------------
476 
477 uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getAccessibleAtPoint( const awt::Point& aPoint )
478     throw (uno::RuntimeException)
479 {
480     ThrowIfDisposed();
481     const vos::OGuard                               aSolarGuard( Application::GetSolarMutex() );
482     const sal_uInt16                                    nItemId = mpParent->GetItemId( Point( aPoint.X, aPoint.Y ) );
483     uno::Reference< accessibility::XAccessible >    xRet;
484 
485     if( VALUESET_ITEM_NOTFOUND != nItemId )
486     {
487         const sal_uInt16 nItemPos = mpParent->GetItemPos( nItemId );
488 
489 	    if( VALUESET_ITEM_NONEITEM != nItemPos )
490         {
491             ValueSetItem* pItem = mpParent->mpImpl->mpItemList->GetObject( nItemPos );
492 
493             if( ( pItem->meType != VALUESETITEM_SPACE ) && !pItem->maRect.IsEmpty() )
494                xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled );
495         }
496     }
497 
498     return xRet;
499 }
500 
501 // -----------------------------------------------------------------------------
502 
503 awt::Rectangle SAL_CALL ValueSetAcc::getBounds()
504     throw (uno::RuntimeException)
505 {
506     ThrowIfDisposed();
507     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
508     const Point         aOutPos( mpParent->GetPosPixel() );
509     const Size          aOutSize( mpParent->GetOutputSizePixel() );
510     awt::Rectangle      aRet;
511 
512     aRet.X = aOutPos.X();
513     aRet.Y = aOutPos.Y();
514     aRet.Width = aOutSize.Width();
515     aRet.Height = aOutSize.Height();
516 
517     return aRet;
518 }
519 
520 // -----------------------------------------------------------------------------
521 
522 awt::Point SAL_CALL ValueSetAcc::getLocation()
523     throw (uno::RuntimeException)
524 {
525     ThrowIfDisposed();
526     const awt::Rectangle    aRect( getBounds() );
527     awt::Point              aRet;
528 
529     aRet.X = aRect.X;
530     aRet.Y = aRect.Y;
531 
532     return aRet;
533 }
534 
535 // -----------------------------------------------------------------------------
536 
537 awt::Point SAL_CALL ValueSetAcc::getLocationOnScreen()
538     throw (uno::RuntimeException)
539 {
540     ThrowIfDisposed();
541     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
542     const Point         aScreenPos( mpParent->OutputToAbsoluteScreenPixel( Point() ) );
543     awt::Point          aRet;
544 
545     aRet.X = aScreenPos.X();
546     aRet.Y = aScreenPos.Y();
547 
548     return aRet;
549 }
550 
551 // -----------------------------------------------------------------------------
552 
553 awt::Size SAL_CALL ValueSetAcc::getSize()
554     throw (uno::RuntimeException)
555 {
556     ThrowIfDisposed();
557     const awt::Rectangle    aRect( getBounds() );
558     awt::Size               aRet;
559 
560     aRet.Width = aRect.Width;
561     aRet.Height = aRect.Height;
562 
563     return aRet;
564 }
565 
566 // -----------------------------------------------------------------------------
567 
568 void SAL_CALL ValueSetAcc::grabFocus()
569     throw (uno::RuntimeException)
570 {
571     ThrowIfDisposed();
572     const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
573     mpParent->GrabFocus();
574 }
575 
576 // -----------------------------------------------------------------------------
577 
578 uno::Any SAL_CALL ValueSetAcc::getAccessibleKeyBinding()
579     throw (uno::RuntimeException)
580 {
581     ThrowIfDisposed();
582     return uno::Any();
583 }
584 
585 // -----------------------------------------------------------------------------
586 
587 sal_Int32 SAL_CALL ValueSetAcc::getForeground(  )
588     throw (uno::RuntimeException)
589 {
590     ThrowIfDisposed();
591     sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor().GetColor();
592     return static_cast<sal_Int32>(nColor);
593 }
594 
595 // -----------------------------------------------------------------------------
596 
597 sal_Int32 SAL_CALL ValueSetAcc::getBackground(  )
598     throw (uno::RuntimeException)
599 {
600     ThrowIfDisposed();
601     sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
602     return static_cast<sal_Int32>(nColor);
603 }
604 
605 // -----------------------------------------------------------------------------
606 
607 void SAL_CALL ValueSetAcc::selectAccessibleChild( sal_Int32 nChildIndex )
608     throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
609 {
610     ThrowIfDisposed();
611     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
612     ValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex));
613 
614     if(pItem != NULL)
615     {
616         mpParent->SelectItem( pItem->mnId );
617         mpParent->Select ();
618     }
619     else
620         throw lang::IndexOutOfBoundsException();
621 }
622 
623 // -----------------------------------------------------------------------------
624 
625 sal_Bool SAL_CALL ValueSetAcc::isAccessibleChildSelected( sal_Int32 nChildIndex )
626     throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
627 {
628     ThrowIfDisposed();
629     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
630     ValueSetItem* pItem = getItem (sal::static_int_cast< sal_uInt16 >(nChildIndex));
631     sal_Bool            bRet = sal_False;
632 
633     if (pItem != NULL)
634         bRet = mpParent->IsItemSelected( pItem->mnId );
635     else
636         throw lang::IndexOutOfBoundsException();
637 
638     return bRet;
639 }
640 
641 // -----------------------------------------------------------------------------
642 
643 void SAL_CALL ValueSetAcc::clearAccessibleSelection()
644     throw (uno::RuntimeException)
645 {
646     ThrowIfDisposed();
647     const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
648     mpParent->SetNoSelection();
649 }
650 
651 // -----------------------------------------------------------------------------
652 
653 void SAL_CALL ValueSetAcc::selectAllAccessibleChildren()
654     throw (uno::RuntimeException)
655 {
656     ThrowIfDisposed();
657     // unsupported due to single selection only
658 }
659 
660 // -----------------------------------------------------------------------------
661 
662 sal_Int32 SAL_CALL ValueSetAcc::getSelectedAccessibleChildCount()
663     throw (uno::RuntimeException)
664 {
665     ThrowIfDisposed();
666     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
667     sal_Int32           nRet = 0;
668 
669     for( sal_uInt16 i = 0, nCount = getItemCount(); i < nCount; i++ )
670     {
671         ValueSetItem* pItem = getItem (i);
672 
673         if( pItem && mpParent->IsItemSelected( pItem->mnId ) )
674             ++nRet;
675     }
676 
677     return nRet;
678 }
679 
680 // -----------------------------------------------------------------------------
681 
682 uno::Reference< accessibility::XAccessible > SAL_CALL ValueSetAcc::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
683     throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
684 {
685     ThrowIfDisposed();
686     const vos::OGuard                               aSolarGuard( Application::GetSolarMutex() );
687     uno::Reference< accessibility::XAccessible >    xRet;
688 
689     for( sal_uInt16 i = 0, nCount = getItemCount(), nSel = 0; ( i < nCount ) && !xRet.is(); i++ )
690     {
691         ValueSetItem* pItem = getItem(i);
692 
693         if( pItem && mpParent->IsItemSelected( pItem->mnId ) && ( nSelectedChildIndex == static_cast< sal_Int32 >( nSel++ ) ) )
694             xRet = pItem->GetAccessible( mbIsTransientChildrenDisabled );
695     }
696 
697     return xRet;
698 }
699 
700 // -----------------------------------------------------------------------------
701 
702 void SAL_CALL ValueSetAcc::deselectAccessibleChild( sal_Int32 nChildIndex )
703     throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
704 {
705     ThrowIfDisposed();
706     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
707     // Because of the single selection we can reset the whole selection when
708     // the specified child is currently selected.
709     if (isAccessibleChildSelected(nChildIndex))
710         mpParent->SetNoSelection();
711 }
712 
713 // -----------------------------------------------------------------------------
714 
715 sal_Int64 SAL_CALL ValueSetAcc::getSomething( const uno::Sequence< sal_Int8 >& rId ) throw( uno::RuntimeException )
716 {
717     sal_Int64 nRet;
718 
719     if( ( rId.getLength() == 16 ) && ( 0 == rtl_compareMemory( ValueSetAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
720         nRet = reinterpret_cast< sal_Int64 >( this );
721     else
722         nRet = 0;
723 
724 	return nRet;
725 }
726 
727 
728 
729 
730 void SAL_CALL ValueSetAcc::disposing (void)
731 {
732     ::std::vector<uno::Reference<accessibility::XAccessibleEventListener> > aListenerListCopy;
733 
734     {
735         // Make a copy of the list and clear the original.
736         const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
737         ::osl::MutexGuard aGuard (m_aMutex);
738         aListenerListCopy = mxEventListeners;
739         mxEventListeners.clear();
740 
741         // Reset the pointer to the parent.  It has to be the one who has
742         // disposed us because he is dying.
743         mpParent = NULL;
744     }
745 
746     // Inform all listeners that this objects is disposing.
747     ::std::vector<uno::Reference<accessibility::XAccessibleEventListener> >::const_iterator
748           aListenerIterator (aListenerListCopy.begin());
749     lang::EventObject aEvent (static_cast<accessibility::XAccessible*>(this));
750     while (aListenerIterator != aListenerListCopy.end())
751     {
752         try
753         {
754             (*aListenerIterator)->disposing (aEvent);
755         }
756         catch( uno::Exception& )
757         {
758             // Ignore exceptions.
759         }
760 
761         ++aListenerIterator;
762     }
763 }
764 
765 
766 sal_uInt16 ValueSetAcc::getItemCount (void) const
767 {
768     sal_uInt16 nCount = mpParent->ImplGetVisibleItemCount();
769     // When the None-Item is visible then increase the number of items by
770     // one.
771     if (HasNoneField())
772         nCount += 1;
773     return nCount;
774 }
775 
776 
777 ValueSetItem* ValueSetAcc::getItem (sal_uInt16 nIndex) const
778 {
779     ValueSetItem* pItem = NULL;
780 
781     if (HasNoneField())
782     {
783         if (nIndex == 0)
784             // When present the first item is the then allways visible none field.
785             pItem = mpParent->ImplGetItem (VALUESET_ITEM_NONEITEM);
786         else
787             // Shift down the index to compensate for the none field.
788             nIndex -= 1;
789     }
790     if (pItem == NULL)
791         //pItem = mpParent->ImplGetVisibleItem (static_cast<sal_uInt16>(nIndex));
792 	pItem = mpParent->ImplGetItem (static_cast<sal_uInt16>(nIndex));
793 
794     return pItem;
795 }
796 
797 
798 
799 
800 void ValueSetAcc::ThrowIfDisposed (void)
801     throw (::com::sun::star::lang::DisposedException)
802 {
803     if (rBHelper.bDisposed || rBHelper.bInDispose)
804     {
805         OSL_TRACE ("Calling disposed object. Throwing exception:");
806         throw lang::DisposedException (
807             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")),
808             static_cast<uno::XWeak*>(this));
809     }
810     else
811     {
812         DBG_ASSERT (mpParent!=NULL, "ValueSetAcc not disposed but mpParent == NULL");
813     }
814 }
815 
816 
817 
818 sal_Bool ValueSetAcc::IsDisposed (void)
819 {
820 	return (rBHelper.bDisposed || rBHelper.bInDispose);
821 }
822 
823 
824 
825 
826 bool ValueSetAcc::HasNoneField (void) const
827 {
828     DBG_ASSERT (mpParent!=NULL, "ValueSetAcc::HasNoneField called with mpParent==NULL");
829     return ((mpParent->GetStyle() & WB_NONEFIELD) != 0);
830 }
831 
832 
833 
834 
835 // ----------------
836 // - ValueItemAcc -
837 // ----------------
838 
839 ValueItemAcc::ValueItemAcc( ValueSetItem* pParent, bool bIsTransientChildrenDisabled ) :
840     mpParent( pParent ),
841     mbIsTransientChildrenDisabled( bIsTransientChildrenDisabled )
842 {
843 }
844 
845 // -----------------------------------------------------------------------------
846 
847 ValueItemAcc::~ValueItemAcc()
848 {
849 }
850 
851 // -----------------------------------------------------------------------
852 
853 void ValueItemAcc::FireAccessibleEvent( short nEventId, const uno::Any& rOldValue, const uno::Any& rNewValue )
854 {
855     if( nEventId )
856     {
857         ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >                  aTmpListeners( mxEventListeners );
858         ::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator  aIter( aTmpListeners.begin() );
859         accessibility::AccessibleEventObject                                                        aEvtObject;
860 
861         aEvtObject.EventId = nEventId;
862         aEvtObject.Source = static_cast<uno::XWeak*>(this);
863         aEvtObject.NewValue = rNewValue;
864 	    aEvtObject.OldValue = rOldValue;
865 
866 		while( aIter != aTmpListeners.end() )
867         {
868             (*aIter)->notifyEvent( aEvtObject );
869             aIter++;
870         }
871     }
872 }
873 
874 // -----------------------------------------------------------------------------
875 
876 void ValueItemAcc::ParentDestroyed()
877 {
878     const ::vos::OGuard aGuard( maMutex );
879     mpParent = NULL;
880 }
881 
882 // -----------------------------------------------------------------------------
883 
884 const uno::Sequence< sal_Int8 >& ValueItemAcc::getUnoTunnelId()
885 {
886     static uno::Sequence< sal_Int8 > aSeq;
887 
888 	if( !aSeq.getLength() )
889 	{
890 		static osl::Mutex           aCreateMutex;
891     	osl::Guard< osl::Mutex >    aGuard( aCreateMutex );
892 
893 		aSeq.realloc( 16 );
894     	rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
895 	}
896 
897     return aSeq;
898 }
899 
900 // -----------------------------------------------------------------------------
901 
902 ValueItemAcc* ValueItemAcc::getImplementation( const uno::Reference< uno::XInterface >& rxData )
903     throw()
904 {
905     try
906     {
907 	    uno::Reference< lang::XUnoTunnel > xUnoTunnel( rxData, uno::UNO_QUERY );
908         return( xUnoTunnel.is() ? reinterpret_cast<ValueItemAcc*>(sal::static_int_cast<sal_IntPtr>(xUnoTunnel->getSomething( ValueItemAcc::getUnoTunnelId() ))) : NULL );
909     }
910     catch( const ::com::sun::star::uno::Exception& )
911 	{
912         return NULL;
913 	}
914 }
915 
916 // -----------------------------------------------------------------------------
917 
918 uno::Reference< accessibility::XAccessibleContext > SAL_CALL ValueItemAcc::getAccessibleContext()
919     throw (uno::RuntimeException)
920 {
921     return this;
922 }
923 
924 // -----------------------------------------------------------------------------
925 
926 sal_Int32 SAL_CALL ValueItemAcc::getAccessibleChildCount()
927     throw (uno::RuntimeException)
928 {
929     return 0;
930 }
931 
932 // -----------------------------------------------------------------------------
933 
934 uno::Reference< accessibility::XAccessible > SAL_CALL ValueItemAcc::getAccessibleChild( sal_Int32 )
935     throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
936 {
937     throw lang::IndexOutOfBoundsException();
938 }
939 
940 // -----------------------------------------------------------------------------
941 
942 uno::Reference< accessibility::XAccessible > SAL_CALL ValueItemAcc::getAccessibleParent()
943     throw (uno::RuntimeException)
944 {
945     const vos::OGuard                               aSolarGuard( Application::GetSolarMutex() );
946     uno::Reference< accessibility::XAccessible >    xRet;
947 
948     if( mpParent )
949         xRet = mpParent->mrParent.GetAccessible();
950 
951     return xRet;
952 }
953 
954 // -----------------------------------------------------------------------------
955 
956 sal_Int32 SAL_CALL ValueItemAcc::getAccessibleIndexInParent()
957     throw (uno::RuntimeException)
958 {
959     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
960     // The index defaults to -1 to indicate the child does not belong to its
961     // parent.
962     sal_Int32 nIndexInParent = -1;
963 
964     if( mpParent )
965     {
966         bool bDone = false;
967 
968         sal_uInt16 nCount = mpParent->mrParent.ImplGetVisibleItemCount();
969         ValueSetItem* pItem;
970         for (sal_uInt16 i=0; i<nCount && !bDone; i++)
971         {
972             // Guard the retrieval of the i-th child with a try/catch block
973             // just in case the number of children changes in the mean time.
974             try
975             {
976                 //pItem = mpParent->mrParent.ImplGetVisibleItem (i);
977                 pItem = mpParent->mrParent.ImplGetItem(i);
978             }
979             catch (lang::IndexOutOfBoundsException aException)
980             {
981                 pItem = NULL;
982             }
983 
984             // Do not create an accessible object for the test.
985             if (pItem != NULL && pItem->mpxAcc != NULL)
986                 if (pItem->GetAccessible( mbIsTransientChildrenDisabled ).get() == this )
987                 {
988                     nIndexInParent = i;
989                     bDone = true;
990                 }
991         }
992     }
993 
994 	//if this valueset contain a none field(common value is default), then we should increase the real index and set the noitem index value equal 0.
995 	if ( mpParent && ( (mpParent->mrParent.GetStyle() & WB_NONEFIELD) != 0 ) )
996 	{
997 		ValueSetItem* pFirstItem = mpParent->mrParent.ImplGetItem (VALUESET_ITEM_NONEITEM);
998 		if( pFirstItem && pFirstItem ->GetAccessible(mbIsTransientChildrenDisabled).get() == this )
999 			nIndexInParent = 0;
1000 		else
1001 			nIndexInParent++;
1002 	}
1003     return nIndexInParent;
1004 }
1005 
1006 // -----------------------------------------------------------------------------
1007 
1008 sal_Int16 SAL_CALL ValueItemAcc::getAccessibleRole()
1009     throw (uno::RuntimeException)
1010 {
1011     return accessibility::AccessibleRole::LIST_ITEM;
1012 }
1013 
1014 // -----------------------------------------------------------------------------
1015 
1016 ::rtl::OUString SAL_CALL ValueItemAcc::getAccessibleDescription()
1017     throw (uno::RuntimeException)
1018 {
1019 	return ::rtl::OUString();
1020 }
1021 
1022 // -----------------------------------------------------------------------------
1023 
1024 ::rtl::OUString SAL_CALL ValueItemAcc::getAccessibleName()
1025     throw (uno::RuntimeException)
1026 {
1027     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
1028     String              aRet;
1029 
1030     if( mpParent )
1031     {
1032         aRet = mpParent->maText;
1033 
1034         if( !aRet.Len() )
1035         {
1036             aRet = String( RTL_CONSTASCII_USTRINGPARAM( "Item " ) );
1037             aRet += String::CreateFromInt32( mpParent->mnId );
1038         }
1039     }
1040 
1041     return aRet;
1042 }
1043 
1044 // -----------------------------------------------------------------------------
1045 
1046 uno::Reference< accessibility::XAccessibleRelationSet > SAL_CALL ValueItemAcc::getAccessibleRelationSet()
1047     throw (uno::RuntimeException)
1048 {
1049     return uno::Reference< accessibility::XAccessibleRelationSet >();
1050 }
1051 
1052 // -----------------------------------------------------------------------------
1053 
1054 uno::Reference< accessibility::XAccessibleStateSet > SAL_CALL ValueItemAcc::getAccessibleStateSet()
1055     throw (uno::RuntimeException)
1056 {
1057     const vos::OGuard                   aSolarGuard( Application::GetSolarMutex() );
1058     ::utl::AccessibleStateSetHelper*    pStateSet = new ::utl::AccessibleStateSetHelper;
1059 
1060     if( mpParent )
1061     {
1062         pStateSet->AddState (accessibility::AccessibleStateType::ENABLED);
1063         pStateSet->AddState (accessibility::AccessibleStateType::SENSITIVE);
1064         pStateSet->AddState (accessibility::AccessibleStateType::SHOWING);
1065         pStateSet->AddState (accessibility::AccessibleStateType::VISIBLE);
1066         if ( !mbIsTransientChildrenDisabled )
1067             pStateSet->AddState (accessibility::AccessibleStateType::TRANSIENT);
1068 
1069 	    // SELECTABLE
1070 	    pStateSet->AddState( accessibility::AccessibleStateType::SELECTABLE );
1071         //	    pStateSet->AddState( accessibility::AccessibleStateType::FOCUSABLE );
1072 
1073 	    // SELECTED
1074         if( mpParent->mrParent.GetSelectItemId() == mpParent->mnId )
1075         {
1076             pStateSet->AddState( accessibility::AccessibleStateType::SELECTED );
1077             //       	    pStateSet->AddState( accessibility::AccessibleStateType::FOCUSED );
1078         }
1079     }
1080 
1081     return pStateSet;
1082 }
1083 
1084 // -----------------------------------------------------------------------------
1085 
1086 lang::Locale SAL_CALL ValueItemAcc::getLocale()
1087     throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException)
1088 {
1089     const vos::OGuard                               aSolarGuard( Application::GetSolarMutex() );
1090     const ::rtl::OUString                           aEmptyStr;
1091     uno::Reference< accessibility::XAccessible >    xParent( getAccessibleParent() );
1092     lang::Locale                                    aRet( aEmptyStr, aEmptyStr, aEmptyStr );
1093 
1094     if( xParent.is() )
1095     {
1096         uno::Reference< accessibility::XAccessibleContext > xParentContext( xParent->getAccessibleContext() );
1097 
1098         if( xParentContext.is() )
1099             aRet = xParentContext->getLocale();
1100     }
1101 
1102     return aRet;
1103 }
1104 
1105 // -----------------------------------------------------------------------------
1106 
1107 void SAL_CALL ValueItemAcc::addEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
1108     throw (uno::RuntimeException)
1109 {
1110     const ::vos::OGuard aGuard( maMutex );
1111 
1112 	if( rxListener.is() )
1113     {
1114        	::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::const_iterator aIter = mxEventListeners.begin();
1115 		sal_Bool bFound = sal_False;
1116 
1117 		while( !bFound && ( aIter != mxEventListeners.end() ) )
1118         {
1119 			if( *aIter == rxListener )
1120                 bFound = sal_True;
1121             else
1122                 aIter++;
1123         }
1124 
1125 		if (!bFound)
1126             mxEventListeners.push_back( rxListener );
1127     }
1128 }
1129 
1130 // -----------------------------------------------------------------------------
1131 
1132 void SAL_CALL ValueItemAcc::removeEventListener( const uno::Reference< accessibility::XAccessibleEventListener >& rxListener )
1133     throw (uno::RuntimeException)
1134 {
1135     const ::vos::OGuard aGuard( maMutex );
1136 
1137 	if( rxListener.is() )
1138     {
1139        	::std::vector< uno::Reference< accessibility::XAccessibleEventListener > >::iterator aIter = mxEventListeners.begin();
1140 		sal_Bool bFound = sal_False;
1141 
1142 		while( !bFound && ( aIter != mxEventListeners.end() ) )
1143         {
1144 			if( *aIter == rxListener )
1145             {
1146                 mxEventListeners.erase( aIter );
1147                 bFound = sal_True;
1148             }
1149             else
1150                 aIter++;
1151         }
1152     }
1153 }
1154 
1155 // -----------------------------------------------------------------------------
1156 
1157 sal_Bool SAL_CALL ValueItemAcc::containsPoint( const awt::Point& aPoint )
1158     throw (uno::RuntimeException)
1159 {
1160     const awt::Rectangle    aRect( getBounds() );
1161     const Point             aSize( aRect.Width, aRect.Height );
1162     const Point             aNullPoint, aTestPoint( aPoint.X, aPoint.Y );
1163 
1164     return Rectangle( aNullPoint, aSize ).IsInside( aTestPoint );
1165 }
1166 
1167 // -----------------------------------------------------------------------------
1168 
1169 uno::Reference< accessibility::XAccessible > SAL_CALL ValueItemAcc::getAccessibleAtPoint( const awt::Point& )
1170     throw (uno::RuntimeException)
1171 {
1172     uno::Reference< accessibility::XAccessible > xRet;
1173     return xRet;
1174 }
1175 
1176 // -----------------------------------------------------------------------------
1177 
1178 awt::Rectangle SAL_CALL ValueItemAcc::getBounds()
1179     throw (uno::RuntimeException)
1180 {
1181     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
1182     awt::Rectangle      aRet;
1183 
1184     if( mpParent )
1185     {
1186         Rectangle   aRect( mpParent->maRect );
1187         Point       aOrigin;
1188         Rectangle   aParentRect( aOrigin, mpParent->mrParent.GetOutputSizePixel() );
1189 
1190         aRect.Intersection( aParentRect );
1191 
1192         aRet.X = aRect.Left();
1193         aRet.Y = aRect.Top();
1194         aRet.Width = aRect.GetWidth();
1195         aRet.Height = aRect.GetHeight();
1196     }
1197 
1198     return aRet;
1199 }
1200 
1201 // -----------------------------------------------------------------------------
1202 
1203 awt::Point SAL_CALL ValueItemAcc::getLocation()
1204     throw (uno::RuntimeException)
1205 {
1206     const awt::Rectangle    aRect( getBounds() );
1207     awt::Point              aRet;
1208 
1209     aRet.X = aRect.X;
1210     aRet.Y = aRect.Y;
1211 
1212     return aRet;
1213 }
1214 
1215 // -----------------------------------------------------------------------------
1216 
1217 awt::Point SAL_CALL ValueItemAcc::getLocationOnScreen()
1218     throw (uno::RuntimeException)
1219 {
1220     const vos::OGuard   aSolarGuard( Application::GetSolarMutex() );
1221     awt::Point          aRet;
1222 
1223     if( mpParent )
1224     {
1225         const Point aScreenPos( mpParent->mrParent.OutputToAbsoluteScreenPixel( mpParent->maRect.TopLeft() ) );
1226 
1227         aRet.X = aScreenPos.X();
1228         aRet.Y = aScreenPos.Y();
1229     }
1230 
1231     return aRet;
1232 }
1233 
1234 // -----------------------------------------------------------------------------
1235 
1236 awt::Size SAL_CALL ValueItemAcc::getSize()
1237     throw (uno::RuntimeException)
1238 {
1239     const awt::Rectangle    aRect( getBounds() );
1240     awt::Size               aRet;
1241 
1242     aRet.Width = aRect.Width;
1243     aRet.Height = aRect.Height;
1244 
1245     return aRet;
1246 }
1247 
1248 // -----------------------------------------------------------------------------
1249 
1250 void SAL_CALL ValueItemAcc::grabFocus()
1251     throw (uno::RuntimeException)
1252 {
1253     // nothing to do
1254 }
1255 
1256 // -----------------------------------------------------------------------------
1257 
1258 uno::Any SAL_CALL ValueItemAcc::getAccessibleKeyBinding()
1259     throw (uno::RuntimeException)
1260 {
1261     return uno::Any();
1262 }
1263 
1264 // -----------------------------------------------------------------------------
1265 
1266 sal_Int32 SAL_CALL ValueItemAcc::getForeground(  )
1267     throw (uno::RuntimeException)
1268 {
1269     sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowTextColor().GetColor();
1270     return static_cast<sal_Int32>(nColor);
1271 }
1272 
1273 // -----------------------------------------------------------------------------
1274 
1275 sal_Int32 SAL_CALL ValueItemAcc::getBackground(  )
1276     throw (uno::RuntimeException)
1277 {
1278     sal_uInt32 nColor;
1279     if (mpParent && mpParent->meType == VALUESETITEM_COLOR)
1280         nColor = mpParent->maColor.GetColor();
1281     else
1282         nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
1283     return static_cast<sal_Int32>(nColor);
1284 }
1285 
1286 // -----------------------------------------------------------------------------
1287 
1288 sal_Int64 SAL_CALL ValueItemAcc::getSomething( const uno::Sequence< sal_Int8 >& rId ) throw( uno::RuntimeException )
1289 {
1290     sal_Int64 nRet;
1291 
1292     if( ( rId.getLength() == 16 ) && ( 0 == rtl_compareMemory( ValueItemAcc::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
1293         nRet = reinterpret_cast< sal_Int64 >( this );
1294     else
1295         nRet = 0;
1296 
1297 	return nRet;
1298 }
1299