10841af79SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
30841af79SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
40841af79SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
50841af79SAndrew Rist  * distributed with this work for additional information
60841af79SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
70841af79SAndrew Rist  * to you under the Apache License, Version 2.0 (the
80841af79SAndrew Rist  * "License"); you may not use this file except in compliance
90841af79SAndrew Rist  * with the License.  You may obtain a copy of the License at
100841af79SAndrew Rist  *
110841af79SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
120841af79SAndrew Rist  *
130841af79SAndrew Rist  * Unless required by applicable law or agreed to in writing,
140841af79SAndrew Rist  * software distributed under the License is distributed on an
150841af79SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
160841af79SAndrew Rist  * KIND, either express or implied.  See the License for the
170841af79SAndrew Rist  * specific language governing permissions and limitations
180841af79SAndrew Rist  * under the License.
190841af79SAndrew Rist  *
200841af79SAndrew Rist  *************************************************************/
210841af79SAndrew Rist 
220841af79SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_accessibility.hxx"
26cdf0e10cSrcweir #include <accessibility/standard/vclxaccessiblebox.hxx>
27cdf0e10cSrcweir #include <accessibility/standard/vclxaccessibletextfield.hxx>
28cdf0e10cSrcweir #include <accessibility/standard/vclxaccessibleedit.hxx>
29cdf0e10cSrcweir #include <accessibility/standard/vclxaccessiblelist.hxx>
30cdf0e10cSrcweir #include <accessibility/helper/listboxhelper.hxx>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <unotools/accessiblestatesethelper.hxx>
33cdf0e10cSrcweir #include <com/sun/star/accessibility/AccessibleStateType.hpp>
34cdf0e10cSrcweir #include <com/sun/star/accessibility/AccessibleEventId.hpp>
35cdf0e10cSrcweir #include <com/sun/star/accessibility/AccessibleRole.hpp>
36cdf0e10cSrcweir #include <vcl/svapp.hxx>
37cdf0e10cSrcweir #include <vcl/combobox.hxx>
38cdf0e10cSrcweir #include <vcl/lstbox.hxx>
39cdf0e10cSrcweir #include <accessibility/helper/accresmgr.hxx>
40cdf0e10cSrcweir #include <accessibility/helper/accessiblestrings.hrc>
41cdf0e10cSrcweir 
42cdf0e10cSrcweir using namespace ::com::sun::star;
43cdf0e10cSrcweir using namespace ::com::sun::star::uno;
44cdf0e10cSrcweir using namespace ::com::sun::star::lang;
45cdf0e10cSrcweir using namespace ::com::sun::star::beans;
46cdf0e10cSrcweir using namespace ::com::sun::star::accessibility;
47cdf0e10cSrcweir 
48cdf0e10cSrcweir VCLXAccessibleBox::VCLXAccessibleBox (VCLXWindow* pVCLWindow, BoxType aType, bool bIsDropDownBox)
49cdf0e10cSrcweir     : VCLXAccessibleComponent (pVCLWindow),
50cdf0e10cSrcweir       m_aBoxType (aType),
51cdf0e10cSrcweir       m_bIsDropDownBox (bIsDropDownBox),
52cdf0e10cSrcweir       m_nIndexInParent (DEFAULT_INDEX_IN_PARENT)
53cdf0e10cSrcweir {
54cdf0e10cSrcweir     // Set up the flags that indicate which children this object has.
55cdf0e10cSrcweir     m_bHasListChild = true;
56cdf0e10cSrcweir 
57cdf0e10cSrcweir     // A text field is not present for non drop down list boxes.
58cdf0e10cSrcweir     if ((m_aBoxType==LISTBOX) && ! m_bIsDropDownBox)
59cdf0e10cSrcweir         m_bHasTextChild = false;
60cdf0e10cSrcweir     else
61cdf0e10cSrcweir         m_bHasTextChild = true;
62cdf0e10cSrcweir }
63cdf0e10cSrcweir 
64cdf0e10cSrcweir VCLXAccessibleBox::~VCLXAccessibleBox (void)
65cdf0e10cSrcweir {
66cdf0e10cSrcweir }
67cdf0e10cSrcweir 
68cdf0e10cSrcweir void VCLXAccessibleBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
69cdf0e10cSrcweir {
70cdf0e10cSrcweir    	uno::Any aOldValue, aNewValue;
71cdf0e10cSrcweir     uno::Reference<XAccessible> xAcc;
72cdf0e10cSrcweir 
73cdf0e10cSrcweir 	switch ( rVclWindowEvent.GetId() )
74cdf0e10cSrcweir 	{
75cdf0e10cSrcweir         case VCLEVENT_WINDOW_SHOW:
76cdf0e10cSrcweir         case VCLEVENT_WINDOW_HIDE:
77cdf0e10cSrcweir         {
78cdf0e10cSrcweir             Window* pChildWindow = (Window *) rVclWindowEvent.GetData();
79cdf0e10cSrcweir             // Just compare to the combo box text field.  All other children
80cdf0e10cSrcweir             // are identical to this object in which case this object will
81cdf0e10cSrcweir             // be removed in a short time.
82cdf0e10cSrcweir             if (m_aBoxType==COMBOBOX)
83cdf0e10cSrcweir             {
84cdf0e10cSrcweir                 ComboBox* pComboBox = static_cast<ComboBox*>(GetWindow());
85cdf0e10cSrcweir                 if ( ( pComboBox != NULL ) && ( pChildWindow != NULL ) )
86cdf0e10cSrcweir                     if (pChildWindow == pComboBox->GetSubEdit())
87cdf0e10cSrcweir                     {
88cdf0e10cSrcweir                         if (rVclWindowEvent.GetId() == VCLEVENT_WINDOW_SHOW)
89cdf0e10cSrcweir                         {
90cdf0e10cSrcweir                             // Instantiate text field.
91cdf0e10cSrcweir                             getAccessibleChild (0);
92cdf0e10cSrcweir                             aNewValue <<= m_xText;
93cdf0e10cSrcweir                         }
94cdf0e10cSrcweir                         else
95cdf0e10cSrcweir                         {
96cdf0e10cSrcweir                             // Release text field.
97cdf0e10cSrcweir                             aOldValue <<= m_xText;
98cdf0e10cSrcweir                             m_xText = NULL;
99cdf0e10cSrcweir                         }
100cdf0e10cSrcweir                         // Tell the listeners about the new/removed child.
101cdf0e10cSrcweir                         NotifyAccessibleEvent (
102cdf0e10cSrcweir                             AccessibleEventId::CHILD,
103cdf0e10cSrcweir                             aOldValue, aNewValue);
104cdf0e10cSrcweir                     }
105cdf0e10cSrcweir 
106cdf0e10cSrcweir             }
107cdf0e10cSrcweir         }
108cdf0e10cSrcweir         break;
109cdf0e10cSrcweir 
110cdf0e10cSrcweir         default:
111cdf0e10cSrcweir             VCLXAccessibleComponent::ProcessWindowChildEvent (rVclWindowEvent);
112cdf0e10cSrcweir 	}
113cdf0e10cSrcweir }
114cdf0e10cSrcweir 
115cdf0e10cSrcweir void VCLXAccessibleBox::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent)
116cdf0e10cSrcweir {
117cdf0e10cSrcweir 	switch ( rVclWindowEvent.GetId() )
118cdf0e10cSrcweir 	{
119*21075d77SSteve Yin 		case VCLEVENT_LISTBOX_SELECT:
120*21075d77SSteve Yin 		case VCLEVENT_LISTBOX_FOCUSITEMCHANGED:
121*21075d77SSteve Yin 
122*21075d77SSteve Yin 		{
123*21075d77SSteve Yin 	            // Forward the call to the list child.
124*21075d77SSteve Yin 	            VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
125*21075d77SSteve Yin 	            if ( pList == NULL )
126*21075d77SSteve Yin 			{
127*21075d77SSteve Yin 				getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
128*21075d77SSteve Yin 				pList = static_cast<VCLXAccessibleList*>(m_xList.get());
129*21075d77SSteve Yin 			}
130*21075d77SSteve Yin 			if ( pList != NULL )
131*21075d77SSteve Yin 			{
132*21075d77SSteve Yin 				pList->ProcessWindowEvent (rVclWindowEvent, m_bIsDropDownBox);
133*21075d77SSteve Yin 				if(m_bIsDropDownBox)
134*21075d77SSteve Yin 				{
135*21075d77SSteve Yin 					NotifyAccessibleEvent(AccessibleEventId::VALUE_CHANGED, Any(), Any());
136*21075d77SSteve Yin 					Any aOldValue;
137*21075d77SSteve Yin 					Any aNewValue;
138*21075d77SSteve Yin 					aOldValue <<= AccessibleStateType::INDETERMINATE;
139*21075d77SSteve Yin 					NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue);
140*21075d77SSteve Yin 
141*21075d77SSteve Yin 				}
142*21075d77SSteve Yin 			}
143*21075d77SSteve Yin 			break;
144*21075d77SSteve Yin 		}
145cdf0e10cSrcweir 		case VCLEVENT_DROPDOWN_OPEN:
146*21075d77SSteve Yin 		{
147*21075d77SSteve Yin 	             VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
148*21075d77SSteve Yin 	             if ( pList == NULL )
149*21075d77SSteve Yin 			{
150*21075d77SSteve Yin 				getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
151*21075d77SSteve Yin 				pList = static_cast<VCLXAccessibleList*>(m_xList.get());
152*21075d77SSteve Yin 			}
153*21075d77SSteve Yin 			if ( pList != NULL )
154*21075d77SSteve Yin 			{
155*21075d77SSteve Yin 				pList->ProcessWindowEvent (rVclWindowEvent);
156*21075d77SSteve Yin 				pList->HandleDropOpen();
157*21075d77SSteve Yin 			}
158*21075d77SSteve Yin 			break;
159*21075d77SSteve Yin 		}
160cdf0e10cSrcweir 		case VCLEVENT_DROPDOWN_CLOSE:
161*21075d77SSteve Yin 		{
162*21075d77SSteve Yin 	             VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
163*21075d77SSteve Yin 	             if ( pList == NULL )
164*21075d77SSteve Yin 			{
165*21075d77SSteve Yin 				getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
166*21075d77SSteve Yin 				pList = static_cast<VCLXAccessibleList*>(m_xList.get());
167*21075d77SSteve Yin 			}
168*21075d77SSteve Yin 			if ( pList != NULL )
169*21075d77SSteve Yin 			{
170*21075d77SSteve Yin 				pList->ProcessWindowEvent (rVclWindowEvent);
171*21075d77SSteve Yin 			}
172*21075d77SSteve Yin 			Window* pWindow = GetWindow();
173*21075d77SSteve Yin 			if( pWindow && (pWindow->HasFocus() || pWindow->HasChildPathFocus()) )
174*21075d77SSteve Yin 			{
175*21075d77SSteve Yin 				Any aOldValue, aNewValue;
176*21075d77SSteve Yin 				aNewValue <<= AccessibleStateType::FOCUSED;
177*21075d77SSteve Yin 				NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
178*21075d77SSteve Yin 			}
179*21075d77SSteve Yin 			break;
180*21075d77SSteve Yin 		}
181*21075d77SSteve Yin 		case VCLEVENT_COMBOBOX_SELECT:
182*21075d77SSteve Yin 		{
183*21075d77SSteve Yin 	             VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
184*21075d77SSteve Yin 	             if (pList != NULL)
185*21075d77SSteve Yin 	             {
186*21075d77SSteve Yin 		                Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
187*21075d77SSteve Yin 		                if ( xText.is() )
188*21075d77SSteve Yin 				{
189*21075d77SSteve Yin 					::rtl::OUString sText = xText->getSelectedText();
190*21075d77SSteve Yin 					if ( !sText.getLength() )
191*21075d77SSteve Yin 						sText = xText->getText();
192*21075d77SSteve Yin 		                    pList->UpdateSelection_Acc (sText, m_bIsDropDownBox);
193*21075d77SSteve Yin 					//if(m_bIsDropDownBox && !pList->IsInDropDown())
194*21075d77SSteve Yin 					if (m_bIsDropDownBox || ( !m_bIsDropDownBox && m_aBoxType==COMBOBOX))
195*21075d77SSteve Yin 						NotifyAccessibleEvent(AccessibleEventId::VALUE_CHANGED, Any(), Any());
196*21075d77SSteve Yin 
197*21075d77SSteve Yin 						Any aOldValue;
198*21075d77SSteve Yin 						Any aNewValue;
199*21075d77SSteve Yin 						aOldValue <<= AccessibleStateType::INDETERMINATE;
200*21075d77SSteve Yin 						NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue);
201*21075d77SSteve Yin 
202*21075d77SSteve Yin 				}
203*21075d77SSteve Yin 	            	}
204*21075d77SSteve Yin 			break;
205*21075d77SSteve Yin 		}
206*21075d77SSteve Yin 		//case VCLEVENT_DROPDOWN_OPEN:
207*21075d77SSteve Yin 		//case VCLEVENT_DROPDOWN_CLOSE:
208cdf0e10cSrcweir 		case VCLEVENT_LISTBOX_DOUBLECLICK:
209cdf0e10cSrcweir 		case VCLEVENT_LISTBOX_SCROLLED:
210*21075d77SSteve Yin 		//case VCLEVENT_LISTBOX_SELECT:
211cdf0e10cSrcweir         case VCLEVENT_LISTBOX_ITEMADDED:
212cdf0e10cSrcweir         case VCLEVENT_LISTBOX_ITEMREMOVED:
213cdf0e10cSrcweir         case VCLEVENT_COMBOBOX_ITEMADDED:
214cdf0e10cSrcweir         case VCLEVENT_COMBOBOX_ITEMREMOVED:
215cdf0e10cSrcweir 		case VCLEVENT_COMBOBOX_SCROLLED:
216cdf0e10cSrcweir         {
217cdf0e10cSrcweir             // Forward the call to the list child.
218cdf0e10cSrcweir             VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
219cdf0e10cSrcweir             if ( pList == NULL )
220cdf0e10cSrcweir 			{
221cdf0e10cSrcweir 				getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
222cdf0e10cSrcweir 				pList = static_cast<VCLXAccessibleList*>(m_xList.get());
223cdf0e10cSrcweir 			}
224cdf0e10cSrcweir 			if ( pList != NULL )
225cdf0e10cSrcweir 				pList->ProcessWindowEvent (rVclWindowEvent);
226cdf0e10cSrcweir             break;
227cdf0e10cSrcweir         }
228cdf0e10cSrcweir 
229*21075d77SSteve Yin 		//case VCLEVENT_COMBOBOX_SELECT:
230cdf0e10cSrcweir         case VCLEVENT_COMBOBOX_DESELECT:
231cdf0e10cSrcweir         {
232cdf0e10cSrcweir             // Selection is handled by VCLXAccessibleList which operates on
233cdf0e10cSrcweir             // the same VCL object as this box does.  In case of the
234cdf0e10cSrcweir             // combobox, however, we have to help the list with providing
235cdf0e10cSrcweir             // the text of the currently selected item.
236cdf0e10cSrcweir             VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
237cdf0e10cSrcweir             if (pList != NULL && m_xText.is())
238cdf0e10cSrcweir             {
239cdf0e10cSrcweir                 Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
240cdf0e10cSrcweir                 if ( xText.is() )
241cdf0e10cSrcweir 				{
242cdf0e10cSrcweir 					::rtl::OUString sText = xText->getSelectedText();
243cdf0e10cSrcweir 					if ( !sText.getLength() )
244cdf0e10cSrcweir 						sText = xText->getText();
245cdf0e10cSrcweir                     pList->UpdateSelection (sText);
246cdf0e10cSrcweir 				}
247cdf0e10cSrcweir             }
248cdf0e10cSrcweir 			break;
249cdf0e10cSrcweir         }
250cdf0e10cSrcweir 
251cdf0e10cSrcweir 		case VCLEVENT_EDIT_MODIFY:
252cdf0e10cSrcweir         case VCLEVENT_EDIT_SELECTIONCHANGED:
253*21075d77SSteve Yin 	 // case VCLEVENT_EDIT_CARETCHANGED:
254cdf0e10cSrcweir             // Modify/Selection events are handled by the combo box instead of
255cdf0e10cSrcweir             // directly by the edit field (Why?).  Therefore, delegate this
256cdf0e10cSrcweir             // call to the edit field.
257cdf0e10cSrcweir             if (m_aBoxType==COMBOBOX)
258cdf0e10cSrcweir             {
259cdf0e10cSrcweir                 if (m_xText.is())
260cdf0e10cSrcweir                 {
261cdf0e10cSrcweir                     Reference<XAccessibleContext> xContext = m_xText->getAccessibleContext();
262cdf0e10cSrcweir                     VCLXAccessibleEdit* pEdit = static_cast<VCLXAccessibleEdit*>(xContext.get());
263cdf0e10cSrcweir                     if (pEdit != NULL)
264cdf0e10cSrcweir                         pEdit->ProcessWindowEvent (rVclWindowEvent);
265cdf0e10cSrcweir                 }
266cdf0e10cSrcweir             }
267cdf0e10cSrcweir             break;
268*21075d77SSteve Yin 		/*
269*21075d77SSteve Yin 		// MT: Not sending VCLEVENT_LISTBOX_STATEUPDATE, see comment in ListBox::SelectEntryPos
270*21075d77SSteve Yin 		case VCLEVENT_LISTBOX_STATEUPDATE:
271*21075d77SSteve Yin 		{
272*21075d77SSteve Yin 			// Need to update the INDETERMINATE state sometimes, Sym2_1986
273*21075d77SSteve Yin 			if (m_bIsDropDownBox && m_aBoxType==LISTBOX)
274*21075d77SSteve Yin 			{
275*21075d77SSteve Yin 				sal_Int32 nSelectedEntryCount = 0;
276*21075d77SSteve Yin 				ListBox* pListBox = static_cast< ListBox* >( GetWindow() );
277*21075d77SSteve Yin 				if (pListBox != NULL && pListBox->GetEntryCount() > 0)
278*21075d77SSteve Yin 				{
279*21075d77SSteve Yin 	        		nSelectedEntryCount = pListBox->GetSelectEntryCount();
280*21075d77SSteve Yin 					Any aOldValue;
281*21075d77SSteve Yin 					Any aNewValue;
282*21075d77SSteve Yin 					if ( nSelectedEntryCount == 0)
283*21075d77SSteve Yin 						aNewValue <<= AccessibleStateType::INDETERMINATE;
284*21075d77SSteve Yin 					else
285*21075d77SSteve Yin 						aOldValue <<= AccessibleStateType::INDETERMINATE;
286*21075d77SSteve Yin 					NotifyAccessibleEvent(AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue);
287*21075d77SSteve Yin 				}
288*21075d77SSteve Yin 			}
289*21075d77SSteve Yin 			break;
290*21075d77SSteve Yin 		}
291*21075d77SSteve Yin 		*/
292cdf0e10cSrcweir 		default:
293cdf0e10cSrcweir 			VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
294cdf0e10cSrcweir 	}
295cdf0e10cSrcweir }
296cdf0e10cSrcweir 
297cdf0e10cSrcweir IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleBox, VCLXAccessibleComponent, VCLXAccessibleBox_BASE)
298cdf0e10cSrcweir IMPLEMENT_FORWARD_XTYPEPROVIDER2(VCLXAccessibleBox, VCLXAccessibleComponent, VCLXAccessibleBox_BASE)
299cdf0e10cSrcweir 
300cdf0e10cSrcweir //=====  XAccessible  =========================================================
301cdf0e10cSrcweir 
302cdf0e10cSrcweir Reference< XAccessibleContext > SAL_CALL VCLXAccessibleBox::getAccessibleContext(  )
303cdf0e10cSrcweir 	throw (RuntimeException)
304cdf0e10cSrcweir {
305cdf0e10cSrcweir 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
306cdf0e10cSrcweir 
307cdf0e10cSrcweir 	return this;
308cdf0e10cSrcweir }
309cdf0e10cSrcweir 
310cdf0e10cSrcweir //=====  XAccessibleContext  ==================================================
311cdf0e10cSrcweir 
312cdf0e10cSrcweir sal_Int32 SAL_CALL VCLXAccessibleBox::getAccessibleChildCount (void)
313cdf0e10cSrcweir     throw (RuntimeException)
314cdf0e10cSrcweir {
315cdf0e10cSrcweir 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
316cdf0e10cSrcweir 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
317cdf0e10cSrcweir 
318cdf0e10cSrcweir     // Usually a box has a text field and a list of items as its children.
319cdf0e10cSrcweir     // Non drop down list boxes have no text field.  Additionally check
320cdf0e10cSrcweir     // whether the object is valid.
321cdf0e10cSrcweir     sal_Int32 nCount = 0;
322cdf0e10cSrcweir     if (IsValid())
323cdf0e10cSrcweir         nCount += (m_bHasTextChild?1:0) + (m_bHasListChild?1:0);
324cdf0e10cSrcweir     else
325cdf0e10cSrcweir     {
326cdf0e10cSrcweir         // Object not valid anymore.  Release references to children.
327cdf0e10cSrcweir         m_bHasTextChild = false;
328cdf0e10cSrcweir         m_xText = NULL;
329cdf0e10cSrcweir         m_bHasListChild = false;
330cdf0e10cSrcweir         m_xList = NULL;
331cdf0e10cSrcweir     }
332cdf0e10cSrcweir 
333cdf0e10cSrcweir     return nCount;
334cdf0e10cSrcweir }
335cdf0e10cSrcweir 
336cdf0e10cSrcweir Reference<XAccessible> SAL_CALL VCLXAccessibleBox::getAccessibleChild (sal_Int32 i)
337cdf0e10cSrcweir     throw (IndexOutOfBoundsException, RuntimeException)
338cdf0e10cSrcweir {
339cdf0e10cSrcweir 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
340cdf0e10cSrcweir 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
341cdf0e10cSrcweir 
342cdf0e10cSrcweir 	if (i<0 || i>=getAccessibleChildCount())
343cdf0e10cSrcweir 		throw IndexOutOfBoundsException();
344cdf0e10cSrcweir 
345cdf0e10cSrcweir 	Reference< XAccessible > xChild;
346cdf0e10cSrcweir     if (IsValid())
347cdf0e10cSrcweir     {
348cdf0e10cSrcweir         if (i==1 || ! m_bHasTextChild)
349cdf0e10cSrcweir         {
350cdf0e10cSrcweir             // List.
351cdf0e10cSrcweir             if ( ! m_xList.is())
352cdf0e10cSrcweir             {
353cdf0e10cSrcweir                 VCLXAccessibleList* pList = new VCLXAccessibleList ( GetVCLXWindow(),
354cdf0e10cSrcweir 					(m_aBoxType == LISTBOX ? VCLXAccessibleList::LISTBOX : VCLXAccessibleList::COMBOBOX),
355cdf0e10cSrcweir 																	this);
356cdf0e10cSrcweir                 pList->SetIndexInParent (i);
357cdf0e10cSrcweir                 m_xList = pList;
358cdf0e10cSrcweir             }
359cdf0e10cSrcweir             xChild = m_xList;
360cdf0e10cSrcweir         }
361cdf0e10cSrcweir         else
362cdf0e10cSrcweir         {
363cdf0e10cSrcweir             // Text Field.
364cdf0e10cSrcweir             if ( ! m_xText.is())
365cdf0e10cSrcweir             {
366cdf0e10cSrcweir                 if (m_aBoxType==COMBOBOX)
367cdf0e10cSrcweir                 {
368cdf0e10cSrcweir                     ComboBox* pComboBox = static_cast<ComboBox*>(GetWindow());
369cdf0e10cSrcweir                     if (pComboBox!=NULL && pComboBox->GetSubEdit()!=NULL)
370*21075d77SSteve Yin 					//Set the edit's acc name the same as parent
371*21075d77SSteve Yin 					{
372*21075d77SSteve Yin 						pComboBox->GetSubEdit()->SetAccessibleName(getAccessibleName());
373cdf0e10cSrcweir                         m_xText = pComboBox->GetSubEdit()->GetAccessible();
374*21075d77SSteve Yin 					}
375cdf0e10cSrcweir                 }
376cdf0e10cSrcweir                 else if (m_bIsDropDownBox)
377cdf0e10cSrcweir                     m_xText = new VCLXAccessibleTextField (GetVCLXWindow(),this);
378cdf0e10cSrcweir             }
379cdf0e10cSrcweir             xChild = m_xText;
380cdf0e10cSrcweir         }
381cdf0e10cSrcweir     }
382cdf0e10cSrcweir 
383cdf0e10cSrcweir     return xChild;
384cdf0e10cSrcweir }
385cdf0e10cSrcweir 
386cdf0e10cSrcweir sal_Int16 SAL_CALL VCLXAccessibleBox::getAccessibleRole (void) throw (RuntimeException)
387cdf0e10cSrcweir {
388cdf0e10cSrcweir 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
389cdf0e10cSrcweir 
390cdf0e10cSrcweir     // Return the role <const>COMBO_BOX</const> for both VCL combo boxes and
391cdf0e10cSrcweir     // VCL list boxes in DropDown-Mode else <const>PANEL</const>.
392cdf0e10cSrcweir 	// This way the Java bridge has not to handle both independently.
393*21075d77SSteve Yin     //return m_bIsDropDownBox ? AccessibleRole::COMBO_BOX : AccessibleRole::PANEL;
394*21075d77SSteve Yin 	if (m_bIsDropDownBox || (!m_bIsDropDownBox && m_aBoxType == COMBOBOX ))
395*21075d77SSteve Yin 		return AccessibleRole::COMBO_BOX;
396*21075d77SSteve Yin 	else
397*21075d77SSteve Yin 		return AccessibleRole::PANEL;
398cdf0e10cSrcweir }
399cdf0e10cSrcweir 
400cdf0e10cSrcweir sal_Int32 SAL_CALL VCLXAccessibleBox::getAccessibleIndexInParent (void)
401cdf0e10cSrcweir     throw (::com::sun::star::uno::RuntimeException)
402cdf0e10cSrcweir {
403cdf0e10cSrcweir     if (m_nIndexInParent != DEFAULT_INDEX_IN_PARENT)
404cdf0e10cSrcweir         return m_nIndexInParent;
405cdf0e10cSrcweir     else
406cdf0e10cSrcweir         return VCLXAccessibleComponent::getAccessibleIndexInParent();
407cdf0e10cSrcweir }
408cdf0e10cSrcweir 
409cdf0e10cSrcweir //=====  XAccessibleAction  ===================================================
410cdf0e10cSrcweir 
411cdf0e10cSrcweir sal_Int32 SAL_CALL VCLXAccessibleBox::getAccessibleActionCount (void)
412cdf0e10cSrcweir     throw (RuntimeException)
413cdf0e10cSrcweir {
414cdf0e10cSrcweir 	::osl::Guard< ::osl::Mutex> aGuard (GetMutex());
415cdf0e10cSrcweir 
416cdf0e10cSrcweir     // There is one action for drop down boxes (toggle popup) and none for
417cdf0e10cSrcweir     // the other boxes.
418*21075d77SSteve Yin 	return m_bIsDropDownBox ? 0 : 1;
419cdf0e10cSrcweir }
420cdf0e10cSrcweir 
421cdf0e10cSrcweir sal_Bool SAL_CALL VCLXAccessibleBox::doAccessibleAction (sal_Int32 nIndex)
422cdf0e10cSrcweir     throw (IndexOutOfBoundsException, RuntimeException)
423cdf0e10cSrcweir {
424cdf0e10cSrcweir 	sal_Bool bNotify = sal_False;
425cdf0e10cSrcweir 
426cdf0e10cSrcweir 	{
427cdf0e10cSrcweir 		vos::OGuard aSolarGuard( Application::GetSolarMutex() );
428cdf0e10cSrcweir 		::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
429cdf0e10cSrcweir 
430cdf0e10cSrcweir         if (nIndex<0 || nIndex>=getAccessibleActionCount())
431cdf0e10cSrcweir             throw ::com::sun::star::lang::IndexOutOfBoundsException();
432cdf0e10cSrcweir 
433cdf0e10cSrcweir 		if (m_aBoxType == COMBOBOX)
434cdf0e10cSrcweir         {
435cdf0e10cSrcweir             ComboBox* pComboBox = static_cast< ComboBox* >( GetWindow() );
436cdf0e10cSrcweir             if (pComboBox != NULL)
437cdf0e10cSrcweir             {
438cdf0e10cSrcweir                 pComboBox->ToggleDropDown();
439cdf0e10cSrcweir                 bNotify = sal_True;
440cdf0e10cSrcweir             }
441cdf0e10cSrcweir         }
442cdf0e10cSrcweir         else if (m_aBoxType == LISTBOX)
443cdf0e10cSrcweir         {
444cdf0e10cSrcweir             ListBox* pListBox = static_cast< ListBox* >( GetWindow() );
445cdf0e10cSrcweir             if (pListBox != NULL)
446cdf0e10cSrcweir             {
447cdf0e10cSrcweir                 pListBox->ToggleDropDown();
448cdf0e10cSrcweir                 bNotify = sal_True;
449cdf0e10cSrcweir             }
450cdf0e10cSrcweir         }
451cdf0e10cSrcweir     }
452cdf0e10cSrcweir 
453cdf0e10cSrcweir 	if (bNotify)
454cdf0e10cSrcweir 		NotifyAccessibleEvent (AccessibleEventId::ACTION_CHANGED, Any(), Any());
455cdf0e10cSrcweir 
456cdf0e10cSrcweir 	return bNotify;
457cdf0e10cSrcweir }
458cdf0e10cSrcweir 
459cdf0e10cSrcweir ::rtl::OUString SAL_CALL VCLXAccessibleBox::getAccessibleActionDescription (sal_Int32 nIndex)
460cdf0e10cSrcweir     throw (IndexOutOfBoundsException, RuntimeException)
461cdf0e10cSrcweir {
462cdf0e10cSrcweir 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
463cdf0e10cSrcweir     if (nIndex<0 || nIndex>=getAccessibleActionCount())
464cdf0e10cSrcweir         throw ::com::sun::star::lang::IndexOutOfBoundsException();
465*21075d77SSteve Yin 	//Solution:When combo_box,it should not has action information.
466*21075d77SSteve Yin     //return TK_RES_STRING( RID_STR_ACC_ACTION_TOGGLEPOPUP);
467*21075d77SSteve Yin 	if (m_aBoxType == LISTBOX)
468*21075d77SSteve Yin 		return ::rtl::OUString();
469*21075d77SSteve Yin 	return m_bIsDropDownBox?::rtl::OUString():TK_RES_STRING( RID_STR_ACC_ACTION_TOGGLEPOPUP);
470cdf0e10cSrcweir }
471cdf0e10cSrcweir 
472cdf0e10cSrcweir Reference< XAccessibleKeyBinding > VCLXAccessibleBox::getAccessibleActionKeyBinding( sal_Int32 nIndex )
473cdf0e10cSrcweir 	throw (IndexOutOfBoundsException, RuntimeException)
474cdf0e10cSrcweir {
475cdf0e10cSrcweir 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
476cdf0e10cSrcweir 
477cdf0e10cSrcweir 	Reference< XAccessibleKeyBinding > xRet;
478cdf0e10cSrcweir 
479cdf0e10cSrcweir     if (nIndex<0 || nIndex>=getAccessibleActionCount())
480cdf0e10cSrcweir         throw ::com::sun::star::lang::IndexOutOfBoundsException();
481cdf0e10cSrcweir 
482cdf0e10cSrcweir 	// ... which key?
483cdf0e10cSrcweir 	return xRet;
484cdf0e10cSrcweir }
485cdf0e10cSrcweir 
486cdf0e10cSrcweir //=====  XComponent  ==========================================================
487cdf0e10cSrcweir 
488cdf0e10cSrcweir void SAL_CALL VCLXAccessibleBox::disposing (void)
489cdf0e10cSrcweir {
490cdf0e10cSrcweir 	VCLXAccessibleComponent::disposing();
491cdf0e10cSrcweir }
492cdf0e10cSrcweir 
493*21075d77SSteve Yin // =====  XAccessibleValue  ===============================================
494*21075d77SSteve Yin Any VCLXAccessibleBox::getCurrentValue( )
495*21075d77SSteve Yin     throw( RuntimeException )
496*21075d77SSteve Yin {
497*21075d77SSteve Yin 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
498*21075d77SSteve Yin 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
499*21075d77SSteve Yin 
500*21075d77SSteve Yin 	Any aAny;
501*21075d77SSteve Yin 	if( m_xList.is() && m_xText.is())
502*21075d77SSteve Yin 	{
503*21075d77SSteve Yin 		// VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
504*21075d77SSteve Yin 		Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
505*21075d77SSteve Yin 		if ( xText.is() )
506*21075d77SSteve Yin 		{
507*21075d77SSteve Yin 			::rtl::OUString sText = xText->getText();
508*21075d77SSteve Yin 			aAny <<= sText;
509*21075d77SSteve Yin 		}
510*21075d77SSteve Yin 	}
511*21075d77SSteve Yin 	if (m_aBoxType == LISTBOX && m_bIsDropDownBox  && m_xList.is() )
512*21075d77SSteve Yin 	{
513*21075d77SSteve Yin 
514*21075d77SSteve Yin 		VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
515*21075d77SSteve Yin 		if(pList->IsInDropDown())
516*21075d77SSteve Yin 		{
517*21075d77SSteve Yin 			if(pList->getSelectedAccessibleChildCount()>0)
518*21075d77SSteve Yin 			{
519*21075d77SSteve Yin 				Reference<XAccessibleContext> xName (pList->getSelectedAccessibleChild((sal_Int32)(0)), UNO_QUERY);
520*21075d77SSteve Yin 				if(xName.is())
521*21075d77SSteve Yin 				{
522*21075d77SSteve Yin 					aAny <<= xName->getAccessibleName();
523*21075d77SSteve Yin 				}
524*21075d77SSteve Yin 			}
525*21075d77SSteve Yin 		}
526*21075d77SSteve Yin 	}
527*21075d77SSteve Yin 
528*21075d77SSteve Yin     return aAny;
529*21075d77SSteve Yin }
530*21075d77SSteve Yin 
531*21075d77SSteve Yin sal_Bool VCLXAccessibleBox::setCurrentValue( const Any& aNumber )
532*21075d77SSteve Yin     throw( RuntimeException )
533*21075d77SSteve Yin {
534*21075d77SSteve Yin 	vos::OGuard aSolarGuard( Application::GetSolarMutex() );
535*21075d77SSteve Yin 	::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
536*21075d77SSteve Yin 
537*21075d77SSteve Yin     ::rtl::OUString  fValue;
538*21075d77SSteve Yin     sal_Bool bValid = (aNumber >>= fValue);
539*21075d77SSteve Yin     if( bValid )
540*21075d77SSteve Yin     {
541*21075d77SSteve Yin 
542*21075d77SSteve Yin     }
543*21075d77SSteve Yin     return bValid;
544*21075d77SSteve Yin 
545*21075d77SSteve Yin }
546*21075d77SSteve Yin 
547*21075d77SSteve Yin Any VCLXAccessibleBox::getMaximumValue( )
548*21075d77SSteve Yin     throw( RuntimeException )
549*21075d77SSteve Yin {
550*21075d77SSteve Yin     Any aAny;
551*21075d77SSteve Yin     return aAny;
552*21075d77SSteve Yin }
553*21075d77SSteve Yin 
554*21075d77SSteve Yin Any VCLXAccessibleBox::getMinimumValue(  )
555*21075d77SSteve Yin     throw( RuntimeException )
556*21075d77SSteve Yin {
557*21075d77SSteve Yin     Any aAny;
558*21075d77SSteve Yin     return aAny;
559*21075d77SSteve Yin }
560*21075d77SSteve Yin 
561*21075d77SSteve Yin // Set the INDETERMINATE state when there is no selected item for combobox
562*21075d77SSteve Yin void VCLXAccessibleBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
563*21075d77SSteve Yin {
564*21075d77SSteve Yin 	VCLXAccessibleComponent::FillAccessibleStateSet(rStateSet);
565*21075d77SSteve Yin 	if (m_aBoxType == COMBOBOX )
566*21075d77SSteve Yin 	{
567*21075d77SSteve Yin 		::rtl::OUString sText;
568*21075d77SSteve Yin 		sal_Int32 nEntryCount = 0;
569*21075d77SSteve Yin 		ComboBox* pComboBox = static_cast<ComboBox*>(GetWindow());
570*21075d77SSteve Yin 		if (pComboBox != NULL)
571*21075d77SSteve Yin 		{
572*21075d77SSteve Yin 			Edit* pSubEdit = pComboBox->GetSubEdit();
573*21075d77SSteve Yin 			if ( pSubEdit)
574*21075d77SSteve Yin 				sText = pSubEdit->GetText();
575*21075d77SSteve Yin 			nEntryCount = pComboBox->GetEntryCount();
576*21075d77SSteve Yin 		}
577*21075d77SSteve Yin 		if (sText.getLength() == 0 && nEntryCount >0)
578*21075d77SSteve Yin 			rStateSet.AddState(AccessibleStateType::INDETERMINATE);
579*21075d77SSteve Yin 	}
580*21075d77SSteve Yin 	else if (m_aBoxType == LISTBOX && m_bIsDropDownBox == true)
581*21075d77SSteve Yin 	{
582*21075d77SSteve Yin 		sal_Int32 nSelectedEntryCount = 0;
583*21075d77SSteve Yin 		ListBox* pListBox = static_cast< ListBox* >( GetWindow() );
584*21075d77SSteve Yin 		if (pListBox != NULL && pListBox->GetEntryCount() > 0)
585*21075d77SSteve Yin 		{
586*21075d77SSteve Yin 	        	nSelectedEntryCount = pListBox->GetSelectEntryCount();
587*21075d77SSteve Yin 			if ( nSelectedEntryCount == 0)
588*21075d77SSteve Yin 				rStateSet.AddState(AccessibleStateType::INDETERMINATE);
589*21075d77SSteve Yin 		}
590*21075d77SSteve Yin 	}
591*21075d77SSteve Yin }
592