1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 #include "scitems.hxx"
31 #include <editeng/eeitem.hxx>
32 #include <tools/gen.hxx>
33 #include "AccessibleText.hxx"
34 #include "editsrc.hxx"
35 #include "AccessiblePreviewCell.hxx"
36 #include "AccessibilityHints.hxx"
37 #include "prevwsh.hxx"
38 #include "unoguard.hxx"
39 #include "prevloc.hxx"
40 #include "document.hxx"
41 #include <svx/AccessibleTextHelper.hxx>
42 #include <unotools/accessiblestatesethelper.hxx>
43 #include <editeng/brshitem.hxx>
44 #include <vcl/window.hxx>
45 #include <toolkit/helper/convert.hxx>
46 
47 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
48 
49 using namespace	::com::sun::star;
50 using namespace	::com::sun::star::accessibility;
51 
52 //=====  internal  ============================================================
53 
54 ScAccessiblePreviewCell::ScAccessiblePreviewCell( const ::com::sun::star::uno::Reference<
55 						        ::com::sun::star::accessibility::XAccessible>& rxParent,
56 							ScPreviewShell* pViewShell, /* const */ ScAddress& rCellAddress,
57 							sal_Int32 nIndex ) :
58 	ScAccessibleCellBase( rxParent, ( pViewShell ? pViewShell->GetDocument() : NULL ), rCellAddress, nIndex ),
59 	mpViewShell( pViewShell ),
60     mpTextHelper(NULL)
61 {
62 	if (mpViewShell)
63 		mpViewShell->AddAccessibilityObject(*this);
64 }
65 
66 ScAccessiblePreviewCell::~ScAccessiblePreviewCell()
67 {
68 	if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
69 	{
70 		// increment refcount to prevent double call off dtor
71 		osl_incrementInterlockedCount( &m_refCount );
72 		// call dispose to inform object wich have a weak reference to this object
73 		dispose();
74 	}
75 }
76 
77 void SAL_CALL ScAccessiblePreviewCell::disposing()
78 {
79     ScUnoGuard aGuard;
80 	if (mpViewShell)
81 	{
82 		mpViewShell->RemoveAccessibilityObject(*this);
83 		mpViewShell = NULL;
84 	}
85 
86 	if (mpTextHelper)
87 		DELETEZ(mpTextHelper);
88 
89 	ScAccessibleCellBase::disposing();
90 }
91 
92 void ScAccessiblePreviewCell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
93 {
94 	if (rHint.ISA( SfxSimpleHint ))
95 	{
96 		const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
97         if (rRef.GetId() == SC_HINT_ACC_VISAREACHANGED)
98         {
99             if (mpTextHelper)
100                 mpTextHelper->UpdateChildren();
101         }
102 	}
103 
104 	ScAccessibleContextBase::Notify(rBC, rHint);
105 }
106 
107 //=====  XAccessibleComponent  ============================================
108 
109 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewCell::getAccessibleAtPoint( const awt::Point& rPoint )
110 								throw (uno::RuntimeException)
111 {
112     uno::Reference<XAccessible> xRet;
113     if (containsPoint(rPoint))
114     {
115  	    ScUnoGuard aGuard;
116         IsObjectValid();
117 
118     	if(!mpTextHelper)
119 	    	CreateTextHelper();
120 
121         xRet = mpTextHelper->GetAt(rPoint);
122     }
123 
124     return xRet;
125 }
126 
127 void SAL_CALL ScAccessiblePreviewCell::grabFocus() throw (uno::RuntimeException)
128 {
129  	ScUnoGuard aGuard;
130     IsObjectValid();
131 	if (getAccessibleParent().is())
132 	{
133 		uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
134 		if (xAccessibleComponent.is())
135 			xAccessibleComponent->grabFocus();
136 	}
137 }
138 
139 //=====  XAccessibleContext  ==============================================
140 
141 sal_Int32 SAL_CALL ScAccessiblePreviewCell::getAccessibleChildCount() throw(uno::RuntimeException)
142 {
143 	ScUnoGuard aGuard;
144     IsObjectValid();
145 	if (!mpTextHelper)
146 		CreateTextHelper();
147 	return mpTextHelper->GetChildCount();
148 }
149 
150 uno::Reference< XAccessible > SAL_CALL ScAccessiblePreviewCell::getAccessibleChild(sal_Int32 nIndex)
151 					        throw (uno::RuntimeException, lang::IndexOutOfBoundsException)
152 {
153 	ScUnoGuard aGuard;
154     IsObjectValid();
155 	if (!mpTextHelper)
156 		CreateTextHelper();
157 	return mpTextHelper->GetChild(nIndex);
158 }
159 
160 uno::Reference<XAccessibleStateSet> SAL_CALL ScAccessiblePreviewCell::getAccessibleStateSet()
161 						    throw(uno::RuntimeException)
162 {
163 	ScUnoGuard aGuard;
164 
165 	uno::Reference<XAccessibleStateSet> xParentStates;
166 	if (getAccessibleParent().is())
167 	{
168 		uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
169 		xParentStates = xParentContext->getAccessibleStateSet();
170 	}
171 	utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
172 	if (IsDefunc(xParentStates))
173 		pStateSet->AddState(AccessibleStateType::DEFUNC);
174     else
175     {
176 	    pStateSet->AddState(AccessibleStateType::ENABLED);
177 	    pStateSet->AddState(AccessibleStateType::MULTI_LINE);
178 	    if (IsOpaque(xParentStates))
179 		    pStateSet->AddState(AccessibleStateType::OPAQUE);
180 	    if (isShowing())
181 		    pStateSet->AddState(AccessibleStateType::SHOWING);
182 	    pStateSet->AddState(AccessibleStateType::TRANSIENT);
183 	    if (isVisible())
184 		    pStateSet->AddState(AccessibleStateType::VISIBLE);
185         // #111635# MANAGES_DESCENDANTS (for paragraphs)
186         pStateSet->AddState(AccessibleStateType::MANAGES_DESCENDANTS);
187     }
188 	return pStateSet;
189 }
190 
191 //=====  XServiceInfo  ====================================================
192 
193 rtl::OUString SAL_CALL ScAccessiblePreviewCell::getImplementationName() throw(uno::RuntimeException)
194 {
195 	return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ScAccessiblePreviewCell"));
196 }
197 
198 uno::Sequence<rtl::OUString> SAL_CALL ScAccessiblePreviewCell::getSupportedServiceNames()
199 													throw(uno::RuntimeException)
200 {
201 	uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
202     sal_Int32 nOldSize(aSequence.getLength());
203     aSequence.realloc(nOldSize + 1);
204     ::rtl::OUString* pNames = aSequence.getArray();
205 
206 	pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.AccessibleCellView"));
207 
208 	return aSequence;
209 }
210 
211 //=====  XTypeProvider  =======================================================
212 
213 uno::Sequence<sal_Int8> SAL_CALL
214 	ScAccessiblePreviewCell::getImplementationId(void)
215     throw (uno::RuntimeException)
216 {
217     ScUnoGuard aGuard;
218     IsObjectValid();
219 	static uno::Sequence<sal_Int8> aId;
220 	if (aId.getLength() == 0)
221 	{
222 		aId.realloc (16);
223 		rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
224 	}
225 	return aId;
226 }
227 
228 //====  internal  =========================================================
229 
230 Rectangle ScAccessiblePreviewCell::GetBoundingBoxOnScreen() const throw (uno::RuntimeException)
231 {
232 	Rectangle aCellRect;
233 	if (mpViewShell)
234 	{
235         mpViewShell->GetLocationData().GetCellPosition( maCellAddress, aCellRect );
236 		Window* pWindow = mpViewShell->GetWindow();
237 		if (pWindow)
238 		{
239 			Rectangle aRect = pWindow->GetWindowExtentsRelative(NULL);
240 			aCellRect.setX(aCellRect.getX() + aRect.getX());
241 			aCellRect.setY(aCellRect.getY() + aRect.getY());
242 		}
243 	}
244 	return aCellRect;
245 }
246 
247 Rectangle ScAccessiblePreviewCell::GetBoundingBox() const throw (uno::RuntimeException)
248 {
249 	Rectangle aCellRect;
250 	if (mpViewShell)
251     {
252         mpViewShell->GetLocationData().GetCellPosition( maCellAddress, aCellRect );
253         uno::Reference<XAccessible> xAccParent = const_cast<ScAccessiblePreviewCell*>(this)->getAccessibleParent();
254         if (xAccParent.is())
255         {
256             uno::Reference<XAccessibleContext> xAccParentContext = xAccParent->getAccessibleContext();
257             uno::Reference<XAccessibleComponent> xAccParentComp (xAccParentContext, uno::UNO_QUERY);
258             if (xAccParentComp.is())
259             {
260                 Rectangle aParentRect (VCLRectangle(xAccParentComp->getBounds()));
261 	            aCellRect.setX(aCellRect.getX() - aParentRect.getX());
262 	            aCellRect.setY(aCellRect.getY() - aParentRect.getY());
263             }
264         }
265     }
266 	return aCellRect;
267 }
268 
269 sal_Bool ScAccessiblePreviewCell::IsDefunc(
270 	const uno::Reference<XAccessibleStateSet>& rxParentStates)
271 {
272 	return ScAccessibleContextBase::IsDefunc() || (mpDoc == NULL) || (mpViewShell == NULL) || !getAccessibleParent().is() ||
273 		 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
274 }
275 
276 sal_Bool ScAccessiblePreviewCell::IsEditable(
277     const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
278 {
279 	return sal_False;
280 }
281 
282 sal_Bool ScAccessiblePreviewCell::IsOpaque(
283     const uno::Reference<XAccessibleStateSet>& /* rxParentStates */)
284 {
285 	// test whether there is a background color
286 	//!	could be moved to ScAccessibleCellBase
287 
288 	sal_Bool bOpaque(sal_True);
289 	if (mpDoc)
290 	{
291 		const SvxBrushItem* pItem = (const SvxBrushItem*)mpDoc->GetAttr(
292 			maCellAddress.Col(), maCellAddress.Row(), maCellAddress.Tab(), ATTR_BACKGROUND);
293 		if (pItem)
294 			bOpaque = pItem->GetColor() != COL_TRANSPARENT;
295 	}
296 	return bOpaque;
297 }
298 
299 void ScAccessiblePreviewCell::CreateTextHelper()
300 {
301 	if (!mpTextHelper)
302 	{
303 		::std::auto_ptr < ScAccessibleTextData > pAccessiblePreviewCellTextData
304 			(new ScAccessiblePreviewCellTextData(mpViewShell, maCellAddress));
305 		::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessiblePreviewCellTextData));
306 
307         mpTextHelper = new ::accessibility::AccessibleTextHelper( pEditSource );
308         mpTextHelper->SetEventSource( this );
309 
310         // #111635# paragraphs in preview are transient
311         ::accessibility::AccessibleTextHelper::VectorOfStates aChildStates;
312         aChildStates.push_back( AccessibleStateType::TRANSIENT );
313         mpTextHelper->SetAdditionalChildStates( aChildStates );
314 	}
315 }
316 
317