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 }
108 
109 // -----------------------------------------------------------------------------
110 // XInterface
111 // -----------------------------------------------------------------------------
112 
113 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleButton, VCLXAccessibleTextComponent, VCLXAccessibleButton_BASE )
114 
115 // -----------------------------------------------------------------------------
116 // XTypeProvider
117 // -----------------------------------------------------------------------------
118 
119 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleButton, VCLXAccessibleTextComponent, VCLXAccessibleButton_BASE )
120 
121 // -----------------------------------------------------------------------------
122 // XServiceInfo
123 // -----------------------------------------------------------------------------
124 
125 ::rtl::OUString VCLXAccessibleButton::getImplementationName() throw (RuntimeException)
126 {
127 	return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleButton" );
128 }
129 
130 // -----------------------------------------------------------------------------
131 
132 Sequence< ::rtl::OUString > VCLXAccessibleButton::getSupportedServiceNames() throw (RuntimeException)
133 {
134 	Sequence< ::rtl::OUString > aNames(1);
135 	aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleButton" );
136 	return aNames;
137 }
138 
139 // -----------------------------------------------------------------------------
140 // XAccessibleContext
141 // -----------------------------------------------------------------------------
142 
143 ::rtl::OUString VCLXAccessibleButton::getAccessibleName(  ) throw (RuntimeException)
144 {
145 	OExternalLockGuard aGuard( this );
146 
147 	::rtl::OUString aName( VCLXAccessibleTextComponent::getAccessibleName() );
148 	sal_Int32 nLength = aName.getLength();
149 
150 	if ( nLength >= 3 && aName.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("..."), nLength - 3 ) )
151 	{
152 		if ( nLength == 3 )
153 		{
154 			// it's a browse button
155 	        aName = ::rtl::OUString( TK_RES_STRING( RID_STR_ACC_NAME_BROWSEBUTTON ) );
156 		}
157 		else
158 		{
159 			// remove the three trailing dots
160 			aName = aName.copy( 0, nLength - 3 );
161 		}
162 	}
163 	else if ( nLength >= 3 && aName.matchAsciiL( RTL_CONSTASCII_STRINGPARAM("<< "), 0 ) )
164 	{
165 		// remove the leading symbols
166 		aName = aName.copy( 3, nLength - 3 );
167 	}
168 	else if ( nLength >= 3 && aName.matchAsciiL( RTL_CONSTASCII_STRINGPARAM(" >>"), nLength - 3 ) )
169 	{
170 		// remove the trailing symbols
171 		aName = aName.copy( 0, nLength - 3 );
172 	}
173 
174 	return aName;
175 }
176 
177 // -----------------------------------------------------------------------------
178 // XAccessibleAction
179 // -----------------------------------------------------------------------------
180 
181 sal_Int32 VCLXAccessibleButton::getAccessibleActionCount( ) throw (RuntimeException)
182 {
183 	OExternalLockGuard aGuard( this );
184 
185 	return 1;
186 }
187 
188 // -----------------------------------------------------------------------------
189 
190 sal_Bool VCLXAccessibleButton::doAccessibleAction ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
191 {
192 	OExternalLockGuard aGuard( this );
193 
194 	if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
195         throw IndexOutOfBoundsException();
196 
197 	PushButton* pButton = (PushButton*) GetWindow();
198 	if ( pButton )
199 		pButton->Click();
200 
201 	return sal_True;
202 }
203 
204 // -----------------------------------------------------------------------------
205 
206 ::rtl::OUString VCLXAccessibleButton::getAccessibleActionDescription ( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
207 {
208 	OExternalLockGuard aGuard( this );
209 
210 	if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
211         throw IndexOutOfBoundsException();
212 
213 	return ::rtl::OUString( TK_RES_STRING( RID_STR_ACC_ACTION_CLICK ) );
214 }
215 
216 // -----------------------------------------------------------------------------
217 
218 Reference< XAccessibleKeyBinding > VCLXAccessibleButton::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
219 {
220     OExternalLockGuard aGuard( this );
221 
222     if ( nIndex < 0 || nIndex >= getAccessibleActionCount() )
223         throw IndexOutOfBoundsException();
224 
225     OAccessibleKeyBindingHelper* pKeyBindingHelper = new OAccessibleKeyBindingHelper();
226     Reference< XAccessibleKeyBinding > xKeyBinding = pKeyBindingHelper;
227 
228     Window* pWindow = GetWindow();
229     if ( pWindow )
230     {
231         KeyEvent aKeyEvent = pWindow->GetActivationKey();
232         KeyCode aKeyCode = aKeyEvent.GetKeyCode();
233         if ( aKeyCode.GetCode() != 0 )
234         {
235             awt::KeyStroke aKeyStroke;
236             aKeyStroke.Modifiers = 0;
237             if ( aKeyCode.IsShift() )
238                 aKeyStroke.Modifiers |= awt::KeyModifier::SHIFT;
239             if ( aKeyCode.IsMod1() )
240                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD1;
241             if ( aKeyCode.IsMod2() )
242                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD2;
243             if ( aKeyCode.IsMod3() )
244                 aKeyStroke.Modifiers |= awt::KeyModifier::MOD3;
245             aKeyStroke.KeyCode = aKeyCode.GetCode();
246             aKeyStroke.KeyChar = aKeyEvent.GetCharCode();
247             aKeyStroke.KeyFunc = static_cast< sal_Int16 >( aKeyCode.GetFunction() );
248             pKeyBindingHelper->AddKeyBinding( aKeyStroke );
249         }
250     }
251 
252     return xKeyBinding;
253 }
254 
255 // -----------------------------------------------------------------------------
256 // XAccessibleValue
257 // -----------------------------------------------------------------------------
258 
259 Any VCLXAccessibleButton::getCurrentValue(  ) throw (RuntimeException)
260 {
261 	OExternalLockGuard aGuard( this );
262 
263 	Any aValue;
264 
265 	PushButton* pButton = (PushButton*) GetWindow();
266 	if ( pButton )
267 		aValue <<= (sal_Int32) pButton->IsPressed();
268 
269 	return aValue;
270 }
271 
272 // -----------------------------------------------------------------------------
273 
274 sal_Bool VCLXAccessibleButton::setCurrentValue( const Any& aNumber ) throw (RuntimeException)
275 {
276 	OExternalLockGuard aGuard( this );
277 
278 	sal_Bool bReturn = sal_False;
279 
280 	PushButton* pButton = (PushButton*) GetWindow();
281 	if ( pButton )
282 	{
283 		sal_Int32 nValue = 0;
284 		OSL_VERIFY( aNumber >>= nValue );
285 
286 		if ( nValue < 0 )
287 			nValue = 0;
288 		else if ( nValue > 1 )
289 			nValue = 1;
290 
291 		pButton->SetPressed( (sal_Bool) nValue );
292 		bReturn = sal_True;
293 	}
294 
295 	return bReturn;
296 }
297 
298 // -----------------------------------------------------------------------------
299 
300 Any VCLXAccessibleButton::getMaximumValue(  ) throw (RuntimeException)
301 {
302 	OExternalLockGuard aGuard( this );
303 
304 	Any aValue;
305 	aValue <<= (sal_Int32) 1;
306 
307 	return aValue;
308 }
309 
310 // -----------------------------------------------------------------------------
311 
312 Any VCLXAccessibleButton::getMinimumValue(  ) throw (RuntimeException)
313 {
314 	OExternalLockGuard aGuard( this );
315 
316 	Any aValue;
317 	aValue <<= (sal_Int32) 0;
318 
319 	return aValue;
320 }
321 
322 // -----------------------------------------------------------------------------
323