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/vclxaccessiblebutton.hxx>
29 #include <accessibility/helper/accresmgr.hxx>
30 #include <accessibility/helper/accessiblestrings.hrc>
31 
32 #include <unotools/accessiblestatesethelper.hxx>
33 #include <comphelper/accessiblekeybindinghelper.hxx>
34 #include <com/sun/star/awt/KeyModifier.hpp>
35 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
36 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
37 #include <cppuhelper/typeprovider.hxx>
38 #include <comphelper/sequence.hxx>
39 
40 #include <vcl/button.hxx>
41 
42 using namespace ::com::sun::star;
43 using namespace ::com::sun::star::uno;
44 using namespace ::com::sun::star::lang;
45 using namespace ::com::sun::star::beans;
46 using namespace ::com::sun::star::accessibility;
47 using namespace ::comphelper;
48 
49 
50 // -----------------------------------------------------------------------------
51 // VCLXAccessibleButton
52 // -----------------------------------------------------------------------------
53 
54 VCLXAccessibleButton::VCLXAccessibleButton( VCLXWindow* pVCLWindow )
55 	:VCLXAccessibleTextComponent( pVCLWindow )
56 {
57 }
58 
59 // -----------------------------------------------------------------------------
60 
61 VCLXAccessibleButton::~VCLXAccessibleButton()
62 {
63 }
64 
65 // -----------------------------------------------------------------------------
66 
67 void VCLXAccessibleButton::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
68 {
69     switch ( rVclWindowEvent.GetId() )
70     {
71 		case VCLEVENT_PUSHBUTTON_TOGGLE:
72         {
73 			Any aOldValue;
74 			Any aNewValue;
75 
76 			PushButton* pButton = (PushButton*) GetWindow();
77 			if ( pButton && pButton->GetState() == STATE_CHECK )
78 				aNewValue <<= AccessibleStateType::CHECKED;
79 			else
80 				aOldValue <<= AccessibleStateType::CHECKED;
81 
82             NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
83         }
84         break;
85 		default:
86 			VCLXAccessibleTextComponent::ProcessWindowEvent( rVclWindowEvent );
87    }
88 }
89 
90 // -----------------------------------------------------------------------------
91 
92 void VCLXAccessibleButton::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
93 {
94 	VCLXAccessibleTextComponent::FillAccessibleStateSet( rStateSet );
95 
96 	PushButton* pButton = (PushButton*) GetWindow();
97 	if ( pButton )
98 	{
99         rStateSet.AddState( AccessibleStateType::FOCUSABLE );
100 
101 		if ( pButton->GetState() == STATE_CHECK )
102             rStateSet.AddState( AccessibleStateType::CHECKED );
103 
104 		if ( pButton->IsPressed() )
105             rStateSet.AddState( AccessibleStateType::PRESSED );
106 
107         // IA2 CWS: If the button has a poppup menu,it should has the state EXPANDABLE
108         if( pButton->GetType() == WINDOW_MENUBUTTON )
109         {
110         	rStateSet.AddState( AccessibleStateType::EXPANDABLE );
111         }
112 		if( pButton->GetStyle() & WB_DEFBUTTON )
113 		{
114 			rStateSet.AddState( AccessibleStateType::DEFAULT );
115 		}
116 	}
117 }
118 
119 // -----------------------------------------------------------------------------
120 // XInterface
121 // -----------------------------------------------------------------------------
122 
123 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleButton, VCLXAccessibleTextComponent, VCLXAccessibleButton_BASE )
124 
125 // -----------------------------------------------------------------------------
126 // XTypeProvider
127 // -----------------------------------------------------------------------------
128 
129 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleButton, VCLXAccessibleTextComponent, VCLXAccessibleButton_BASE )
130 
131 // -----------------------------------------------------------------------------
132 // XServiceInfo
133 // -----------------------------------------------------------------------------
134 
135 ::rtl::OUString VCLXAccessibleButton::getImplementationName() throw (RuntimeException)
136 {
137 	return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleButton" );
138 }
139 
140 // -----------------------------------------------------------------------------
141 
142 Sequence< ::rtl::OUString > VCLXAccessibleButton::getSupportedServiceNames() throw (RuntimeException)
143 {
144 	Sequence< ::rtl::OUString > aNames(1);
145 	aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleButton" );
146 	return aNames;
147 }
148 
149 // -----------------------------------------------------------------------------
150 // XAccessibleContext
151 // -----------------------------------------------------------------------------
152 
153 ::rtl::OUString VCLXAccessibleButton::getAccessibleName(  ) throw (RuntimeException)
154 {
155 	OExternalLockGuard aGuard( this );
156 
157 	::rtl::OUString aName( VCLXAccessibleTextComponent::getAccessibleName() );
158 
159 	// IA2 CWS: Removed special handling for browse/more buttons.
160 	//          Comment was "the '...' or '<<' or '>>' should be kepted per the requirements from AT"
161 	// MT: We did introduce this special handling by intention.
162 	//     As the original text is still what you get via XAccessibleText,
163 	//     I think for the accessible name the stuff below is correct.
164 
165 	sal_Int32 nLength = aName.getLength();
166 
167 	if ( nLength >= 3 && aName.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("..."), nLength - 3 ) )
168 	{
169 		if ( nLength == 3 )
170 		{
171 			// it's a browse button
172 	        aName = ::rtl::OUString( TK_RES_STRING( RID_STR_ACC_NAME_BROWSEBUTTON ) );
173 		}
174 		else
175 		{
176 			// remove the three trailing dots
177 			aName = aName.copy( 0, nLength - 3 );
178 		}
179 	}
180 	else if ( nLength >= 3 && aName.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("<< "), 0 ) )
181 	{
182 		// remove the leading symbols
183 		aName = aName.copy( 3, nLength - 3 );
184 	}
185 	else if ( nLength >= 3 && aName.matchAsciiL( RTL_CONSTASCII_STRINGPARAM(" >>"), nLength - 3 ) )
186 	{
187 		// remove the trailing symbols
188 		aName = aName.copy( 0, nLength - 3 );
189 	}
190 
191 	return aName;
192 }
193 
194 // -----------------------------------------------------------------------------
195 // XAccessibleAction
196 // -----------------------------------------------------------------------------
197 
198 sal_Int32 VCLXAccessibleButton::getAccessibleActionCount( ) throw (RuntimeException)
199 {
200 	OExternalLockGuard aGuard( this );
201 
202 	return 1;
203 }
204 
205 // -----------------------------------------------------------------------------
206 
207 sal_Bool VCLXAccessibleButton::doAccessibleAction ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
208 {
209 	OExternalLockGuard aGuard( this );
210 
211 	if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
212         throw IndexOutOfBoundsException();
213 
214 	PushButton* pButton = (PushButton*) GetWindow();
215 	if ( pButton )
216 		pButton->Click();
217 
218 	return sal_True;
219 }
220 
221 // -----------------------------------------------------------------------------
222 
223 ::rtl::OUString VCLXAccessibleButton::getAccessibleActionDescription ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
224 {
225 	OExternalLockGuard aGuard( this );
226 
227 	if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
228         throw IndexOutOfBoundsException();
229 
230 	return ::rtl::OUString( TK_RES_STRING( RID_STR_ACC_ACTION_CLICK ) );
231 }
232 
233 // -----------------------------------------------------------------------------
234 
235 Reference< XAccessibleKeyBinding > VCLXAccessibleButton::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
236 {
237     OExternalLockGuard aGuard( this );
238 
239     if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
240         throw IndexOutOfBoundsException();
241 
242     OAccessibleKeyBindingHelper* pKeyBindingHelper = new OAccessibleKeyBindingHelper();
243     Reference< XAccessibleKeyBinding > xKeyBinding = pKeyBindingHelper;
244 
245     Window* pWindow = GetWindow();
246     if ( pWindow )
247     {
248         KeyEvent aKeyEvent = pWindow->GetActivationKey();
249         KeyCode aKeyCode = aKeyEvent.GetKeyCode();
250         if ( aKeyCode.GetCode() != 0 )
251         {
252             awt::KeyStroke aKeyStroke;
253             aKeyStroke.Modifiers = 0;
254             if ( aKeyCode.IsShift() )
255                 aKeyStroke.Modifiers |= awt::KeyModifier::SHIFT;
256             if ( aKeyCode.IsMod1() )
257                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD1;
258             if ( aKeyCode.IsMod2() )
259                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD2;
260             if ( aKeyCode.IsMod3() )
261                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD3;
262             aKeyStroke.KeyCode = aKeyCode.GetCode();
263             aKeyStroke.KeyChar = aKeyEvent.GetCharCode();
264             aKeyStroke.KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() );
265             pKeyBindingHelper->AddKeyBinding( aKeyStroke );
266         }
267     }
268 
269     return xKeyBinding;
270 }
271 
272 // -----------------------------------------------------------------------------
273 // XAccessibleValue
274 // -----------------------------------------------------------------------------
275 
276 Any VCLXAccessibleButton::getCurrentValue(  ) throw (RuntimeException)
277 {
278 	OExternalLockGuard aGuard( this );
279 
280 	Any aValue;
281 
282 	PushButton* pButton = (PushButton*) GetWindow();
283 	if ( pButton )
284 		aValue <<= (sal_Int32) pButton->IsPressed();
285 
286 	return aValue;
287 }
288 
289 // -----------------------------------------------------------------------------
290 
291 sal_Bool VCLXAccessibleButton::setCurrentValue( const Any& aNumber ) throw (RuntimeException)
292 {
293 	OExternalLockGuard aGuard( this );
294 
295 	sal_Bool bReturn = sal_False;
296 
297 	PushButton* pButton = (PushButton*) GetWindow();
298 	if ( pButton )
299 	{
300 		sal_Int32 nValue = 0;
301 		OSL_VERIFY( aNumber >>= nValue );
302 
303 		if ( nValue < 0 )
304 			nValue = 0;
305 		else if ( nValue > 1 )
306 			nValue = 1;
307 
308 		pButton->SetPressed( (sal_Bool) nValue );
309 		bReturn = sal_True;
310 	}
311 
312 	return bReturn;
313 }
314 
315 // -----------------------------------------------------------------------------
316 
317 Any VCLXAccessibleButton::getMaximumValue(  ) throw (RuntimeException)
318 {
319 	OExternalLockGuard aGuard( this );
320 
321 	Any aValue;
322 	aValue <<= (sal_Int32) 1;
323 
324 	return aValue;
325 }
326 
327 // -----------------------------------------------------------------------------
328 
329 Any VCLXAccessibleButton::getMinimumValue(  ) throw (RuntimeException)
330 {
331 	OExternalLockGuard aGuard( this );
332 
333 	Any aValue;
334 	aValue <<= (sal_Int32) 0;
335 
336 	return aValue;
337 }
338 
339 // -----------------------------------------------------------------------------
340