blob: 6b6fb54992f5937f08ec0cd93ca382e24a057e5e [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "precompiled_sd.hxx"
#include "AccessibleSlideSorterView.hxx"
#include "AccessibleSlideSorterObject.hxx"
#include "SlideSorter.hxx"
#include "controller/SlideSorterController.hxx"
#include "controller/SlsPageSelector.hxx"
#include "controller/SlsFocusManager.hxx"
#include "controller/SlsSelectionManager.hxx"
#include "view/SlideSorterView.hxx"
#include "model/SlideSorterModel.hxx"
#include "model/SlsPageDescriptor.hxx"
#include "SlideSorterViewShell.hxx"
#include "ViewShellHint.hxx"
#include "sdpage.hxx"
#include "drawdoc.hxx"
#include "sdresid.hxx"
#include "accessibility.hrc"
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <comphelper/accessibleeventnotifier.hxx>
#include <unotools/accessiblestatesethelper.hxx>
#include <rtl/ref.hxx>
#include <vcl/svapp.hxx>
using ::rtl::OUString;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::accessibility;
namespace accessibility {
/** Inner implementation class of the AccessibleSlideSorterView.
Note that some event broadcasting is done asynchronously because
otherwise it could lead to deadlocks on (at least) some Solaris
machines. Probably (but unverified) this can happen on all GTK based
systems. The asynchronous broadcasting is just a workaround for a
poorly understood problem.
*/
class AccessibleSlideSorterView::Implementation
: public SfxListener
{
public:
Implementation (
AccessibleSlideSorterView& rAccessibleSlideSorter,
::sd::slidesorter::SlideSorter& rSlideSorter,
::Window* pWindow);
~Implementation (void);
void RequestUpdateChildren (void);
void Clear (void);
sal_Int32 GetVisibleChildCount (void) const;
AccessibleSlideSorterObject* GetAccessibleChild (sal_Int32 nIndex);
AccessibleSlideSorterObject* GetVisibleChild (sal_Int32 nIndex);
void ConnectListeners (void);
void ReleaseListeners (void);
void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint);
DECL_LINK(WindowEventListener, VclWindowEvent*);
DECL_LINK(SelectionChangeListener, void*);
DECL_LINK(BroadcastSelectionChange, void*);
DECL_LINK(FocusChangeListener, void*);
DECL_LINK(UpdateChildrenCallback, void*);
void Activated(void);
private:
AccessibleSlideSorterView& mrAccessibleSlideSorter;
::sd::slidesorter::SlideSorter& mrSlideSorter;
typedef ::std::vector<rtl::Reference<AccessibleSlideSorterObject> > PageObjectList;
PageObjectList maPageObjects;
sal_Int32 mnFirstVisibleChild;
sal_Int32 mnLastVisibleChild;
bool mbListeningToDocument;
::Window* mpWindow;
sal_Int32 mnFocusedIndex;
bool mbModelChangeLocked;
sal_uLong mnUpdateChildrenUserEventId;
sal_uLong mnSelectionChangeUserEventId;
void UpdateChildren (void);
};
//===== AccessibleSlideSorterView =============================================
AccessibleSlideSorterView::AccessibleSlideSorterView(
::sd::slidesorter::SlideSorter& rSlideSorter,
const Reference<XAccessible>& rxParent,
::Window* pContentWindow)
: AccessibleSlideSorterViewBase(MutexOwner::maMutex),
mpImpl(new Implementation(*this,rSlideSorter,pContentWindow)),
mrSlideSorter(rSlideSorter),
mxParent(rxParent),
mnClientId(0),
mpContentWindow(pContentWindow)
{
}
AccessibleSlideSorterView::~AccessibleSlideSorterView (void)
{
Destroyed ();
}
void AccessibleSlideSorterView::FireAccessibleEvent (
short nEventId,
const uno::Any& rOldValue,
const uno::Any& rNewValue )
{
if (mnClientId != 0)
{
AccessibleEventObject aEventObject;
aEventObject.Source = Reference<XWeak>(this);
aEventObject.EventId = nEventId;
aEventObject.NewValue = rNewValue;
aEventObject.OldValue = rOldValue;
comphelper::AccessibleEventNotifier::addEvent (mnClientId, aEventObject);
}
}
void SAL_CALL AccessibleSlideSorterView::disposing (void)
{
if (mnClientId != 0)
{
comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
mnClientId = 0;
}
mpImpl.reset();
}
AccessibleSlideSorterObject* AccessibleSlideSorterView::GetAccessibleChildImplementation (
sal_Int32 nIndex)
{
AccessibleSlideSorterObject* pResult = NULL;
::osl::MutexGuard aGuard (maMutex);
if (nIndex>=0 && nIndex<mpImpl->GetVisibleChildCount())
pResult = mpImpl->GetVisibleChild(nIndex);
return pResult;
}
void AccessibleSlideSorterView::Destroyed (void)
{
::osl::MutexGuard aGuard (maMutex);
// Send a disposing to all listeners.
if (mnClientId != 0)
{
comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
mnClientId = 0;
}
}
//===== XAccessible =========================================================
Reference<XAccessibleContext > SAL_CALL
AccessibleSlideSorterView::getAccessibleContext (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed ();
return this;
}
//===== XAccessibleContext ==================================================
sal_Int32 SAL_CALL AccessibleSlideSorterView::getAccessibleChildCount (void)
throw (RuntimeException)
{
ThrowIfDisposed();
::osl::MutexGuard aGuard (maMutex);
return mpImpl->GetVisibleChildCount();
}
Reference<XAccessible > SAL_CALL
AccessibleSlideSorterView::getAccessibleChild (sal_Int32 nIndex)
throw (lang::IndexOutOfBoundsException, RuntimeException)
{
ThrowIfDisposed();
::osl::MutexGuard aGuard (maMutex);
if (nIndex<0 || nIndex>=mpImpl->GetVisibleChildCount())
throw lang::IndexOutOfBoundsException();
return mpImpl->GetVisibleChild(nIndex);
}
Reference<XAccessible > SAL_CALL AccessibleSlideSorterView::getAccessibleParent (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed();
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
Reference<XAccessible> xParent;
if (mpContentWindow != NULL)
{
::Window* pParent = mpContentWindow->GetAccessibleParentWindow();
if (pParent != NULL)
xParent = pParent->GetAccessible();
}
return xParent;
}
sal_Int32 SAL_CALL AccessibleSlideSorterView::getAccessibleIndexInParent (void)
throw (uno::RuntimeException)
{
OSL_ASSERT(getAccessibleParent().is());
ThrowIfDisposed();
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
sal_Int32 nIndexInParent(-1);
Reference<XAccessibleContext> xParentContext (getAccessibleParent()->getAccessibleContext());
if (xParentContext.is())
{
sal_Int32 nChildCount (xParentContext->getAccessibleChildCount());
for (sal_Int32 i=0; i<nChildCount; ++i)
if (xParentContext->getAccessibleChild(i).get()
== static_cast<XAccessible*>(this))
{
nIndexInParent = i;
break;
}
}
return nIndexInParent;
}
sal_Int16 SAL_CALL AccessibleSlideSorterView::getAccessibleRole (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed();
static sal_Int16 nRole = AccessibleRole::DOCUMENT;
return nRole;
}
::rtl::OUString SAL_CALL AccessibleSlideSorterView::getAccessibleDescription (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed();
::vos::OGuard aGuard (Application::GetSolarMutex());
return String(SdResId(SID_SD_A11Y_I_SLIDEVIEW_D));
}
::rtl::OUString SAL_CALL AccessibleSlideSorterView::getAccessibleName (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed();
::vos::OGuard aGuard (Application::GetSolarMutex());
return String(SdResId(SID_SD_A11Y_I_SLIDEVIEW_N));
}
Reference<XAccessibleRelationSet> SAL_CALL
AccessibleSlideSorterView::getAccessibleRelationSet (void)
throw (uno::RuntimeException)
{
return Reference<XAccessibleRelationSet>();
}
Reference<XAccessibleStateSet > SAL_CALL
AccessibleSlideSorterView::getAccessibleStateSet (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed();
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper();
pStateSet->AddState(AccessibleStateType::FOCUSABLE);
pStateSet->AddState(AccessibleStateType::SELECTABLE);
pStateSet->AddState(AccessibleStateType::ENABLED);
pStateSet->AddState(AccessibleStateType::ACTIVE);
pStateSet->AddState(AccessibleStateType::MULTI_SELECTABLE);
pStateSet->AddState(AccessibleStateType::OPAQUE);
if (mpContentWindow!=NULL)
{
if (mpContentWindow->IsVisible())
pStateSet->AddState(AccessibleStateType::VISIBLE);
if (mpContentWindow->IsReallyVisible())
pStateSet->AddState(AccessibleStateType::SHOWING);
}
return pStateSet;
}
lang::Locale SAL_CALL AccessibleSlideSorterView::getLocale (void)
throw (IllegalAccessibleComponentStateException,
RuntimeException)
{
ThrowIfDisposed ();
Reference<XAccessibleContext> xParentContext;
Reference<XAccessible> xParent (getAccessibleParent());
if (xParent.is())
xParentContext = xParent->getAccessibleContext();
if (xParentContext.is())
return xParentContext->getLocale();
else
// Strange, no parent! Anyway, return the default locale.
return Application::GetSettings().GetLocale();
}
void SAL_CALL AccessibleSlideSorterView::addEventListener(
const Reference<XAccessibleEventListener >& rxListener)
throw (RuntimeException)
{
if (rxListener.is())
{
const osl::MutexGuard aGuard(maMutex);
if (IsDisposed())
{
uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY);
rxListener->disposing (lang::EventObject (x));
}
else
{
if ( ! mnClientId)
mnClientId = comphelper::AccessibleEventNotifier::registerClient();
comphelper::AccessibleEventNotifier::addEventListener(mnClientId, rxListener);
}
}
}
void SAL_CALL AccessibleSlideSorterView::removeEventListener(
const Reference<XAccessibleEventListener >& rxListener)
throw (RuntimeException)
{
ThrowIfDisposed();
if (rxListener.is())
{
const osl::MutexGuard aGuard(maMutex);
if (mnClientId != 0)
{
sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener(
mnClientId, rxListener );
if ( !nListenerCount )
{
// no listeners anymore -> revoke ourself. This may lead to
// the notifier thread dying (if we were the last client),
// and at least to us not firing any events anymore, in case
// somebody calls NotifyAccessibleEvent, again
comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
mnClientId = 0;
}
}
}
}
//===== XAccessibleComponent ==================================================
sal_Bool SAL_CALL AccessibleSlideSorterView::containsPoint (const awt::Point& aPoint)
throw (RuntimeException)
{
ThrowIfDisposed();
const awt::Rectangle aBBox (getBounds());
return (aPoint.X >= 0)
&& (aPoint.X < aBBox.Width)
&& (aPoint.Y >= 0)
&& (aPoint.Y < aBBox.Height);
}
Reference<XAccessible> SAL_CALL
AccessibleSlideSorterView::getAccessibleAtPoint (const awt::Point& aPoint)
throw (RuntimeException)
{
ThrowIfDisposed();
Reference<XAccessible> xAccessible;
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
const Point aTestPoint (aPoint.X, aPoint.Y);
::sd::slidesorter::model::SharedPageDescriptor pHitDescriptor (
mrSlideSorter.GetController().GetPageAt(aTestPoint));
if (pHitDescriptor.get() != NULL)
xAccessible = mpImpl->GetAccessibleChild(
(pHitDescriptor->GetPage()->GetPageNum()-1)/2);
return xAccessible;
}
awt::Rectangle SAL_CALL AccessibleSlideSorterView::getBounds (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed();
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
awt::Rectangle aBBox;
if (mpContentWindow != NULL)
{
const Point aPosition (mpContentWindow->GetPosPixel());
const Size aSize (mpContentWindow->GetOutputSizePixel());
aBBox.X = aPosition.X();
aBBox.Y = aPosition.Y();
aBBox.Width = aSize.Width();
aBBox.Height = aSize.Height();
}
return aBBox;
}
awt::Point SAL_CALL AccessibleSlideSorterView::getLocation (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed();
awt::Point aLocation;
if (mpContentWindow != NULL)
{
const Point aPosition (mpContentWindow->GetPosPixel());
aLocation.X = aPosition.X();
aLocation.Y = aPosition.Y();
}
return aLocation;
}
/** Calculate the location on screen from the parent's location on screen
and our own relative location.
*/
awt::Point SAL_CALL AccessibleSlideSorterView::getLocationOnScreen()
throw (uno::RuntimeException)
{
ThrowIfDisposed();
const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
awt::Point aParentLocationOnScreen;
Reference<XAccessible> xParent (getAccessibleParent());
if (xParent.is())
{
Reference<XAccessibleComponent> xParentComponent (
xParent->getAccessibleContext(), uno::UNO_QUERY);
if (xParentComponent.is())
aParentLocationOnScreen = xParentComponent->getLocationOnScreen();
}
awt::Point aLocationOnScreen (getLocation());
aLocationOnScreen.X += aParentLocationOnScreen.X;
aLocationOnScreen.Y += aParentLocationOnScreen.Y;
return aLocationOnScreen;
}
awt::Size SAL_CALL AccessibleSlideSorterView::getSize (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed();
awt::Size aSize;
if (mpContentWindow != NULL)
{
const Size aOutputSize (mpContentWindow->GetOutputSizePixel());
aSize.Width = aOutputSize.Width();
aSize.Height = aOutputSize.Height();
}
return aSize;
}
void SAL_CALL AccessibleSlideSorterView::grabFocus (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed();
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
if (mpContentWindow)
mpContentWindow->GrabFocus();
}
sal_Int32 SAL_CALL AccessibleSlideSorterView::getForeground (void)
throw (RuntimeException)
{
ThrowIfDisposed();
svtools::ColorConfig aColorConfig;
sal_uInt32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
return static_cast<sal_Int32>(nColor);
}
sal_Int32 SAL_CALL AccessibleSlideSorterView::getBackground (void)
throw (RuntimeException)
{
ThrowIfDisposed();
sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
return static_cast<sal_Int32>(nColor);
}
//===== XAccessibleSelection ==================================================
void SAL_CALL AccessibleSlideSorterView::selectAccessibleChild (sal_Int32 nChildIndex)
throw (lang::IndexOutOfBoundsException,
RuntimeException)
{
ThrowIfDisposed();
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
if (pChild != NULL)
mrSlideSorter.GetController().GetPageSelector().SelectPage(pChild->GetPageNumber());
else
throw lang::IndexOutOfBoundsException();
}
sal_Bool SAL_CALL AccessibleSlideSorterView::isAccessibleChildSelected (sal_Int32 nChildIndex)
throw (lang::IndexOutOfBoundsException,
RuntimeException)
{
ThrowIfDisposed();
sal_Bool bIsSelected = sal_False;
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
if (pChild != NULL)
bIsSelected = mrSlideSorter.GetController().GetPageSelector().IsPageSelected(
pChild->GetPageNumber());
else
throw lang::IndexOutOfBoundsException();
return bIsSelected;
}
void SAL_CALL AccessibleSlideSorterView::clearAccessibleSelection (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed();
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
mrSlideSorter.GetController().GetPageSelector().DeselectAllPages();
}
void SAL_CALL AccessibleSlideSorterView::selectAllAccessibleChildren (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed();
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
mrSlideSorter.GetController().GetPageSelector().SelectAllPages();
}
sal_Int32 SAL_CALL AccessibleSlideSorterView::getSelectedAccessibleChildCount (void)
throw (uno::RuntimeException)
{
ThrowIfDisposed ();
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
return mrSlideSorter.GetController().GetPageSelector().GetSelectedPageCount();
}
Reference<XAccessible > SAL_CALL
AccessibleSlideSorterView::getSelectedAccessibleChild (sal_Int32 nSelectedChildIndex )
throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
{
ThrowIfDisposed ();
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
Reference<XAccessible> xChild;
::sd::slidesorter::controller::PageSelector& rSelector (
mrSlideSorter.GetController().GetPageSelector());
sal_Int32 nPageCount(rSelector.GetPageCount());
sal_Int32 nSelectedCount = 0;
for (sal_Int32 i=0; i<nPageCount; i++)
if (rSelector.IsPageSelected(i))
{
if (nSelectedCount == nSelectedChildIndex)
{
xChild = mpImpl->GetAccessibleChild(i);
break;
}
++nSelectedCount;
}
if ( ! xChild.is() )
throw lang::IndexOutOfBoundsException();
return xChild;
}
void SAL_CALL AccessibleSlideSorterView::deselectAccessibleChild (sal_Int32 nChildIndex)
throw (lang::IndexOutOfBoundsException,
RuntimeException)
{
ThrowIfDisposed();
const vos::OGuard aSolarGuard (Application::GetSolarMutex());
AccessibleSlideSorterObject* pChild = mpImpl->GetAccessibleChild(nChildIndex);
if (pChild != NULL)
mrSlideSorter.GetController().GetPageSelector().DeselectPage(pChild->GetPageNumber());
else
throw lang::IndexOutOfBoundsException();
}
//===== XServiceInfo ========================================================
::rtl::OUString SAL_CALL
AccessibleSlideSorterView::getImplementationName (void)
throw (::com::sun::star::uno::RuntimeException)
{
return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleSlideSorterView"));
}
sal_Bool SAL_CALL
AccessibleSlideSorterView::supportsService (const OUString& sServiceName)
throw (::com::sun::star::uno::RuntimeException)
{
ThrowIfDisposed ();
// Iterate over all supported service names and return true if on of them
// matches the given name.
uno::Sequence< ::rtl::OUString> aSupportedServices (
getSupportedServiceNames ());
for (int i=0; i<aSupportedServices.getLength(); i++)
if (sServiceName == aSupportedServices[i])
return sal_True;
return sal_False;
}
uno::Sequence< ::rtl::OUString> SAL_CALL
AccessibleSlideSorterView::getSupportedServiceNames (void)
throw (::com::sun::star::uno::RuntimeException)
{
ThrowIfDisposed ();
static const OUString sServiceNames[3] = {
OUString(RTL_CONSTASCII_USTRINGPARAM(
"com.sun.star.accessibility.Accessible")),
OUString(RTL_CONSTASCII_USTRINGPARAM(
"com.sun.star.accessibility.AccessibleContext")),
OUString(RTL_CONSTASCII_USTRINGPARAM(
"com.sun.star.drawing.AccessibleSlideSorterView"))
};
return uno::Sequence<OUString> (sServiceNames, 3);
}
void AccessibleSlideSorterView::ThrowIfDisposed (void)
throw (lang::DisposedException)
{
if (rBHelper.bDisposed || rBHelper.bInDispose)
{
OSL_TRACE ("Calling disposed object. Throwing exception:");
throw lang::DisposedException (
OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")),
static_cast<uno::XWeak*>(this));
}
}
sal_Bool AccessibleSlideSorterView::IsDisposed (void)
{
return (rBHelper.bDisposed || rBHelper.bInDispose);
}
//===== AccessibleSlideSorterView::Implementation =============================
AccessibleSlideSorterView::Implementation::Implementation (
AccessibleSlideSorterView& rAccessibleSlideSorter,
::sd::slidesorter::SlideSorter& rSlideSorter,
::Window* pWindow)
: mrAccessibleSlideSorter(rAccessibleSlideSorter),
mrSlideSorter(rSlideSorter),
maPageObjects(),
mnFirstVisibleChild(0),
mnLastVisibleChild(-1),
mbListeningToDocument(false),
mpWindow(pWindow),
mnFocusedIndex(-1),
mbModelChangeLocked(false),
mnUpdateChildrenUserEventId(0),
mnSelectionChangeUserEventId(0)
{
ConnectListeners();
UpdateChildren();
}
AccessibleSlideSorterView::Implementation::~Implementation (void)
{
if (mnUpdateChildrenUserEventId != 0)
Application::RemoveUserEvent(mnUpdateChildrenUserEventId);
if (mnSelectionChangeUserEventId != 0)
Application::RemoveUserEvent(mnSelectionChangeUserEventId);
ReleaseListeners();
Clear();
}
void AccessibleSlideSorterView::Implementation::RequestUpdateChildren (void)
{
if (mnUpdateChildrenUserEventId == 0)
mnUpdateChildrenUserEventId = Application::PostUserEvent(
LINK(this, AccessibleSlideSorterView::Implementation,
UpdateChildrenCallback));
}
void AccessibleSlideSorterView::Implementation::UpdateChildren (void)
{
//By default, all children should be accessable. So here workaround is to make all children visible.
// MT: THis was in UpdateVisibility, which has some similarity, and hg merge automatically has put it here. Correct?!
// In the IA2 CWS, also setting mnFirst/LastVisibleChild was commented out!
mnLastVisibleChild = maPageObjects.size();
if (mbModelChangeLocked)
{
// Do nothing right now. When the flag is reset, this method is
// called again.
return;
}
const Pair aRange (mrSlideSorter.GetView().GetVisiblePageRange());
mnFirstVisibleChild = aRange.A();
mnLastVisibleChild = aRange.B();
// Release all children.
Clear();
// Create new children for the modified visible range.
maPageObjects.resize(mrSlideSorter.GetModel().GetPageCount());
for (sal_Int32 nIndex(mnFirstVisibleChild); nIndex<=mnLastVisibleChild; ++nIndex)
GetAccessibleChild(nIndex);
}
void AccessibleSlideSorterView::Implementation::Clear (void)
{
PageObjectList::iterator iPageObject;
PageObjectList::iterator iEnd = maPageObjects.end();
for (iPageObject=maPageObjects.begin(); iPageObject!=iEnd; ++iPageObject)
if (*iPageObject != NULL)
{
mrAccessibleSlideSorter.FireAccessibleEvent(
AccessibleEventId::CHILD,
Any(Reference<XAccessible>(iPageObject->get())),
Any());
Reference<XComponent> xComponent (Reference<XWeak>(iPageObject->get()), UNO_QUERY);
if (xComponent.is())
xComponent->dispose();
*iPageObject = NULL;
}
maPageObjects.clear();
}
sal_Int32 AccessibleSlideSorterView::Implementation::GetVisibleChildCount (void) const
{
if (mnFirstVisibleChild<=mnLastVisibleChild && mnFirstVisibleChild>=0)
return mnLastVisibleChild - mnFirstVisibleChild + 1;
else
return 0;
}
AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetVisibleChild (
sal_Int32 nIndex)
{
assert(nIndex>=0 && nIndex<GetVisibleChildCount());
return GetAccessibleChild(nIndex+mnFirstVisibleChild);
}
AccessibleSlideSorterObject* AccessibleSlideSorterView::Implementation::GetAccessibleChild (
sal_Int32 nIndex)
{
AccessibleSlideSorterObject* pChild = NULL;
if (nIndex>=0 && (sal_uInt32)nIndex<maPageObjects.size())
{
if (maPageObjects[nIndex] == NULL)
{
::sd::slidesorter::model::SharedPageDescriptor pDescriptor(
mrSlideSorter.GetModel().GetPageDescriptor(nIndex));
if (pDescriptor.get() != NULL)
{
maPageObjects[nIndex] = new AccessibleSlideSorterObject(
&mrAccessibleSlideSorter,
mrSlideSorter,
(pDescriptor->GetPage()->GetPageNum()-1)/2);
mrAccessibleSlideSorter.FireAccessibleEvent(
AccessibleEventId::CHILD,
Any(),
Any(Reference<XAccessible>(maPageObjects[nIndex].get())));
}
}
pChild = maPageObjects[nIndex].get();
}
else
{
OSL_ASSERT(nIndex>=0 && (sal_uInt32)nIndex<maPageObjects.size());
}
return pChild;
}
void AccessibleSlideSorterView::Implementation::ConnectListeners (void)
{
StartListening (*mrSlideSorter.GetModel().GetDocument());
if (mrSlideSorter.GetViewShell() != NULL)
StartListening (*mrSlideSorter.GetViewShell());
mbListeningToDocument = true;
if (mpWindow != NULL)
mpWindow->AddEventListener(
LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener));
mrSlideSorter.GetController().GetSelectionManager()->AddSelectionChangeListener(
LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener));
mrSlideSorter.GetController().GetFocusManager().AddFocusChangeListener(
LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener));
mrSlideSorter.GetView().AddVisibilityChangeListener(
LINK(this,AccessibleSlideSorterView::Implementation,UpdateChildrenCallback));
}
void AccessibleSlideSorterView::Implementation::ReleaseListeners (void)
{
mrSlideSorter.GetController().GetFocusManager().RemoveFocusChangeListener(
LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener));
mrSlideSorter.GetController().GetSelectionManager()->RemoveSelectionChangeListener(
LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener));
mrSlideSorter.GetView().RemoveVisibilityChangeListener(
LINK(this,AccessibleSlideSorterView::Implementation,UpdateChildrenCallback));
if (mpWindow != NULL)
mpWindow->RemoveEventListener(
LINK(this,AccessibleSlideSorterView::Implementation,WindowEventListener));
if (mbListeningToDocument)
{
if (mrSlideSorter.GetViewShell() != NULL)
StartListening(*mrSlideSorter.GetViewShell());
EndListening (*mrSlideSorter.GetModel().GetDocument());
mbListeningToDocument = false;
}
}
void AccessibleSlideSorterView::Implementation::Notify (
SfxBroadcaster&,
const SfxHint& rHint)
{
if (rHint.ISA(SdrHint))
{
SdrHint& rSdrHint (*PTR_CAST(SdrHint,&rHint));
switch (rSdrHint.GetKind())
{
case HINT_PAGEORDERCHG:
RequestUpdateChildren();
break;
default:
break;
}
}
else if (rHint.ISA(sd::ViewShellHint))
{
sd::ViewShellHint& rViewShellHint (*PTR_CAST(sd::ViewShellHint, &rHint));
switch (rViewShellHint.GetHintId())
{
case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_START:
mbModelChangeLocked = true;
break;
case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END:
mbModelChangeLocked = false;
RequestUpdateChildren();
break;
default:
break;
}
}
}
void AccessibleSlideSorterView::SwitchViewActivated (void)
{
// Firstly, set focus to view
this->FireAccessibleEvent(AccessibleEventId::STATE_CHANGED,
Any(),
Any(AccessibleStateType::FOCUSED));
mpImpl->Activated();
}
void AccessibleSlideSorterView::Implementation::Activated()
{
mrSlideSorter.GetController().GetFocusManager().ShowFocus();
}
IMPL_LINK(AccessibleSlideSorterView::Implementation, WindowEventListener, VclWindowEvent*, pEvent)
{
switch (pEvent->GetId())
{
case VCLEVENT_WINDOW_MOVE:
case VCLEVENT_WINDOW_RESIZE:
RequestUpdateChildren();
break;
case VCLEVENT_WINDOW_GETFOCUS:
case VCLEVENT_WINDOW_LOSEFOCUS:
mrAccessibleSlideSorter.FireAccessibleEvent(
AccessibleEventId::SELECTION_CHANGED,
Any(),
Any());
break;
default:
break;
}
return 1;
}
IMPL_LINK(AccessibleSlideSorterView::Implementation, SelectionChangeListener, void*, EMPTYARG )
{
if (mnSelectionChangeUserEventId == 0)
mnSelectionChangeUserEventId = Application::PostUserEvent(
LINK(this, AccessibleSlideSorterView::Implementation, BroadcastSelectionChange));
return 1;
}
IMPL_LINK(AccessibleSlideSorterView::Implementation, BroadcastSelectionChange, void*, EMPTYARG )
{
mnSelectionChangeUserEventId = 0;
mrAccessibleSlideSorter.FireAccessibleEvent(
AccessibleEventId::SELECTION_CHANGED,
Any(),
Any());
return 1;
}
IMPL_LINK(AccessibleSlideSorterView::Implementation, FocusChangeListener, void*, EMPTYARG )
{
sal_Int32 nNewFocusedIndex (
mrSlideSorter.GetController().GetFocusManager().GetFocusedPageIndex());
sal_Bool bHasFocus = mrSlideSorter.GetController().GetFocusManager().IsFocusShowing();
if (!bHasFocus)
nNewFocusedIndex = -1;
// add a checker whether the focus event is sent out. Only after sent, the mnFocusedIndex should be updated.
sal_Bool bSentFocus = sal_False;
if (nNewFocusedIndex != mnFocusedIndex)
{
if (mnFocusedIndex >= 0)
{
AccessibleSlideSorterObject* pObject = GetAccessibleChild(mnFocusedIndex);
if (pObject != NULL)
{
pObject->FireAccessibleEvent(
AccessibleEventId::STATE_CHANGED,
Any(AccessibleStateType::FOCUSED),
Any());
bSentFocus = sal_True;
}
}
if (nNewFocusedIndex >= 0)
{
AccessibleSlideSorterObject* pObject = GetAccessibleChild(nNewFocusedIndex);
if (pObject != NULL)
{
pObject->FireAccessibleEvent(
AccessibleEventId::STATE_CHANGED,
Any(),
Any(AccessibleStateType::FOCUSED));
bSentFocus = sal_True;
}
}
if (bSentFocus == sal_True)
mnFocusedIndex = nNewFocusedIndex;
}
return 1;
}
IMPL_LINK(AccessibleSlideSorterView::Implementation, UpdateChildrenCallback, void*, EMPTYARG )
{
mnUpdateChildrenUserEventId = 0;
UpdateChildren();
return 1;
}
} // end of namespace ::accessibility