1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_accessibility.hxx"
26 
27 // includes --------------------------------------------------------------
28 #include <accessibility/standard/vclxaccessiblecheckbox.hxx>
29 
30 #include <toolkit/awt/vclxwindows.hxx>
31 #include <accessibility/helper/accresmgr.hxx>
32 #include <accessibility/helper/accessiblestrings.hrc>
33 
34 #include <unotools/accessiblestatesethelper.hxx>
35 #include <comphelper/accessiblekeybindinghelper.hxx>
36 #include <com/sun/star/awt/KeyModifier.hpp>
37 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
38 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
39 #include <cppuhelper/typeprovider.hxx>
40 #include <comphelper/sequence.hxx>
41 
42 #include <vcl/button.hxx>
43 
44 using namespace ::com::sun::star;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::beans;
48 using namespace ::com::sun::star::accessibility;
49 using namespace ::comphelper;
50 
51 
52 // -----------------------------------------------------------------------------
53 // VCLXAccessibleCheckBox
54 // -----------------------------------------------------------------------------
55 
56 VCLXAccessibleCheckBox::VCLXAccessibleCheckBox( VCLXWindow* pVCLWindow )
57 	:VCLXAccessibleTextComponent( pVCLWindow )
58 {
59     m_bChecked = IsChecked();
60     m_bIndeterminate = IsIndeterminate();
61 }
62 
63 // -----------------------------------------------------------------------------
64 
65 VCLXAccessibleCheckBox::~VCLXAccessibleCheckBox()
66 {
67 }
68 
69 // -----------------------------------------------------------------------------
70 
71 bool VCLXAccessibleCheckBox::IsChecked()
72 {
73     bool bChecked = false;
74 
75     VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
76     if ( pVCLXCheckBox && pVCLXCheckBox->getState() == (sal_Int16) 1 )
77         bChecked = true;
78 
79     return bChecked;
80 }
81 
82 // -----------------------------------------------------------------------------
83 
84 bool VCLXAccessibleCheckBox::IsIndeterminate()
85 {
86     bool bIndeterminate = false;
87 
88     VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
89     if ( pVCLXCheckBox && pVCLXCheckBox->getState() == (sal_Int16) 2 )
90         bIndeterminate = true;
91 
92     return bIndeterminate;
93 }
94 
95 // -----------------------------------------------------------------------------
96 
97 void VCLXAccessibleCheckBox::SetChecked( bool bChecked )
98 {
99 	if ( m_bChecked != bChecked )
100 	{
101 		Any aOldValue, aNewValue;
102 		if ( m_bChecked )
103 			aOldValue <<= AccessibleStateType::CHECKED;
104 		else
105 			aNewValue <<= AccessibleStateType::CHECKED;
106 		m_bChecked = bChecked;
107 		NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
108 	}
109 }
110 
111 // -----------------------------------------------------------------------------
112 
113 void VCLXAccessibleCheckBox::SetIndeterminate( bool bIndeterminate )
114 {
115 	if ( m_bIndeterminate != bIndeterminate )
116 	{
117 		Any aOldValue, aNewValue;
118 		if ( m_bIndeterminate )
119 			aOldValue <<= AccessibleStateType::INDETERMINATE;
120 		else
121 			aNewValue <<= AccessibleStateType::INDETERMINATE;
122 		m_bIndeterminate = bIndeterminate;
123 		NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
124 	}
125 }
126 
127 // -----------------------------------------------------------------------------
128 
129 void VCLXAccessibleCheckBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
130 {
131     switch ( rVclWindowEvent.GetId() )
132     {
133 		case VCLEVENT_CHECKBOX_TOGGLE:
134         {
135             SetChecked( IsChecked() );
136             SetIndeterminate( IsIndeterminate() );
137         }
138         break;
139 		default:
140 			VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
141    }
142 }
143 
144 // -----------------------------------------------------------------------------
145 
146 void VCLXAccessibleCheckBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
147 {
148 	VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
149 
150     rStateSet.AddState( AccessibleStateType::FOCUSABLE );
151 
152     if ( IsChecked() )
153         rStateSet.AddState( AccessibleStateType::CHECKED );
154 
155     if ( IsIndeterminate() )
156         rStateSet.AddState( AccessibleStateType::INDETERMINATE );
157 }
158 
159 // -----------------------------------------------------------------------------
160 // XInterface
161 // -----------------------------------------------------------------------------
162 
163 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleCheckBox, VCLXAccessibleTextComponent, VCLXAccessibleCheckBox_BASE )
164 
165 // -----------------------------------------------------------------------------
166 // XTypeProvider
167 // -----------------------------------------------------------------------------
168 
169 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleCheckBox, VCLXAccessibleTextComponent, VCLXAccessibleCheckBox_BASE )
170 
171 // -----------------------------------------------------------------------------
172 // XServiceInfo
173 // -----------------------------------------------------------------------------
174 
175 ::rtl::OUString VCLXAccessibleCheckBox::getImplementationName() throw (RuntimeException)
176 {
177 	return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleCheckBox" );
178 }
179 
180 // -----------------------------------------------------------------------------
181 
182 Sequence< ::rtl::OUString > VCLXAccessibleCheckBox::getSupportedServiceNames() throw (RuntimeException)
183 {
184 	Sequence< ::rtl::OUString > aNames(1);
185 	aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleCheckBox" );
186 	return aNames;
187 }
188 
189 // -----------------------------------------------------------------------------
190 // XAccessibleAction
191 // -----------------------------------------------------------------------------
192 
193 sal_Int32 VCLXAccessibleCheckBox::getAccessibleActionCount( ) throw (RuntimeException)
194 {
195 	OExternalLockGuard aGuard( this );
196 
197 	return 1;
198 }
199 
200 // -----------------------------------------------------------------------------
201 
202 sal_Bool VCLXAccessibleCheckBox::doAccessibleAction ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
203 {
204 	OExternalLockGuard aGuard( this );
205 
206 	if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
207         throw IndexOutOfBoundsException();
208 
209 	CheckBox* pCheckBox = (CheckBox*) GetWindow();
210 	VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
211 	if ( pCheckBox && pVCLXCheckBox )
212 	{
213 		sal_Int32 nValueMin = (sal_Int32) 0;
214 		sal_Int32 nValueMax = (sal_Int32) 1;
215 
216 		if ( pCheckBox->IsTriStateEnabled() )
217 			nValueMax = (sal_Int32) 2;
218 
219 		sal_Int32 nValue = (sal_Int32) pVCLXCheckBox->getState();
220 
221 		++nValue;
222 
223 		if ( nValue > nValueMax )
224 			nValue = nValueMin;
225 
226 		pVCLXCheckBox->setState( (sal_Int16) nValue );
227 	}
228 
229 	return sal_True;
230 }
231 
232 // -----------------------------------------------------------------------------
233 
234 ::rtl::OUString VCLXAccessibleCheckBox::getAccessibleActionDescription ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
235 {
236 	OExternalLockGuard aGuard( this );
237 
238 	if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
239         throw IndexOutOfBoundsException();
240 
241 	return ::rtl::OUString( TK_RES_STRING( RID_STR_ACC_ACTION_CLICK ) );
242 }
243 
244 // -----------------------------------------------------------------------------
245 
246 Reference< XAccessibleKeyBinding > VCLXAccessibleCheckBox::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
247 {
248     OExternalLockGuard aGuard( this );
249 
250     if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
251         throw IndexOutOfBoundsException();
252 
253     OAccessibleKeyBindingHelper* pKeyBindingHelper = new OAccessibleKeyBindingHelper();
254     Reference< XAccessibleKeyBinding > xKeyBinding = pKeyBindingHelper;
255 
256     Window* pWindow = GetWindow();
257     if ( pWindow )
258     {
259         KeyEvent aKeyEvent = pWindow->GetActivationKey();
260         KeyCode aKeyCode = aKeyEvent.GetKeyCode();
261         if ( aKeyCode.GetCode() != 0 )
262         {
263             awt::KeyStroke aKeyStroke;
264             aKeyStroke.Modifiers = 0;
265             if ( aKeyCode.IsShift() )
266                 aKeyStroke.Modifiers |= awt::KeyModifier::SHIFT;
267             if ( aKeyCode.IsMod1() )
268                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD1;
269             if ( aKeyCode.IsMod2() )
270                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD2;
271             if ( aKeyCode.IsMod3() )
272                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD3;
273             aKeyStroke.KeyCode = aKeyCode.GetCode();
274             aKeyStroke.KeyChar = aKeyEvent.GetCharCode();
275             aKeyStroke.KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() );
276             pKeyBindingHelper->AddKeyBinding( aKeyStroke );
277         }
278     }
279 
280     return xKeyBinding;
281 }
282 
283 // -----------------------------------------------------------------------------
284 // XAccessibleValue
285 // -----------------------------------------------------------------------------
286 
287 Any VCLXAccessibleCheckBox::getCurrentValue(  ) throw (RuntimeException)
288 {
289 	OExternalLockGuard aGuard( this );
290 
291 	Any aValue;
292 
293 	VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
294 	if ( pVCLXCheckBox )
295 		aValue <<= (sal_Int32) pVCLXCheckBox->getState();
296 
297 	return aValue;
298 }
299 
300 // -----------------------------------------------------------------------------
301 
302 sal_Bool VCLXAccessibleCheckBox::setCurrentValue( const Any& aNumber ) throw (RuntimeException)
303 {
304 	OExternalLockGuard aGuard( this );
305 
306 	sal_Bool bReturn = sal_False;
307 
308 	VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
309 	if ( pVCLXCheckBox )
310 	{
311 		sal_Int32 nValue = 0, nValueMin = 0, nValueMax = 0;
312 		OSL_VERIFY( aNumber >>= nValue );
313 		OSL_VERIFY( getMinimumValue() >>= nValueMin );
314 		OSL_VERIFY( getMaximumValue() >>= nValueMax );
315 
316 		if ( nValue < nValueMin )
317 			nValue = nValueMin;
318 		else if ( nValue > nValueMax )
319 			nValue = nValueMax;
320 
321 		pVCLXCheckBox->setState( (sal_Int16) nValue );
322 		bReturn = sal_True;
323 	}
324 
325 	return bReturn;
326 }
327 
328 // -----------------------------------------------------------------------------
329 
330 Any VCLXAccessibleCheckBox::getMaximumValue(  ) throw (RuntimeException)
331 {
332 	OExternalLockGuard aGuard( this );
333 
334 	Any aValue;
335 
336 	CheckBox* pCheckBox = (CheckBox*) GetWindow();
337 	if ( pCheckBox && pCheckBox->IsTriStateEnabled() )
338 		aValue <<= (sal_Int32) 2;
339 	else
340 		aValue <<= (sal_Int32) 1;
341 
342 	return aValue;
343 }
344 
345 // -----------------------------------------------------------------------------
346 
347 Any VCLXAccessibleCheckBox::getMinimumValue(  ) throw (RuntimeException)
348 {
349 	OExternalLockGuard aGuard( this );
350 
351 	Any aValue;
352 	aValue <<= (sal_Int32) 0;
353 
354 	return aValue;
355 }
356 
357 // -----------------------------------------------------------------------------
358