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