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