Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "atkwrapper.hxx"
22 :
23 : #include <com/sun/star/accessibility/XAccessibleAction.hpp>
24 : #include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
25 :
26 : #include <com/sun/star/awt/Key.hpp>
27 : #include <com/sun/star/awt/KeyModifier.hpp>
28 :
29 : #include <rtl/strbuf.hxx>
30 : #include <algorithm>
31 : #include <map>
32 :
33 : #include <stdio.h>
34 :
35 : using namespace ::com::sun::star;
36 :
37 : // FIXME
38 : static G_CONST_RETURN gchar *
39 0 : getAsConst( const rtl::OString& rString )
40 : {
41 : static const int nMax = 10;
42 0 : static rtl::OString aUgly[nMax];
43 : static int nIdx = 0;
44 0 : nIdx = (nIdx + 1) % nMax;
45 0 : aUgly[nIdx] = rString;
46 0 : return aUgly[ nIdx ].getStr();
47 : }
48 :
49 : static accessibility::XAccessibleAction*
50 0 : getAction( AtkAction *action ) throw (uno::RuntimeException)
51 : {
52 0 : AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( action );
53 :
54 0 : if( pWrap )
55 : {
56 0 : if( !pWrap->mpAction && pWrap->mpContext )
57 : {
58 0 : uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleAction::static_type(NULL) );
59 0 : pWrap->mpAction = reinterpret_cast< accessibility::XAccessibleAction * > (any.pReserved);
60 0 : pWrap->mpAction->acquire();
61 : }
62 :
63 0 : return pWrap->mpAction;
64 : }
65 :
66 0 : return NULL;
67 : }
68 :
69 : extern "C" {
70 :
71 : static gboolean
72 0 : action_wrapper_do_action (AtkAction *action,
73 : gint i)
74 : {
75 : try {
76 0 : accessibility::XAccessibleAction* pAction = getAction( action );
77 0 : if( pAction )
78 0 : return pAction->doAccessibleAction( i );
79 : }
80 0 : catch(const uno::Exception& e) {
81 0 : g_warning( "Exception in doAccessibleAction()" );
82 : }
83 :
84 0 : return FALSE;
85 : }
86 :
87 : static gint
88 0 : action_wrapper_get_n_actions (AtkAction *action)
89 : {
90 : try {
91 0 : accessibility::XAccessibleAction* pAction = getAction( action );
92 0 : if( pAction )
93 0 : return pAction->getAccessibleActionCount();
94 : }
95 0 : catch(const uno::Exception& e) {
96 0 : g_warning( "Exception in getAccessibleActionCount()" );
97 : }
98 :
99 0 : return 0;
100 : }
101 :
102 : static G_CONST_RETURN gchar *
103 0 : action_wrapper_get_description (AtkAction *, gint)
104 : {
105 : // GAIL implement this only for cells
106 0 : g_warning( "Not implemented: get_description()" );
107 0 : return "";
108 : }
109 :
110 : static G_CONST_RETURN gchar *
111 0 : action_wrapper_get_localized_name (AtkAction *, gint)
112 : {
113 : // GAIL doesn't implement this as well
114 0 : g_warning( "Not implemented: get_localized_name()" );
115 0 : return "";
116 : }
117 :
118 : #define ACTION_NAME_PAIR( OOoName, AtkName ) \
119 : std::pair< const rtl::OUString, const gchar * > ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OOoName ) ), AtkName )
120 :
121 : static G_CONST_RETURN gchar *
122 0 : action_wrapper_get_name (AtkAction *action,
123 : gint i)
124 : {
125 0 : static std::map< rtl::OUString, const gchar * > aNameMap;
126 :
127 0 : if( aNameMap.empty() )
128 : {
129 0 : aNameMap.insert( ACTION_NAME_PAIR( "click", "click" ) );
130 0 : aNameMap.insert( ACTION_NAME_PAIR( "select", "click" ) );
131 0 : aNameMap.insert( ACTION_NAME_PAIR( "togglePopup", "push" ) );
132 : }
133 :
134 : try {
135 0 : accessibility::XAccessibleAction* pAction = getAction( action );
136 0 : if( pAction )
137 : {
138 0 : std::map< rtl::OUString, const gchar * >::iterator iter;
139 :
140 0 : rtl::OUString aDesc( pAction->getAccessibleActionDescription( i ) );
141 :
142 0 : iter = aNameMap.find( aDesc );
143 0 : if( iter != aNameMap.end() )
144 0 : return iter->second;
145 :
146 : std::pair< const rtl::OUString, const gchar * > aNewVal( aDesc,
147 0 : g_strdup( OUStringToConstGChar(aDesc) ) );
148 :
149 0 : if( aNameMap.insert( aNewVal ).second )
150 0 : return aNewVal.second;
151 : }
152 : }
153 0 : catch(const uno::Exception& e) {
154 0 : g_warning( "Exception in getAccessibleActionDescription()" );
155 : }
156 :
157 0 : return "";
158 : }
159 :
160 : /*
161 : * GNOME Expects a string in the format:
162 : *
163 : * <nmemonic>;<full-path>;<accelerator>
164 : *
165 : * The keybindings in <full-path> should be separated by ":"
166 : */
167 :
168 : static inline void
169 0 : appendKeyStrokes(rtl::OStringBuffer& rBuffer, const uno::Sequence< awt::KeyStroke >& rKeyStrokes)
170 : {
171 0 : for( sal_Int32 i = 0; i < rKeyStrokes.getLength(); i++ )
172 : {
173 0 : if( rKeyStrokes[i].Modifiers & awt::KeyModifier::SHIFT )
174 0 : rBuffer.append("<Shift>");
175 0 : if( rKeyStrokes[i].Modifiers & awt::KeyModifier::MOD1 )
176 0 : rBuffer.append("<Control>");
177 0 : if( rKeyStrokes[i].Modifiers & awt::KeyModifier::MOD2 )
178 0 : rBuffer.append("<Alt>");
179 :
180 0 : if( ( rKeyStrokes[i].KeyCode >= awt::Key::A ) && ( rKeyStrokes[i].KeyCode <= awt::Key::Z ) )
181 0 : rBuffer.append( (sal_Char) ( 'a' + ( rKeyStrokes[i].KeyCode - awt::Key::A ) ) );
182 : else
183 : {
184 0 : sal_Char c = '\0';
185 :
186 0 : switch( rKeyStrokes[i].KeyCode )
187 : {
188 0 : case awt::Key::TAB: c = '\t'; break;
189 0 : case awt::Key::SPACE: c = ' '; break;
190 0 : case awt::Key::ADD: c = '+'; break;
191 0 : case awt::Key::SUBTRACT: c = '-'; break;
192 0 : case awt::Key::MULTIPLY: c = '*'; break;
193 0 : case awt::Key::DIVIDE: c = '/'; break;
194 0 : case awt::Key::POINT: c = '.'; break;
195 0 : case awt::Key::COMMA: c = ','; break;
196 0 : case awt::Key::LESS: c = '<'; break;
197 0 : case awt::Key::GREATER: c = '>'; break;
198 0 : case awt::Key::EQUAL: c = '='; break;
199 : case 0:
200 0 : break;
201 : default:
202 0 : g_warning( "Unmapped KeyCode: %d", rKeyStrokes[i].KeyCode );
203 0 : break;
204 : }
205 :
206 0 : if( c != '\0' )
207 0 : rBuffer.append( c );
208 : }
209 : }
210 0 : }
211 :
212 :
213 : static G_CONST_RETURN gchar *
214 0 : action_wrapper_get_keybinding (AtkAction *action,
215 : gint i)
216 : {
217 : try {
218 0 : accessibility::XAccessibleAction* pAction = getAction( action );
219 0 : if( pAction )
220 : {
221 0 : uno::Reference< accessibility::XAccessibleKeyBinding > xBinding( pAction->getAccessibleActionKeyBinding( i ));
222 :
223 0 : if( xBinding.is() )
224 : {
225 0 : rtl::OStringBuffer aRet;
226 :
227 0 : sal_Int32 nmax = std::min( xBinding->getAccessibleKeyBindingCount(), (sal_Int32) 3 );
228 0 : for( sal_Int32 n = 0; n < nmax; n++ )
229 : {
230 0 : appendKeyStrokes( aRet, xBinding->getAccessibleKeyBinding( n ) );
231 :
232 0 : if( n < 2 )
233 0 : aRet.append( (sal_Char) ';' );
234 : }
235 :
236 : // !! FIXME !! remember keystroke in wrapper object ?
237 0 : return getAsConst( aRet.makeStringAndClear() );
238 0 : }
239 : }
240 : }
241 0 : catch(const uno::Exception& e) {
242 0 : g_warning( "Exception in get_keybinding()" );
243 : }
244 :
245 0 : return "";
246 : }
247 :
248 : static gboolean
249 0 : action_wrapper_set_description (AtkAction *, gint, const gchar *)
250 : {
251 0 : return FALSE;
252 : }
253 :
254 : } // extern "C"
255 :
256 : void
257 0 : actionIfaceInit (AtkActionIface *iface)
258 : {
259 0 : g_return_if_fail (iface != NULL);
260 :
261 0 : iface->do_action = action_wrapper_do_action;
262 0 : iface->get_n_actions = action_wrapper_get_n_actions;
263 0 : iface->get_description = action_wrapper_get_description;
264 0 : iface->get_keybinding = action_wrapper_get_keybinding;
265 0 : iface->get_name = action_wrapper_get_name;
266 0 : iface->get_localized_name = action_wrapper_get_localized_name;
267 0 : iface->set_description = action_wrapper_set_description;
268 : }
269 :
270 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|