xref: /AOO41X/main/sc/source/ui/Accessibility/AccessibleEditObject.cxx (revision ff0525f24f03981d56b7579b645949f111420994)
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_sc.hxx"
26 #include "AccessibleEditObject.hxx"
27 #include "scitems.hxx"
28 #include <editeng/eeitem.hxx>
29 #include "unoguard.hxx"
30 #include "AccessibleText.hxx"
31 #include "editsrc.hxx"
32 #include "scmod.hxx"
33 #include "inputhdl.hxx"
34 
35 #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX
36 #include <unotools/accessiblestatesethelper.hxx>
37 #endif
38 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
39 #include <com/sun/star/accessibility/AccessibleRole.hpp>
40 #endif
41 #ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
42 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
43 #endif
44 #include <rtl/uuid.h>
45 #include <tools/debug.hxx>
46 #include <svx/AccessibleTextHelper.hxx>
47 #include <editeng/editview.hxx>
48 #include <editeng/editeng.hxx>
49 #include <svx/svdmodel.hxx>
50 
51 using namespace ::com::sun::star;
52 using namespace ::com::sun::star::accessibility;
53 
54 //=====  internal  ============================================================
55 
56 ScAccessibleEditObject::ScAccessibleEditObject(
57         const uno::Reference<XAccessible>& rxParent,
58         EditView* pEditView, Window* pWin, const rtl::OUString& rName,
59         const rtl::OUString& rDescription, EditObjectType eObjectType)
60     :
61     ScAccessibleContextBase(rxParent, AccessibleRole::TEXT_FRAME),
62     mpTextHelper(NULL),
63     mpEditView(pEditView),
64     mpWindow(pWin),
65     meObjectType(eObjectType),
66     mbHasFocus(sal_False)
67 {
68     CreateTextHelper();
69     SetName(rName);
70     SetDescription(rDescription);
71 }
72 
73 ScAccessibleEditObject::~ScAccessibleEditObject()
74 {
75     if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
76     {
77         // increment refcount to prevent double call off dtor
78         osl_incrementInterlockedCount( &m_refCount );
79         // call dispose to inform object wich have a weak reference to this object
80         dispose();
81     }
82 }
83 
84 void SAL_CALL ScAccessibleEditObject::disposing()
85 {
86     ScUnoGuard aGuard;
87     if (mpTextHelper)
88         DELETEZ(mpTextHelper);
89 
90     ScAccessibleContextBase::disposing();
91 }
92 
93 void ScAccessibleEditObject::LostFocus()
94 {
95     mbHasFocus = sal_False;
96     if (mpTextHelper)
97         mpTextHelper->SetFocus(sal_False);
98     CommitFocusLost();
99 }
100 
101 void ScAccessibleEditObject::GotFocus()
102 {
103     mbHasFocus = sal_True;
104     CommitFocusGained();
105     if (mpTextHelper)
106         mpTextHelper->SetFocus(sal_True);
107 }
108 
109     //=====  XAccessibleComponent  ============================================
110 
111 uno::Reference< XAccessible > SAL_CALL ScAccessibleEditObject::getAccessibleAtPoint(
112         const awt::Point& rPoint )
113         throw (uno::RuntimeException)
114 {
115     uno::Reference<XAccessible> xRet;
116     if (containsPoint(rPoint))
117     {
118         ScUnoGuard aGuard;
119         IsObjectValid();
120 
121         if(!mpTextHelper)
122             CreateTextHelper();
123 
124         xRet = mpTextHelper->GetAt(rPoint);
125     }
126 
127     return xRet;
128 }
129 
130 Rectangle ScAccessibleEditObject::GetBoundingBoxOnScreen(void) const
131         throw (uno::RuntimeException)
132 {
133     Rectangle aScreenBounds;
134 
135     if ( mpWindow )
136     {
137         if ( meObjectType == CellInEditMode )
138         {
139             if ( mpEditView && mpEditView->GetEditEngine() )
140             {
141                 MapMode aMapMode( mpEditView->GetEditEngine()->GetRefMapMode() );
142                 aScreenBounds = mpWindow->LogicToPixel( mpEditView->GetOutputArea(), aMapMode );
143                 Point aCellLoc = aScreenBounds.TopLeft();
144                 Rectangle aWindowRect = mpWindow->GetWindowExtentsRelative( NULL );
145                 Point aWindowLoc = aWindowRect.TopLeft();
146                 Point aPos( aCellLoc.getX() + aWindowLoc.getX(), aCellLoc.getY() + aWindowLoc.getY() );
147                 aScreenBounds.SetPos( aPos );
148             }
149         }
150         else
151         {
152             aScreenBounds = mpWindow->GetWindowExtentsRelative( NULL );
153         }
154     }
155 
156     return aScreenBounds;
157 }
158 
159 Rectangle ScAccessibleEditObject::GetBoundingBox(void) const
160         throw (uno::RuntimeException)
161 {
162     Rectangle aBounds( GetBoundingBoxOnScreen() );
163 
164     if ( mpWindow )
165     {
166         uno::Reference< XAccessible > xThis( mpWindow->GetAccessible() );
167         if ( xThis.is() )
168         {
169             uno::Reference< XAccessibleContext > xContext( xThis->getAccessibleContext() );
170             if ( xContext.is() )
171             {
172                 uno::Reference< XAccessible > xParent( xContext->getAccessibleParent() );
173                 if ( xParent.is() )
174                 {
175                     uno::Reference< XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
176                     if ( xParentComponent.is() )
177                     {
178                         Point aScreenLoc = aBounds.TopLeft();
179                         awt::Point aParentScreenLoc = xParentComponent->getLocationOnScreen();
180                         Point aPos( aScreenLoc.getX() - aParentScreenLoc.X, aScreenLoc.getY() - aParentScreenLoc.Y );
181                         aBounds.SetPos( aPos );
182                     }
183                 }
184             }
185         }
186     }
187 
188     return aBounds;
189 }
190 
191     //=====  XAccessibleContext  ==============================================
192 
193 sal_Int32 SAL_CALL
194     ScAccessibleEditObject::getAccessibleChildCount(void)
195                     throw (uno::RuntimeException)
196 {
197     ScUnoGuard aGuard;
198     IsObjectValid();
199     if (!mpTextHelper)
200         CreateTextHelper();
201     return mpTextHelper->GetChildCount();
202 }
203 
204 uno::Reference< XAccessible > SAL_CALL
205     ScAccessibleEditObject::getAccessibleChild(sal_Int32 nIndex)
206         throw (uno::RuntimeException,
207         lang::IndexOutOfBoundsException)
208 {
209     ScUnoGuard aGuard;
210     IsObjectValid();
211     if (!mpTextHelper)
212         CreateTextHelper();
213     return mpTextHelper->GetChild(nIndex);
214 }
215 
216 uno::Reference<XAccessibleStateSet> SAL_CALL
217     ScAccessibleEditObject::getAccessibleStateSet(void)
218     throw (uno::RuntimeException)
219 {
220     ScUnoGuard aGuard;
221     uno::Reference<XAccessibleStateSet> xParentStates;
222     if (getAccessibleParent().is())
223     {
224         uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
225         xParentStates = xParentContext->getAccessibleStateSet();
226     }
227     utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
228     if (IsDefunc(xParentStates))
229         pStateSet->AddState(AccessibleStateType::DEFUNC);
230     else
231     {
232         // all states are const, because this object exists only in one state
233         pStateSet->AddState(AccessibleStateType::EDITABLE);
234         pStateSet->AddState(AccessibleStateType::ENABLED);
235         pStateSet->AddState(AccessibleStateType::SENSITIVE);
236         pStateSet->AddState(AccessibleStateType::MULTI_LINE);
237         pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
238         pStateSet->AddState(AccessibleStateType::SHOWING);
239         pStateSet->AddState(AccessibleStateType::VISIBLE);
240     }
241     return pStateSet;
242 }
243 
244 ::rtl::OUString SAL_CALL
245     ScAccessibleEditObject::createAccessibleDescription(void)
246     throw (uno::RuntimeException)
247 {
248 //    DBG_ERRORFILE("Should never be called, because is set in the constructor.")
249     return rtl::OUString();
250 }
251 
252 ::rtl::OUString SAL_CALL
253     ScAccessibleEditObject::createAccessibleName(void)
254     throw (uno::RuntimeException)
255 {
256     DBG_ERRORFILE("Should never be called, because is set in the constructor.");
257     return rtl::OUString();
258 }
259 
260     ///=====  XAccessibleEventBroadcaster  =====================================
261 
262 void SAL_CALL
263     ScAccessibleEditObject::addEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
264         throw (uno::RuntimeException)
265 {
266     if (!mpTextHelper)
267         CreateTextHelper();
268 
269     mpTextHelper->AddEventListener(xListener);
270 
271     ScAccessibleContextBase::addEventListener(xListener);
272 }
273 
274 void SAL_CALL
275     ScAccessibleEditObject::removeEventListener(const uno::Reference<XAccessibleEventListener>& xListener)
276         throw (uno::RuntimeException)
277 {
278     if (!mpTextHelper)
279         CreateTextHelper();
280 
281     mpTextHelper->RemoveEventListener(xListener);
282 
283     ScAccessibleContextBase::removeEventListener(xListener);
284 }
285 
286     //=====  XServiceInfo  ====================================================
287 
288 ::rtl::OUString SAL_CALL ScAccessibleEditObject::getImplementationName(void)
289         throw (uno::RuntimeException)
290 {
291     return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessibleEditObject"));
292 }
293 
294 //=====  XTypeProvider  =======================================================
295 
296 uno::Sequence<sal_Int8> SAL_CALL
297     ScAccessibleEditObject::getImplementationId(void)
298     throw (uno::RuntimeException)
299 {
300     ScUnoGuard aGuard;
301     IsObjectValid();
302     static uno::Sequence<sal_Int8> aId;
303     if (aId.getLength() == 0)
304     {
305         aId.realloc (16);
306         rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
307     }
308     return aId;
309 }
310 
311     //====  internal  =========================================================
312 
313 sal_Bool ScAccessibleEditObject::IsDefunc(
314     const uno::Reference<XAccessibleStateSet>& rxParentStates)
315 {
316     return ScAccessibleContextBase::IsDefunc() || !getAccessibleParent().is() ||
317          (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
318 }
319 
320 void ScAccessibleEditObject::CreateTextHelper()
321 {
322     if (!mpTextHelper)
323     {
324         ::std::auto_ptr < ScAccessibleTextData > pAccessibleTextData;
325         if (meObjectType == CellInEditMode || meObjectType == EditControl)
326         {
327             pAccessibleTextData.reset
328                 (new ScAccessibleEditObjectTextData(mpEditView, mpWindow));
329         }
330         else
331         {
332             pAccessibleTextData.reset
333                 (new ScAccessibleEditLineTextData(NULL, mpWindow));
334         }
335 
336         ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessibleTextData));
337         mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource );
338         mpTextHelper->SetEventSource(this);
339         mpTextHelper->SetFocus(mbHasFocus);
340 
341         // #i54814# activate cell in edit mode
342         if( meObjectType == CellInEditMode )
343         {
344             // do not activate cell object, if top edit line is active
345             const ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
346             if( pInputHdl && !pInputHdl->IsTopMode() )
347             {
348                 SdrHint aHint( HINT_BEGEDIT );
349                 mpTextHelper->GetEditSource().GetBroadcaster().Broadcast( aHint );
350             }
351         }
352     }
353 }
354 
355