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 	if(IsChecked())
242 		return ::rtl::OUString( TK_RES_STRING( RID_STR_ACC_ACTION_UNCHECK ) );
243 	else
244 		return ::rtl::OUString( TK_RES_STRING( RID_STR_ACC_ACTION_CHECK ) );
245 }
246 
247 // -----------------------------------------------------------------------------
248 
249 Reference< XAccessibleKeyBinding > VCLXAccessibleCheckBox::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
250 {
251     OExternalLockGuard aGuard( this );
252 
253     if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
254         throw IndexOutOfBoundsException();
255 
256     OAccessibleKeyBindingHelper* pKeyBindingHelper = new OAccessibleKeyBindingHelper();
257     Reference< XAccessibleKeyBinding > xKeyBinding = pKeyBindingHelper;
258 
259     Window* pWindow = GetWindow();
260     if ( pWindow )
261     {
262         KeyEvent aKeyEvent = pWindow->GetActivationKey();
263         KeyCode aKeyCode = aKeyEvent.GetKeyCode();
264         if ( aKeyCode.GetCode() != 0 )
265         {
266             awt::KeyStroke aKeyStroke;
267             aKeyStroke.Modifiers = 0;
268             if ( aKeyCode.IsShift() )
269                 aKeyStroke.Modifiers |= awt::KeyModifier::SHIFT;
270             if ( aKeyCode.IsMod1() )
271                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD1;
272             if ( aKeyCode.IsMod2() )
273                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD2;
274             if ( aKeyCode.IsMod3() )
275                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD3;
276             aKeyStroke.KeyCode = aKeyCode.GetCode();
277             aKeyStroke.KeyChar = aKeyEvent.GetCharCode();
278             aKeyStroke.KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() );
279             pKeyBindingHelper->AddKeyBinding( aKeyStroke );
280         }
281     }
282 
283     return xKeyBinding;
284 }
285 
286 // -----------------------------------------------------------------------------
287 // XAccessibleValue
288 // -----------------------------------------------------------------------------
289 
290 Any VCLXAccessibleCheckBox::getCurrentValue(  ) throw (RuntimeException)
291 {
292 	OExternalLockGuard aGuard( this );
293 
294 	Any aValue;
295 
296 	VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
297 	if ( pVCLXCheckBox )
298 		aValue <<= (sal_Int32) pVCLXCheckBox->getState();
299 
300 	return aValue;
301 }
302 
303 // -----------------------------------------------------------------------------
304 
305 sal_Bool VCLXAccessibleCheckBox::setCurrentValue( const Any& aNumber ) throw (RuntimeException)
306 {
307 	OExternalLockGuard aGuard( this );
308 
309 	sal_Bool bReturn = sal_False;
310 
311 	VCLXCheckBox* pVCLXCheckBox = static_cast< VCLXCheckBox* >( GetVCLXWindow() );
312 	if ( pVCLXCheckBox )
313 	{
314 		sal_Int32 nValue = 0, nValueMin = 0, nValueMax = 0;
315 		OSL_VERIFY( aNumber >>= nValue );
316 		OSL_VERIFY( getMinimumValue() >>= nValueMin );
317 		OSL_VERIFY( getMaximumValue() >>= nValueMax );
318 
319 		if ( nValue < nValueMin )
320 			nValue = nValueMin;
321 		else if ( nValue > nValueMax )
322 			nValue = nValueMax;
323 
324 		pVCLXCheckBox->setState( (sal_Int16) nValue );
325 		bReturn = sal_True;
326 	}
327 
328 	return bReturn;
329 }
330 
331 // -----------------------------------------------------------------------------
332 
333 Any VCLXAccessibleCheckBox::getMaximumValue(  ) throw (RuntimeException)
334 {
335 	OExternalLockGuard aGuard( this );
336 
337 	Any aValue;
338 
339 	CheckBox* pCheckBox = (CheckBox*) GetWindow();
340 	if ( pCheckBox && pCheckBox->IsTriStateEnabled() )
341 		aValue <<= (sal_Int32) 2;
342 	else
343 		aValue <<= (sal_Int32) 1;
344 
345 	return aValue;
346 }
347 
348 // -----------------------------------------------------------------------------
349 
350 Any VCLXAccessibleCheckBox::getMinimumValue(  ) throw (RuntimeException)
351 {
352 	OExternalLockGuard aGuard( this );
353 
354 	Any aValue;
355 	aValue <<= (sal_Int32) 0;
356 
357 	return aValue;
358 }
359 
360 // -----------------------------------------------------------------------------
361