Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <accessibility/standard/vclxaccessiblebox.hxx>
30 : : #include <accessibility/standard/vclxaccessibletextfield.hxx>
31 : : #include <accessibility/standard/vclxaccessibleedit.hxx>
32 : : #include <accessibility/standard/vclxaccessiblelist.hxx>
33 : : #include <accessibility/helper/listboxhelper.hxx>
34 : :
35 : : #include <unotools/accessiblestatesethelper.hxx>
36 : : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
37 : : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
38 : : #include <com/sun/star/accessibility/AccessibleRole.hpp>
39 : : #include <vcl/svapp.hxx>
40 : : #include <vcl/combobox.hxx>
41 : : #include <vcl/lstbox.hxx>
42 : : #include <accessibility/helper/accresmgr.hxx>
43 : : #include <accessibility/helper/accessiblestrings.hrc>
44 : :
45 : : using namespace ::com::sun::star;
46 : : using namespace ::com::sun::star::uno;
47 : : using namespace ::com::sun::star::lang;
48 : : using namespace ::com::sun::star::beans;
49 : : using namespace ::com::sun::star::accessibility;
50 : :
51 : 16 : VCLXAccessibleBox::VCLXAccessibleBox (VCLXWindow* pVCLWindow, BoxType aType, bool bIsDropDownBox)
52 : : : VCLXAccessibleComponent (pVCLWindow),
53 : : m_aBoxType (aType),
54 : : m_bIsDropDownBox (bIsDropDownBox),
55 : 16 : m_nIndexInParent (DEFAULT_INDEX_IN_PARENT)
56 : : {
57 : : // Set up the flags that indicate which children this object has.
58 : 16 : m_bHasListChild = true;
59 : :
60 : : // A text field is not present for non drop down list boxes.
61 [ - + ][ + + ]: 16 : if ((m_aBoxType==LISTBOX) && ! m_bIsDropDownBox)
62 : 0 : m_bHasTextChild = false;
63 : : else
64 : 16 : m_bHasTextChild = true;
65 : 16 : }
66 : :
67 : 0 : VCLXAccessibleBox::~VCLXAccessibleBox (void)
68 : : {
69 [ # # ]: 0 : }
70 : :
71 : 268 : void VCLXAccessibleBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
72 : : {
73 : 268 : uno::Any aOldValue, aNewValue;
74 : 268 : uno::Reference<XAccessible> xAcc;
75 : :
76 [ + + ]: 268 : switch ( rVclWindowEvent.GetId() )
77 : : {
78 : : case VCLEVENT_WINDOW_SHOW:
79 : : case VCLEVENT_WINDOW_HIDE:
80 : : {
81 : 78 : Window* pChildWindow = (Window *) rVclWindowEvent.GetData();
82 : : // Just compare to the combo box text field. All other children
83 : : // are identical to this object in which case this object will
84 : : // be removed in a short time.
85 [ + + ]: 78 : if (m_aBoxType==COMBOBOX)
86 : : {
87 [ + - ]: 50 : ComboBox* pComboBox = static_cast<ComboBox*>(GetWindow());
88 [ + - ][ + + ]: 50 : if ( ( pComboBox != NULL ) && ( pChildWindow != NULL ) )
89 [ - + ]: 30 : if (pChildWindow == pComboBox->GetSubEdit())
90 : : {
91 [ # # ]: 0 : if (rVclWindowEvent.GetId() == VCLEVENT_WINDOW_SHOW)
92 : : {
93 : : // Instantiate text field.
94 [ # # ]: 0 : getAccessibleChild (0);
95 [ # # ]: 0 : aNewValue <<= m_xText;
96 : : }
97 : : else
98 : : {
99 : : // Release text field.
100 [ # # ]: 0 : aOldValue <<= m_xText;
101 [ # # ]: 0 : m_xText = NULL;
102 : : }
103 : : // Tell the listeners about the new/removed child.
104 : : NotifyAccessibleEvent (
105 : : AccessibleEventId::CHILD,
106 [ # # ]: 0 : aOldValue, aNewValue);
107 : : }
108 : :
109 : : }
110 : : }
111 : 78 : break;
112 : :
113 : : default:
114 [ + - ]: 190 : VCLXAccessibleComponent::ProcessWindowChildEvent (rVclWindowEvent);
115 : 268 : }
116 : 268 : }
117 : :
118 : 74 : void VCLXAccessibleBox::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent)
119 : : {
120 [ + - + + ]: 74 : switch ( rVclWindowEvent.GetId() )
121 : : {
122 : : case VCLEVENT_DROPDOWN_OPEN:
123 : : case VCLEVENT_DROPDOWN_CLOSE:
124 : : case VCLEVENT_LISTBOX_DOUBLECLICK:
125 : : case VCLEVENT_LISTBOX_SCROLLED:
126 : : case VCLEVENT_LISTBOX_SELECT:
127 : : case VCLEVENT_LISTBOX_ITEMADDED:
128 : : case VCLEVENT_LISTBOX_ITEMREMOVED:
129 : : case VCLEVENT_COMBOBOX_ITEMADDED:
130 : : case VCLEVENT_COMBOBOX_ITEMREMOVED:
131 : : case VCLEVENT_COMBOBOX_SCROLLED:
132 : : {
133 : : // Forward the call to the list child.
134 [ + + ]: 6 : VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
135 [ + + ]: 6 : if ( pList == NULL )
136 : : {
137 [ + - ]: 2 : getAccessibleChild ( m_bHasTextChild ? 1 : 0 );
138 [ + - ]: 2 : pList = static_cast<VCLXAccessibleList*>(m_xList.get());
139 : : }
140 [ + - ]: 6 : if ( pList != NULL )
141 : 6 : pList->ProcessWindowEvent (rVclWindowEvent);
142 : 6 : break;
143 : : }
144 : :
145 : : case VCLEVENT_COMBOBOX_SELECT:
146 : : case VCLEVENT_COMBOBOX_DESELECT:
147 : : {
148 : : // Selection is handled by VCLXAccessibleList which operates on
149 : : // the same VCL object as this box does. In case of the
150 : : // combobox, however, we have to help by providing the list with
151 : : // the text of the currently selected item.
152 [ # # ]: 0 : VCLXAccessibleList* pList = static_cast<VCLXAccessibleList*>(m_xList.get());
153 [ # # ][ # # ]: 0 : if (pList != NULL && m_xText.is())
[ # # ]
154 : : {
155 [ # # ][ # # ]: 0 : Reference<XAccessibleText> xText (m_xText->getAccessibleContext(), UNO_QUERY);
[ # # ]
156 [ # # ]: 0 : if ( xText.is() )
157 : : {
158 [ # # ][ # # ]: 0 : ::rtl::OUString sText = xText->getSelectedText();
159 [ # # ]: 0 : if ( sText.isEmpty() )
160 [ # # ][ # # ]: 0 : sText = xText->getText();
161 [ # # ]: 0 : pList->UpdateSelection (sText);
162 : 0 : }
163 : : }
164 : 0 : break;
165 : : }
166 : :
167 : : case VCLEVENT_EDIT_MODIFY:
168 : : case VCLEVENT_EDIT_SELECTIONCHANGED:
169 : : // Modify/Selection events are handled by the combo box instead of
170 : : // directly by the edit field (Why?). Therefore, delegate this
171 : : // call to the edit field.
172 [ + - ]: 2 : if (m_aBoxType==COMBOBOX)
173 : : {
174 [ - + ]: 2 : if (m_xText.is())
175 : : {
176 [ # # ][ # # ]: 0 : Reference<XAccessibleContext> xContext = m_xText->getAccessibleContext();
177 [ # # ][ # # ]: 0 : VCLXAccessibleEdit* pEdit = static_cast<VCLXAccessibleEdit*>(xContext.get());
178 [ # # ]: 0 : if (pEdit != NULL)
179 [ # # ]: 0 : pEdit->ProcessWindowEvent (rVclWindowEvent);
180 : : }
181 : : }
182 : 2 : break;
183 : :
184 : : default:
185 : 66 : VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
186 : : }
187 : 74 : }
188 : :
189 [ + + ][ + - ]: 2090 : IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleBox, VCLXAccessibleComponent, VCLXAccessibleBox_BASE)
190 [ # # ][ # # ]: 0 : IMPLEMENT_FORWARD_XTYPEPROVIDER2(VCLXAccessibleBox, VCLXAccessibleComponent, VCLXAccessibleBox_BASE)
[ # # ]
191 : :
192 : : //===== XAccessible =========================================================
193 : :
194 : 16 : Reference< XAccessibleContext > SAL_CALL VCLXAccessibleBox::getAccessibleContext( )
195 : : throw (RuntimeException)
196 : : {
197 [ + - ]: 16 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
198 : :
199 [ + - ][ + - ]: 16 : return this;
200 : : }
201 : :
202 : : //===== XAccessibleContext ==================================================
203 : :
204 : 118 : sal_Int32 SAL_CALL VCLXAccessibleBox::getAccessibleChildCount (void)
205 : : throw (RuntimeException)
206 : : {
207 [ + - ]: 118 : SolarMutexGuard aSolarGuard;
208 [ + - ]: 118 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
209 : :
210 : : // Usually a box has a text field and a list of items as its children.
211 : : // Non drop down list boxes have no text field. Additionally check
212 : : // whether the object is valid.
213 : 118 : sal_Int32 nCount = 0;
214 [ + - ][ + - ]: 118 : if (IsValid())
215 [ + - ][ + - ]: 118 : nCount += (m_bHasTextChild?1:0) + (m_bHasListChild?1:0);
216 : : else
217 : : {
218 : : // Object not valid anymore. Release references to children.
219 : 0 : m_bHasTextChild = false;
220 [ # # ]: 0 : m_xText = NULL;
221 : 0 : m_bHasListChild = false;
222 [ # # ]: 0 : m_xList = NULL;
223 : : }
224 : :
225 [ + - ][ + - ]: 118 : return nCount;
226 : : }
227 : :
228 : 54 : Reference<XAccessible> SAL_CALL VCLXAccessibleBox::getAccessibleChild (sal_Int32 i)
229 : : throw (IndexOutOfBoundsException, RuntimeException)
230 : : {
231 [ + - ]: 54 : SolarMutexGuard aSolarGuard;
232 [ + - ]: 54 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
233 : :
234 [ + - ][ + - ]: 54 : if (i<0 || i>=getAccessibleChildCount())
[ - + ][ - + ]
235 [ # # ]: 0 : throw IndexOutOfBoundsException();
236 : :
237 : 54 : Reference< XAccessible > xChild;
238 [ + - ][ + - ]: 54 : if (IsValid())
239 : : {
240 [ + + ][ - + ]: 54 : if (i==1 || ! m_bHasTextChild)
241 : : {
242 : : // List.
243 [ + + ]: 26 : if ( ! m_xList.is())
244 : : {
245 : 16 : VCLXAccessibleList* pList = new VCLXAccessibleList ( GetVCLXWindow(),
246 : : (m_aBoxType == LISTBOX ? VCLXAccessibleList::LISTBOX : VCLXAccessibleList::COMBOBOX),
247 [ + - ][ + + ]: 16 : this);
[ + - ]
248 [ + - ]: 16 : pList->SetIndexInParent (i);
249 [ + - ][ + - ]: 16 : m_xList = pList;
250 : : }
251 [ + - ]: 26 : xChild = m_xList;
252 : : }
253 : : else
254 : : {
255 : : // Text Field.
256 [ + + ]: 28 : if ( ! m_xText.is())
257 : : {
258 [ + + ]: 16 : if (m_aBoxType==COMBOBOX)
259 : : {
260 [ + - ]: 10 : ComboBox* pComboBox = static_cast<ComboBox*>(GetWindow());
261 [ + - ][ + - ]: 10 : if (pComboBox!=NULL && pComboBox->GetSubEdit()!=NULL)
[ + - ]
262 [ + - ][ + - ]: 10 : m_xText = pComboBox->GetSubEdit()->GetAccessible();
263 : : }
264 [ + - ]: 6 : else if (m_bIsDropDownBox)
265 [ + - ][ + - ]: 6 : m_xText = new VCLXAccessibleTextField (GetVCLXWindow(),this);
[ + - ][ + - ]
266 : : }
267 [ + - ]: 54 : xChild = m_xText;
268 : : }
269 : : }
270 : :
271 [ + - ][ + - ]: 54 : return xChild;
272 : : }
273 : :
274 : 78 : sal_Int16 SAL_CALL VCLXAccessibleBox::getAccessibleRole (void) throw (RuntimeException)
275 : : {
276 [ + - ]: 78 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
277 : :
278 : : // Return the role <const>COMBO_BOX</const> for both VCL combo boxes and
279 : : // VCL list boxes in DropDown-Mode else <const>PANEL</const>.
280 : : // This way the Java bridge has not to handle both independently.
281 [ + - ][ + - ]: 78 : return m_bIsDropDownBox ? AccessibleRole::COMBO_BOX : AccessibleRole::PANEL;
282 : : }
283 : :
284 : 2 : sal_Int32 SAL_CALL VCLXAccessibleBox::getAccessibleIndexInParent (void)
285 : : throw (::com::sun::star::uno::RuntimeException)
286 : : {
287 [ - + ]: 2 : if (m_nIndexInParent != DEFAULT_INDEX_IN_PARENT)
288 : 0 : return m_nIndexInParent;
289 : : else
290 : 2 : return VCLXAccessibleComponent::getAccessibleIndexInParent();
291 : : }
292 : :
293 : : //===== XAccessibleAction ===================================================
294 : :
295 : 40 : sal_Int32 SAL_CALL VCLXAccessibleBox::getAccessibleActionCount (void)
296 : : throw (RuntimeException)
297 : : {
298 [ + - ]: 40 : ::osl::Guard< ::osl::Mutex> aGuard (GetMutex());
299 : :
300 : : // There is one action for drop down boxes (toggle popup) and none for
301 : : // the other boxes.
302 [ + - ][ + - ]: 40 : return m_bIsDropDownBox ? 1 : 0;
303 : : }
304 : :
305 : 16 : sal_Bool SAL_CALL VCLXAccessibleBox::doAccessibleAction (sal_Int32 nIndex)
306 : : throw (IndexOutOfBoundsException, RuntimeException)
307 : : {
308 : 16 : sal_Bool bNotify = sal_False;
309 : :
310 : : {
311 [ + - ]: 16 : SolarMutexGuard aSolarGuard;
312 [ + - ]: 16 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
313 : :
314 [ + - ][ + - ]: 16 : if (nIndex<0 || nIndex>=getAccessibleActionCount())
[ + + ][ + + ]
315 [ + - ]: 4 : throw ::com::sun::star::lang::IndexOutOfBoundsException();
316 : :
317 [ + + ]: 12 : if (m_aBoxType == COMBOBOX)
318 : : {
319 [ + - ]: 6 : ComboBox* pComboBox = static_cast< ComboBox* >( GetWindow() );
320 [ + - ]: 6 : if (pComboBox != NULL)
321 : : {
322 [ + - ]: 6 : pComboBox->ToggleDropDown();
323 : 6 : bNotify = sal_True;
324 : : }
325 : : }
326 [ + - ]: 6 : else if (m_aBoxType == LISTBOX)
327 : : {
328 [ + - ]: 6 : ListBox* pListBox = static_cast< ListBox* >( GetWindow() );
329 [ + - ]: 6 : if (pListBox != NULL)
330 : : {
331 [ + - ]: 6 : pListBox->ToggleDropDown();
332 : 6 : bNotify = sal_True;
333 : : }
334 [ + - ][ + - ]: 16 : }
335 : : }
336 : :
337 [ + - ]: 12 : if (bNotify)
338 [ + - ]: 12 : NotifyAccessibleEvent (AccessibleEventId::ACTION_CHANGED, Any(), Any());
339 : :
340 : 12 : return bNotify;
341 : : }
342 : :
343 : 12 : ::rtl::OUString SAL_CALL VCLXAccessibleBox::getAccessibleActionDescription (sal_Int32 nIndex)
344 : : throw (IndexOutOfBoundsException, RuntimeException)
345 : : {
346 [ + - ]: 12 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
347 [ + - ][ + - ]: 12 : if (nIndex<0 || nIndex>=getAccessibleActionCount())
[ + + ][ + + ]
348 [ + - ]: 4 : throw ::com::sun::star::lang::IndexOutOfBoundsException();
349 [ + - ][ + - ]: 12 : return TK_RES_STRING( RID_STR_ACC_ACTION_TOGGLEPOPUP);
350 : : }
351 : :
352 : 8 : Reference< XAccessibleKeyBinding > VCLXAccessibleBox::getAccessibleActionKeyBinding( sal_Int32 nIndex )
353 : : throw (IndexOutOfBoundsException, RuntimeException)
354 : : {
355 [ + - ]: 8 : ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
356 : :
357 : 8 : Reference< XAccessibleKeyBinding > xRet;
358 : :
359 [ + - ][ + + ]: 8 : if (nIndex<0 || nIndex>=getAccessibleActionCount())
[ + + ][ + - ]
360 [ + - ]: 4 : throw ::com::sun::star::lang::IndexOutOfBoundsException();
361 : :
362 : : // ... which key?
363 [ + - ]: 8 : return xRet;
364 : : }
365 : :
366 : : //===== XComponent ==========================================================
367 : :
368 : 16 : void SAL_CALL VCLXAccessibleBox::disposing (void)
369 : : {
370 : 16 : VCLXAccessibleComponent::disposing();
371 : 16 : }
372 : :
373 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|