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