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/vclxaccessibleradiobutton.hxx>
29 
30 #include <toolkit/awt/vclxwindows.hxx>
31 #include <accessibility/helper/accresmgr.hxx>
32 #include <accessibility/helper/accessiblestrings.hrc>
33 
34 #include <unotools/accessiblerelationsethelper.hxx>
35 #include <unotools/accessiblestatesethelper.hxx>
36 #include <comphelper/accessiblekeybindinghelper.hxx>
37 #include <com/sun/star/awt/KeyModifier.hpp>
38 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
39 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
40 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
41 #include <cppuhelper/typeprovider.hxx>
42 #include <comphelper/sequence.hxx>
43 #include <vcl/window.hxx>
44 #include <vcl/button.hxx>
45 
46 
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::uno;
49 using namespace ::com::sun::star::lang;
50 using namespace ::com::sun::star::beans;
51 using namespace ::com::sun::star::accessibility;
52 using namespace ::comphelper;
53 
54 
55 // -----------------------------------------------------------------------------
56 // VCLXAccessibleRadioButton
57 // -----------------------------------------------------------------------------
58 
59 VCLXAccessibleRadioButton::VCLXAccessibleRadioButton( VCLXWindow* pVCLWindow )
60 	:VCLXAccessibleTextComponent( pVCLWindow )
61 {
62 }
63 
64 // -----------------------------------------------------------------------------
65 
66 VCLXAccessibleRadioButton::~VCLXAccessibleRadioButton()
67 {
68 }
69 
70 // -----------------------------------------------------------------------------
71 
72 void VCLXAccessibleRadioButton::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
73 {
74     switch ( rVclWindowEvent.GetId() )
75     {
76 		case VCLEVENT_RADIOBUTTON_TOGGLE:
77         {
78 			Any aOldValue;
79 			Any aNewValue;
80 
81 			VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
82 			if ( pVCLXRadioButton && pVCLXRadioButton->getState() )
83 				aNewValue <<= AccessibleStateType::CHECKED;
84 			else
85 				aOldValue <<= AccessibleStateType::CHECKED;
86 
87             NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
88         }
89         break;
90 		default:
91 			VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
92    }
93 }
94 
95 // -----------------------------------------------------------------------------
96 
97 void VCLXAccessibleRadioButton::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
98 {
99     VCLXAccessibleTextComponent::FillAccessibleRelationSet( rRelationSet );
100 
101     RadioButton* pRadioButton = dynamic_cast< RadioButton* >( GetWindow() );
102     if ( pRadioButton )
103     {
104         ::std::vector< RadioButton* > aGroup;
105         pRadioButton->GetRadioButtonGroup( aGroup, true );
106         if ( !aGroup.empty() )
107         {
108             sal_Int32 i = 0;
109             Sequence< Reference< XInterface > > aSequence( static_cast< sal_Int32 >( aGroup.size() ) );
110             ::std::vector< RadioButton* >::const_iterator aEndItr = aGroup.end();
111             for ( ::std::vector< RadioButton* >::const_iterator aItr = aGroup.begin(); aItr < aEndItr; ++aItr )
112             {
113                 aSequence[i++] = (*aItr)->GetAccessible();
114             }
115             rRelationSet.AddRelation( AccessibleRelation( AccessibleRelationType::MEMBER_OF, aSequence ) );
116         }
117     }
118 }
119 
120 // -----------------------------------------------------------------------------
121 
122 void VCLXAccessibleRadioButton::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
123 {
124 	VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
125 
126 	VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
127 	if ( pVCLXRadioButton )
128 	{
129         rStateSet.AddState( AccessibleStateType::FOCUSABLE );
130 		if ( pVCLXRadioButton->getState() )
131             rStateSet.AddState( AccessibleStateType::CHECKED );
132 	}
133 }
134 
135 // -----------------------------------------------------------------------------
136 // XInterface
137 // -----------------------------------------------------------------------------
138 
139 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleRadioButton, VCLXAccessibleTextComponent, VCLXAccessibleRadioButton_BASE )
140 
141 // -----------------------------------------------------------------------------
142 // XTypeProvider
143 // -----------------------------------------------------------------------------
144 
145 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleRadioButton, VCLXAccessibleTextComponent, VCLXAccessibleRadioButton_BASE )
146 
147 // -----------------------------------------------------------------------------
148 // XServiceInfo
149 // -----------------------------------------------------------------------------
150 
151 ::rtl::OUString VCLXAccessibleRadioButton::getImplementationName() throw (RuntimeException)
152 {
153 	return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleRadioButton" );
154 }
155 
156 // -----------------------------------------------------------------------------
157 
158 Sequence< ::rtl::OUString > VCLXAccessibleRadioButton::getSupportedServiceNames() throw (RuntimeException)
159 {
160 	Sequence< ::rtl::OUString > aNames(1);
161 	aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleRadioButton" );
162 	return aNames;
163 }
164 
165 // -----------------------------------------------------------------------------
166 // XAccessibleAction
167 // -----------------------------------------------------------------------------
168 
169 sal_Int32 VCLXAccessibleRadioButton::getAccessibleActionCount( ) throw (RuntimeException)
170 {
171 	OExternalLockGuard aGuard( this );
172 
173 	return 1;
174 }
175 
176 // -----------------------------------------------------------------------------
177 
178 sal_Bool VCLXAccessibleRadioButton::doAccessibleAction ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
179 {
180 	OExternalLockGuard aGuard( this );
181 
182 	if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
183         throw IndexOutOfBoundsException();
184 
185 	VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
186 	if ( pVCLXRadioButton && !pVCLXRadioButton->getState() )
187 		pVCLXRadioButton->setState( sal_True );
188 
189 	return sal_True;
190 }
191 
192 // -----------------------------------------------------------------------------
193 
194 ::rtl::OUString VCLXAccessibleRadioButton::getAccessibleActionDescription ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
195 {
196 	OExternalLockGuard aGuard( this );
197 
198 	if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
199         throw IndexOutOfBoundsException();
200 
201 	return ::rtl::OUString( TK_RES_STRING( RID_STR_ACC_ACTION_CLICK ) );
202 }
203 
204 // -----------------------------------------------------------------------------
205 
206 Reference< XAccessibleKeyBinding > VCLXAccessibleRadioButton::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
207 {
208     OExternalLockGuard aGuard( this );
209 
210     if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
211         throw IndexOutOfBoundsException();
212 
213     OAccessibleKeyBindingHelper* pKeyBindingHelper = new OAccessibleKeyBindingHelper();
214     Reference< XAccessibleKeyBinding > xKeyBinding = pKeyBindingHelper;
215 
216     Window* pWindow = GetWindow();
217     if ( pWindow )
218     {
219         KeyEvent aKeyEvent = pWindow->GetActivationKey();
220         KeyCode aKeyCode = aKeyEvent.GetKeyCode();
221         if ( aKeyCode.GetCode() != 0 )
222         {
223             awt::KeyStroke aKeyStroke;
224             aKeyStroke.Modifiers = 0;
225             if ( aKeyCode.IsShift() )
226                 aKeyStroke.Modifiers |= awt::KeyModifier::SHIFT;
227             if ( aKeyCode.IsMod1() )
228                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD1;
229             if ( aKeyCode.IsMod2() )
230                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD2;
231             if ( aKeyCode.IsMod3() )
232                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD3;
233             aKeyStroke.KeyCode = aKeyCode.GetCode();
234             aKeyStroke.KeyChar = aKeyEvent.GetCharCode();
235             aKeyStroke.KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() );
236             pKeyBindingHelper->AddKeyBinding( aKeyStroke );
237         }
238     }
239 
240     return xKeyBinding;
241 }
242 
243 // -----------------------------------------------------------------------------
244 // XAccessibleValue
245 // -----------------------------------------------------------------------------
246 
247 Any VCLXAccessibleRadioButton::getCurrentValue(  ) throw (RuntimeException)
248 {
249 	OExternalLockGuard aGuard( this );
250 
251 	Any aValue;
252 
253 	VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
254 	if ( pVCLXRadioButton )
255 		aValue <<= (sal_Int32) pVCLXRadioButton->getState();
256 
257 	return aValue;
258 }
259 
260 // -----------------------------------------------------------------------------
261 
262 sal_Bool VCLXAccessibleRadioButton::setCurrentValue( const Any& aNumber ) throw (RuntimeException)
263 {
264 	OExternalLockGuard aGuard( this );
265 
266 	sal_Bool bReturn = sal_False;
267 
268 	VCLXRadioButton* pVCLXRadioButton = static_cast< VCLXRadioButton* >( GetVCLXWindow() );
269 	if ( pVCLXRadioButton )
270 	{
271 		sal_Int32 nValue = 0;
272 		OSL_VERIFY( aNumber >>= nValue );
273 
274 		if ( nValue < 0 )
275 			nValue = 0;
276 		else if ( nValue > 1 )
277 			nValue = 1;
278 
279 		pVCLXRadioButton->setState( (sal_Bool) nValue );
280 		bReturn = sal_True;
281 	}
282 
283 	return bReturn;
284 }
285 
286 // -----------------------------------------------------------------------------
287 
288 Any VCLXAccessibleRadioButton::getMaximumValue(  ) throw (RuntimeException)
289 {
290 	OExternalLockGuard aGuard( this );
291 
292 	Any aValue;
293 	aValue <<= (sal_Int32) 1;
294 
295 	return aValue;
296 }
297 
298 // -----------------------------------------------------------------------------
299 
300 Any VCLXAccessibleRadioButton::getMinimumValue(  ) throw (RuntimeException)
301 {
302 	OExternalLockGuard aGuard( this );
303 
304 	Any aValue;
305 	aValue <<= (sal_Int32) 0;
306 
307 	return aValue;
308 }
309 
310 // -----------------------------------------------------------------------------
311