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