merge the formfield patch from ooo-build
[ooovba.git] / sc / source / ui / Accessibility / AccessiblePageHeader.cxx
blobb47a2401282f8b1bdd0762199306228b999f8942
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: AccessiblePageHeader.cxx,v $
10 * $Revision: 1.22 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include "AccessiblePageHeader.hxx"
35 #include "AccessiblePageHeaderArea.hxx"
36 #include "AccessibilityHints.hxx"
37 #include "prevwsh.hxx"
38 #include "unoguard.hxx"
39 #include "miscuno.hxx"
40 #include "prevloc.hxx"
41 #include "document.hxx"
42 #include "stlpool.hxx"
43 #include "scitems.hxx"
44 #include "attrib.hxx"
45 #include "scresid.hxx"
46 #ifndef SC_SC_HRC
47 #include "sc.hrc"
48 #endif
50 #include <com/sun/star/accessibility/AccessibleRole.hpp>
51 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
52 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
54 #include <vcl/window.hxx>
55 #include <svtools/smplhint.hxx>
56 #include <unotools/accessiblestatesethelper.hxx>
57 #include <svtools/style.hxx>
58 #include <svtools/itempool.hxx>
59 #include <svx/editobj.hxx>
60 #include <toolkit/helper/convert.hxx>
62 #include <algorithm>
64 using namespace ::com::sun::star;
65 using namespace ::com::sun::star::accessibility;
67 const sal_uInt8 MAX_AREAS = 3;
69 //===== internal ============================================================
70 struct Acquire
72 void operator() (ScAccessiblePageHeaderArea* pArea)
74 if (pArea)
75 pArea->acquire();
79 struct Release
81 void operator() (ScAccessiblePageHeaderArea*& pArea)
83 if (pArea)
84 pArea->release();
88 struct Dispose
90 void operator() (ScAccessiblePageHeaderArea*& pArea)
92 if (pArea)
94 pArea->dispose();
95 pArea->release();
97 pArea = NULL;
101 ScAccessiblePageHeader::ScAccessiblePageHeader( const ::com::sun::star::uno::Reference<
102 ::com::sun::star::accessibility::XAccessible>& rxParent,
103 ScPreviewShell* pViewShell, sal_Bool bHeader, sal_Int32 nIndex ) :
104 ScAccessibleContextBase( rxParent, bHeader ? AccessibleRole::HEADER : AccessibleRole::FOOTER ),
105 mpViewShell( pViewShell ),
106 mnIndex( nIndex ),
107 mbHeader( bHeader ),
108 maAreas(MAX_AREAS, NULL),
109 mnChildCount(-1)
111 if (mpViewShell)
112 mpViewShell->AddAccessibilityObject(*this);
115 ScAccessiblePageHeader::~ScAccessiblePageHeader()
117 if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
119 // increment refcount to prevent double call off dtor
120 osl_incrementInterlockedCount( &m_refCount );
121 dispose();
125 void SAL_CALL ScAccessiblePageHeader::disposing()
127 ScUnoGuard aGuard;
128 if (mpViewShell)
130 mpViewShell->RemoveAccessibilityObject(*this);
131 mpViewShell = NULL;
133 std::for_each(maAreas.begin(), maAreas.end(), Dispose());
135 ScAccessibleContextBase::disposing();
138 //===== SfxListener =====================================================
140 void ScAccessiblePageHeader::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
142 if (rHint.ISA( SfxSimpleHint ) )
144 const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
145 // only notify if child exist, otherwise it is not necessary
146 if ((rRef.GetId() == SC_HINT_DATACHANGED))
148 ScHFAreas aOldAreas(maAreas);
149 std::for_each(aOldAreas.begin(), aOldAreas.end(), Acquire());
150 mnChildCount = -1;
151 getAccessibleChildCount();
152 for (sal_uInt8 i = 0; i < MAX_AREAS; ++i)
154 if ((aOldAreas[i] && maAreas[i] && !ScGlobal::EETextObjEqual(aOldAreas[i]->GetEditTextObject(), maAreas[i]->GetEditTextObject())) ||
155 (aOldAreas[i] && !maAreas[i]) || (!aOldAreas[i] && maAreas[i]))
157 if (aOldAreas[i] && aOldAreas[i]->GetEditTextObject())
159 AccessibleEventObject aEvent;
160 aEvent.EventId = AccessibleEventId::CHILD;
161 aEvent.Source = uno::Reference< XAccessibleContext >(this);
162 aEvent.OldValue = uno::makeAny(uno::Reference<XAccessible>(aOldAreas[i]));
164 CommitChange(aEvent); // child gone - event
165 aOldAreas[i]->dispose();
167 if (maAreas[i] && maAreas[i]->GetEditTextObject())
169 AccessibleEventObject aEvent;
170 aEvent.EventId = AccessibleEventId::CHILD;
171 aEvent.Source = uno::Reference< XAccessibleContext >(this);
172 aEvent.NewValue = uno::makeAny(uno::Reference<XAccessible>(maAreas[i]));
174 CommitChange(aEvent); // new child - event
178 std::for_each(aOldAreas.begin(), aOldAreas.end(), Release());
180 else if (rRef.GetId() == SC_HINT_ACC_VISAREACHANGED)
182 AccessibleEventObject aEvent;
183 aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
184 aEvent.Source = uno::Reference< XAccessibleContext >(this);
185 CommitChange(aEvent);
189 ScAccessibleContextBase::Notify(rBC, rHint);
192 //===== XAccessibleComponent ============================================
194 uno::Reference< XAccessible > SAL_CALL ScAccessiblePageHeader::getAccessibleAtPoint( const awt::Point& aPoint )
195 throw (uno::RuntimeException)
197 uno::Reference<XAccessible> xRet;
199 if (containsPoint(aPoint))
201 ScUnoGuard aGuard;
202 IsObjectValid();
204 sal_Int32 nCount(getAccessibleChildCount()); // fill the areas
206 if (nCount)
208 // return the first with content, because they have all the same Bounding Box
209 sal_uInt8 i(0);
210 while(!xRet.is() && i < MAX_AREAS)
212 if (maAreas[i])
213 xRet = maAreas[i];
214 else
215 ++i;
220 return xRet;
223 void SAL_CALL ScAccessiblePageHeader::grabFocus() throw (uno::RuntimeException)
225 ScUnoGuard aGuard;
226 IsObjectValid();
227 if (getAccessibleParent().is())
229 uno::Reference<XAccessibleComponent> xAccessibleComponent(getAccessibleParent()->getAccessibleContext(), uno::UNO_QUERY);
230 if (xAccessibleComponent.is())
231 xAccessibleComponent->grabFocus();
235 //===== XAccessibleContext ==============================================
237 sal_Int32 SAL_CALL ScAccessiblePageHeader::getAccessibleChildCount() throw (uno::RuntimeException)
239 ScUnoGuard aGuard;
240 IsObjectValid();
242 if((mnChildCount < 0) && mpViewShell)
244 mnChildCount = 0;
245 ScDocument* pDoc = mpViewShell->GetDocument();
246 if (pDoc)
248 // find out how many regions (left,center, right) are with content
250 SfxStyleSheetBase* pStyle = pDoc->GetStyleSheetPool()->Find(pDoc->GetPageStyle(mpViewShell->GetLocationData().GetPrintTab()), SFX_STYLE_FAMILY_PAGE);
251 if (pStyle)
253 sal_uInt16 nPageWhichId(0);
254 if (mbHeader)
255 nPageWhichId = mpViewShell->GetLocationData().IsHeaderLeft() ? ATTR_PAGE_HEADERLEFT : ATTR_PAGE_HEADERRIGHT;
256 else
257 nPageWhichId = mpViewShell->GetLocationData().IsFooterLeft() ? ATTR_PAGE_FOOTERLEFT : ATTR_PAGE_FOOTERRIGHT;
259 const ScPageHFItem& rPageItem = static_cast<const ScPageHFItem&>(pStyle->GetItemSet().Get(nPageWhichId));
260 AddChild(rPageItem.GetLeftArea(), 0, SVX_ADJUST_LEFT);
261 AddChild(rPageItem.GetCenterArea(), 1, SVX_ADJUST_CENTER);
262 AddChild(rPageItem.GetRightArea(), 2, SVX_ADJUST_RIGHT);
267 return mnChildCount;
270 uno::Reference< XAccessible > SAL_CALL ScAccessiblePageHeader::getAccessibleChild( sal_Int32 nIndex )
271 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
273 ScUnoGuard aGuard;
274 IsObjectValid();
276 uno::Reference<XAccessible> xRet;
278 if(mnChildCount < 0)
279 getAccessibleChildCount();
281 ScHFAreas::iterator aItr = maAreas.begin();
282 ScHFAreas::iterator aEndItr = maAreas.end();
283 while (!xRet.is() && (nIndex >= 0) && (aItr != aEndItr))
285 if (*aItr)
287 if (nIndex == 0)
288 xRet = *aItr;
289 else
290 --nIndex;
292 else
293 ++aItr;
296 if ( !xRet.is() )
297 throw lang::IndexOutOfBoundsException();
299 return xRet;
302 sal_Int32 SAL_CALL ScAccessiblePageHeader::getAccessibleIndexInParent() throw (uno::RuntimeException)
304 return mnIndex;
307 uno::Reference< XAccessibleStateSet > SAL_CALL ScAccessiblePageHeader::getAccessibleStateSet()
308 throw (uno::RuntimeException)
310 ScUnoGuard aGuard;
311 uno::Reference<XAccessibleStateSet> xParentStates;
312 if (getAccessibleParent().is())
314 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
315 xParentStates = xParentContext->getAccessibleStateSet();
317 utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
318 if (IsDefunc(xParentStates))
319 pStateSet->AddState(AccessibleStateType::DEFUNC);
320 else
322 pStateSet->AddState(AccessibleStateType::ENABLED);
323 pStateSet->AddState(AccessibleStateType::OPAQUE);
324 if (isShowing())
325 pStateSet->AddState(AccessibleStateType::SHOWING);
326 if (isVisible())
327 pStateSet->AddState(AccessibleStateType::VISIBLE);
329 return pStateSet;
332 //===== XServiceInfo ====================================================
334 rtl::OUString SAL_CALL ScAccessiblePageHeader::getImplementationName() throw(uno::RuntimeException)
336 return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ScAccessiblePageHeader"));
339 uno::Sequence<rtl::OUString> SAL_CALL ScAccessiblePageHeader::getSupportedServiceNames()
340 throw(uno::RuntimeException)
342 uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
343 sal_Int32 nOldSize(aSequence.getLength());
344 aSequence.realloc(nOldSize + 1);
345 ::rtl::OUString* pNames = aSequence.getArray();
347 pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.AccessibleHeaderFooterView"));
349 return aSequence;
352 //==== internal =========================================================
354 ::rtl::OUString SAL_CALL ScAccessiblePageHeader::createAccessibleDescription(void)
355 throw (uno::RuntimeException)
357 String sDesc(ScResId(mbHeader ? STR_ACC_HEADER_DESCR : STR_ACC_FOOTER_DESCR));
358 sDesc.SearchAndReplaceAscii("%1", String(ScResId(SCSTR_UNKNOWN)));
359 return rtl::OUString( sDesc );
362 ::rtl::OUString SAL_CALL ScAccessiblePageHeader::createAccessibleName(void)
363 throw (uno::RuntimeException)
365 String sName(ScResId(mbHeader ? STR_ACC_HEADER_NAME : STR_ACC_FOOTER_NAME));
366 sName.SearchAndReplaceAscii("%1", String(ScResId(SCSTR_UNKNOWN)));
367 return rtl::OUString( sName );
370 Rectangle ScAccessiblePageHeader::GetBoundingBoxOnScreen() const throw (uno::RuntimeException)
372 Rectangle aCellRect(GetBoundingBox());
373 if (mpViewShell)
375 Window* pWindow = mpViewShell->GetWindow();
376 if (pWindow)
378 Rectangle aRect = pWindow->GetWindowExtentsRelative(NULL);
379 aCellRect.setX(aCellRect.getX() + aRect.getX());
380 aCellRect.setY(aCellRect.getY() + aRect.getY());
383 return aCellRect;
386 Rectangle ScAccessiblePageHeader::GetBoundingBox() const throw (uno::RuntimeException)
388 Rectangle aRect;
389 if (mpViewShell)
391 const ScPreviewLocationData& rData = mpViewShell->GetLocationData();
392 if ( mbHeader )
393 rData.GetHeaderPosition( aRect );
394 else
395 rData.GetFooterPosition( aRect );
397 // the Rectangle could contain negative coordinates so it should be cliped
398 Rectangle aClipRect(Point(0, 0), aRect.GetSize());
399 Window* pWindow = mpViewShell->GetWindow();
400 if (pWindow)
401 aClipRect = pWindow->GetWindowExtentsRelative(pWindow->GetAccessibleParentWindow());
402 aRect = aClipRect.GetIntersection(aRect);
404 if (aRect.IsEmpty())
405 aRect.SetSize(Size(-1, -1));
407 return aRect;
410 sal_Bool ScAccessiblePageHeader::IsDefunc( const uno::Reference<XAccessibleStateSet>& rxParentStates )
412 return ScAccessibleContextBase::IsDefunc() || (mpViewShell == NULL) || !getAccessibleParent().is() ||
413 (rxParentStates.is() && rxParentStates->contains(AccessibleStateType::DEFUNC));
416 void ScAccessiblePageHeader::AddChild(const EditTextObject* pArea, sal_uInt32 nIndex, SvxAdjust eAdjust)
418 if (pArea && (pArea->GetText(0).Len() || (pArea->GetParagraphCount() > 1)))
420 if (maAreas[nIndex])
422 if (!ScGlobal::EETextObjEqual(maAreas[nIndex]->GetEditTextObject(), pArea))
424 maAreas[nIndex]->release();
425 maAreas[nIndex] = new ScAccessiblePageHeaderArea(this, mpViewShell, pArea, mbHeader, eAdjust);
426 maAreas[nIndex]->acquire();
429 else
431 maAreas[nIndex] = new ScAccessiblePageHeaderArea(this, mpViewShell, pArea, mbHeader, eAdjust);
432 maAreas[nIndex]->acquire();
434 ++mnChildCount;
436 else
438 if (maAreas[nIndex])
440 maAreas[nIndex]->release();
441 maAreas[nIndex] = NULL;